lsp4j updates to document symbols

This commit is contained in:
Martin Lippert
2018-08-25 20:38:04 +02:00
parent 5b94f58fb5
commit dbf72934e8
6 changed files with 48 additions and 25 deletions

View File

@@ -6,7 +6,8 @@ Bundle-Version: 4.0.0.qualifier
Require-Bundle: org.eclipse.ui,
org.eclipse.ui.workbench.texteditor,
org.eclipse.lsp4e;bundle-version="0.5.0",
org.eclipse.lsp4j;bundle-version="0.4.0",
org.eclipse.lsp4j;bundle-version="0.5.0",
org.eclipse.lsp4j.jsonrpc;bundle-version="0.5.0",
org.eclipse.jface.text;bundle-version="3.12.0",
org.eclipse.core.resources;bundle-version="3.12.0",
org.eclipse.core.filebuffers,

View File

@@ -39,6 +39,7 @@ import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.lsp4e.LSPEclipseUtils;
import org.eclipse.lsp4e.outline.SymbolsLabelProvider;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
@@ -106,7 +107,7 @@ public class GotoSymbolDialog extends PopupDialog {
boolean showKindInformation = false;
symbolsLabelProvider = new SymbolsLabelProvider(showSymbolsLabelProviderLocation , showKindInformation) {
@Override
protected int getMaxSeverity(IResource resource, SymbolInformation symbolInformation)
protected int getMaxSeverity(IResource resource, Range range)
throws CoreException, BadLocationException {
int maxSeverity = -1;
for (IMarker marker : resource.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_ZERO)) {

View File

@@ -18,7 +18,9 @@ import java.util.List;
import java.util.stream.Collectors;
import org.eclipse.core.runtime.Assert;
import org.eclipse.lsp4j.DocumentSymbol;
import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.springframework.tooling.ls.eclipse.gotosymbol.GotoSymbolPlugin;
import org.springsource.ide.eclipse.commons.core.util.FuzzyMatcher;
import org.springsource.ide.eclipse.commons.core.util.StringUtil;
@@ -46,10 +48,14 @@ public class GotoSymbolDialogModel {
}
public static Comparator<Match<SymbolInformation>> MATCH_COMPARATOR = (m1, m2) -> {
public static Comparator<Match<Either<SymbolInformation, DocumentSymbol>>> MATCH_COMPARATOR = (m1, m2) -> {
int comp = Double.compare(m2.score, m1.score);
if (comp!=0) return comp;
return m1.value.getName().compareTo(m2.value.getName());
String m1Name = m1.value.isLeft() ? m1.value.getLeft().getName() : m1.value.getRight().getName();
String m2Name = m2.value.isLeft() ? m2.value.getLeft().getName() : m2.value.getRight().getName();
return m1Name.compareTo(m2Name);
};
private static final String SEARCH_BOX_HINT_MESSAGE = "@/ -> request mappings, @+ -> beans, @> -> functions, @ -> all spring elements";
@@ -76,7 +82,7 @@ public class GotoSymbolDialogModel {
private int currentSymbolsProviderIndex;
private final LiveVariable<SymbolsProvider> currentSymbolsProvider = new LiveVariable<>(null);
private final LiveVariable<String> searchBox = new LiveVariable<>("");
private final ObservableSet<SymbolInformation> unfilteredSymbols = new ObservableSet<SymbolInformation>(ImmutableSet.of(), AsyncMode.ASYNC, AsyncMode.SYNC) {
private final ObservableSet<Either<SymbolInformation, DocumentSymbol>> unfilteredSymbols = new ObservableSet<Either<SymbolInformation, DocumentSymbol>>(ImmutableSet.of(), AsyncMode.ASYNC, AsyncMode.SYNC) {
//Note: fetching is 'slow' so is done asynchronously
{
setRefreshDelay(100);
@@ -85,7 +91,7 @@ public class GotoSymbolDialogModel {
}
@Override
protected ImmutableSet<SymbolInformation> compute() {
protected ImmutableSet<Either<SymbolInformation, DocumentSymbol>> compute() {
status.setValue("Fetching symbols...");
try {
SymbolsProvider sp = currentSymbolsProvider.getValue();
@@ -93,7 +99,7 @@ public class GotoSymbolDialogModel {
debug("Fetching "+sp.getName());
String query = searchBox.getValue();
debug("Fetching symbols... from symbol provider, for '"+query+"'");
Collection<SymbolInformation> fetched = sp.fetchFor(query);
Collection<Either<SymbolInformation, DocumentSymbol>> fetched = sp.fetchFor(query);
if (keyBindings==null) {
status.setValue(sp.getName());
} else {
@@ -116,7 +122,7 @@ public class GotoSymbolDialogModel {
}
};
private LiveExpression<Collection<Match<SymbolInformation>>> filteredSymbols = new LiveExpression<Collection<Match<SymbolInformation>>>() {
private LiveExpression<Collection<Match<Either<SymbolInformation, DocumentSymbol>>>> filteredSymbols = new LiveExpression<Collection<Match<Either<SymbolInformation, DocumentSymbol>>>>() {
//Note: filtering is 'fast' so is done synchronously
{
dependsOn(searchBox);
@@ -124,18 +130,25 @@ public class GotoSymbolDialogModel {
}
@Override
protected Collection<Match<SymbolInformation>> compute() {
protected Collection<Match<Either<SymbolInformation, DocumentSymbol>>> compute() {
String query = searchBox.getValue();
if (!StringUtil.hasText(query)) {
query = "";
}
query = query.toLowerCase();
List<Match<SymbolInformation>> matches = new ArrayList<>();
for (SymbolInformation symbol : unfilteredSymbols.getValues()) {
String name = symbol.getName().toLowerCase();
List<Match<Either<SymbolInformation, DocumentSymbol>>> matches = new ArrayList<>();
for (Either<SymbolInformation, DocumentSymbol> symbol : unfilteredSymbols.getValues()) {
String name = null;
if (symbol.isLeft()) {
name = symbol.getLeft().getName().toLowerCase();
}
else if (symbol.isRight()) {
name = symbol.getRight().getName().toLowerCase();
}
double score = FuzzyMatcher.matchScore(query, name);
if (score!=0.0) {
matches.add(new Match<SymbolInformation>(score, query, symbol));
matches.add(new Match<Either<SymbolInformation, DocumentSymbol>>(score, query, symbol));
}
}
Collections.sort(matches, MATCH_COMPARATOR);
@@ -161,11 +174,11 @@ public class GotoSymbolDialogModel {
}
}
private List<String> summary(Collection<Match<SymbolInformation>> collection) {
return collection.stream().map(match -> match.value.getName()).collect(Collectors.toList());
private List<String> summary(Collection<Match<Either<SymbolInformation, DocumentSymbol>>> collection) {
return collection.stream().map(match -> match.value.isLeft() ? match.value.getLeft().getName() : match.value.getRight().getName()).collect(Collectors.toList());
}
public LiveExpression<Collection<Match<SymbolInformation>>> getSymbols() {
public LiveExpression<Collection<Match<Either<SymbolInformation, DocumentSymbol>>>> getSymbols() {
return filteredSymbols;
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017 Pivotal, Inc.
* Copyright (c) 2017, 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
@@ -17,9 +17,11 @@ import java.util.concurrent.CompletableFuture;
import org.eclipse.lsp4e.LSPEclipseUtils;
import org.eclipse.lsp4e.LanguageServiceAccessor;
import org.eclipse.lsp4e.LanguageServiceAccessor.LSPDocumentInfo;
import org.eclipse.lsp4j.DocumentSymbol;
import org.eclipse.lsp4j.DocumentSymbolParams;
import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.ui.texteditor.ITextEditor;
import com.google.common.collect.ImmutableList;
@@ -40,12 +42,12 @@ public class InFileSymbolsProvider implements SymbolsProvider {
}
@Override
public Collection<SymbolInformation> fetchFor(String query) throws Exception {
public List<Either<SymbolInformation, DocumentSymbol>> fetchFor(String query) throws Exception {
DocumentSymbolParams params = new DocumentSymbolParams(
new TextDocumentIdentifier(info.getFileUri().toString()));
CompletableFuture<List<? extends SymbolInformation>> symbolsFuture = info.getLanguageClient()
CompletableFuture<List<Either<SymbolInformation, DocumentSymbol>>> symbolsFuture = info.getLanguageClient()
.getTextDocumentService().documentSymbol(params);
List<? extends SymbolInformation> symbols = symbolsFuture.get();
List<Either<SymbolInformation, DocumentSymbol>> symbols = symbolsFuture.get();
return symbols == null ? ImmutableList.of() : ImmutableList.copyOf(symbols);
}

View File

@@ -21,8 +21,10 @@ import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.lsp4e.LanguageServiceAccessor;
import org.eclipse.lsp4j.DocumentSymbol;
import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.lsp4j.WorkspaceSymbolParams;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.lsp4j.services.LanguageServer;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.handlers.HandlerUtil;
@@ -52,7 +54,7 @@ public class InWorkspaceSymbolsProvider implements SymbolsProvider {
}
@Override
public Collection<SymbolInformation> fetchFor(String query) throws Exception {
public List<Either<SymbolInformation, DocumentSymbol>> fetchFor(String query) throws Exception {
//TODO: if we want decent support for multiple language servers...
// consider changing SymbolsProvider api and turning the stuff in here into something producing a
// Flux<Collection<SymbolInformation>>
@@ -64,12 +66,13 @@ public class InWorkspaceSymbolsProvider implements SymbolsProvider {
// really use this with a single language server anyways.
WorkspaceSymbolParams params = new WorkspaceSymbolParams(query);
Flux<SymbolInformation> symbols = Flux.fromIterable(this.languageServers)
.flatMap(server -> Mono.fromFuture(server.getWorkspaceService().symbol(params))
Flux<Either<SymbolInformation, DocumentSymbol>> symbols = Flux.fromIterable(this.languageServers)
.flatMap(server -> Mono.fromFuture(server.getWorkspaceService().symbol(params))
.timeout(TIMEOUT)
.doOnError(e -> log(e))
.onErrorReturn(ImmutableList.of())
.flatMapMany(Flux::fromIterable)
.map(symbol -> Either.forLeft(symbol))
);
//Consider letting the Flux go out from here instead of blocking and collecting elements.
return symbols.take(MAX_RESULTS).collect(Collectors.toList()).block();

View File

@@ -10,9 +10,11 @@
*******************************************************************************/
package org.springframework.tooling.ls.eclipse.gotosymbol.dialogs;
import java.util.Collection;
import java.util.List;
import org.eclipse.lsp4j.DocumentSymbol;
import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
/**
* An SymbolsProvider can fetch symbols from a service (typically, a language server
@@ -21,7 +23,8 @@ import org.eclipse.lsp4j.SymbolInformation;
*/
public interface SymbolsProvider {
String getName();
Collection<SymbolInformation> fetchFor(String query) throws Exception;
List<Either<SymbolInformation, DocumentSymbol>> fetchFor(String query) throws Exception;
/**
* True if the symbol information is provided from a file provider (a file is the provider of the symbols). False otherwise
* @param symbol