GH-1431: compute document symbols directly instead of going through workspace symbols

This commit is contained in:
Martin Lippert
2025-02-20 14:34:27 +01:00
parent eb99148c7a
commit f92a7a5b89
11 changed files with 133 additions and 92 deletions

View File

@@ -16,10 +16,12 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -42,6 +44,7 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.DocumentSymbol;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.eclipse.lsp4j.WorkspaceSymbol;
@@ -51,6 +54,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ide.vscode.boot.index.SpringIndexToSymbolsConverter;
import org.springframework.ide.vscode.boot.index.SpringMetamodelIndex;
import org.springframework.ide.vscode.boot.index.cache.IndexCache;
import org.springframework.ide.vscode.boot.java.BootJavaLanguageServerComponents;
@@ -80,6 +84,7 @@ import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocu
import org.springframework.ide.vscode.commons.languageserver.util.SimpleWorkspaceService;
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
import org.springframework.ide.vscode.commons.protocol.spring.BeansParams;
import org.springframework.ide.vscode.commons.protocol.spring.DocumentElement;
import org.springframework.ide.vscode.commons.protocol.spring.MatchingBeansParams;
import org.springframework.ide.vscode.commons.protocol.spring.SpringIndex;
import org.springframework.ide.vscode.commons.protocol.spring.SpringIndexElement;
@@ -732,7 +737,99 @@ public class SpringSymbolIndex implements InitializingBean, SpringIndex {
return Collections.emptyList();
}
}
public List<? extends DocumentSymbol> getDocumentSymbols(String docURI) {
List<DocumentSymbol> result = new ArrayList<>();
List<? extends WorkspaceSymbol> symbols = getSymbols(docURI);
for (WorkspaceSymbol symbol : symbols) {
DocumentSymbol docSymbol = new DocumentSymbol();
docSymbol.setName(symbol.getName());
docSymbol.setKind(symbol.getKind());
docSymbol.setRange(symbol.getLocation().getLeft().getRange());
docSymbol.setSelectionRange(symbol.getLocation().getLeft().getRange());
docSymbol.setTags(symbol.getTags());
result.add(docSymbol);
}
return result;
}
/*
public List<? extends WorkspaceSymbol> getSymbols(String docURI) {
List<WorkspaceSymbol> result = new ArrayList<>();
Deque<DocumentSymbol> remainingSymbols = new ArrayDeque<>();
List<? extends DocumentSymbol> documentSymbols = getDocumentSymbols(docURI);
remainingSymbols.addAll(documentSymbols);
while (!remainingSymbols.isEmpty()) {
DocumentSymbol documentSymbol = remainingSymbols.poll();
WorkspaceSymbol workspaceSymbol = new WorkspaceSymbol();
workspaceSymbol.setName(documentSymbol.getName());
workspaceSymbol.setKind(documentSymbol.getKind());
workspaceSymbol.setTags(documentSymbol.getTags());
Location location = new Location(docURI, documentSymbol.getRange());
workspaceSymbol.setLocation(Either.forLeft(location));
result.add(workspaceSymbol);
if (documentSymbol.getChildren() != null) {
remainingSymbols.addAll(documentSymbol.getChildren());
}
}
return result;
}
public List<? extends DocumentSymbol> getDocumentSymbols(String docURI) {
try {
TextDocument doc = server.getTextDocumentService().getLatestSnapshot(docURI);
URI uri = URI.create(docURI);
CompletableFuture<IJavaProject> projectInitialized = futureProjectFinder.findFuture(uri).thenCompose(project -> projectInitializedFuture(project));
IJavaProject project = projectInitialized.get(15, TimeUnit.SECONDS);
ImmutableList.Builder<DocumentSymbol> builder = ImmutableList.builder();
if (project != null && doc != null) {
// Collect symbols from the opened document
synchronized(this) {
for (SpringIndexer indexer : this.indexers) {
if (indexer.isInterestedIn(docURI)) {
try {
List<DocumentSymbol> adhocDocumentSymbols = indexer.computeDocumentSymbols(project, docURI, doc.get());
builder.addAll(adhocDocumentSymbols);
} catch (Exception e) {
log.error("{}", e);
}
}
}
}
} else {
// Take symbols from the index if there is no opened document.
DocumentElement document = springIndex.getDocument(docURI);
if (document != null) {
List<SpringIndexElement> children = document.getChildren();
builder.addAll(SpringIndexToSymbolsConverter.createDocumentSymbols(children));
}
}
return builder.build();
} catch (Exception e) {
log.warn("", e);
return Collections.emptyList();
}
}
*/
@Override
public CompletableFuture<List<Bean>> beans(BeansParams params) {
String projectName = params.getProjectName();

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2022 VMware, Inc.
* Copyright (c) 2022, 2025 VMware, 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
@@ -49,7 +49,7 @@ public class SpringFactoriesLanguageServerComponents implements LanguageServerCo
@Override
public Optional<DocumentSymbolHandler> getDocumentSymbolProvider() {
return Optional.of(params -> springIndex.getSymbols(params.getTextDocument().getUri()));
return Optional.of(params -> springIndex.getDocumentSymbols(params.getTextDocument().getUri()));
}
}

View File

@@ -173,8 +173,8 @@ public class BootJavaLanguageServerComponents implements LanguageServerComponent
new SpringProcessCommandHandler(server, liveDataService, liveDataLocalProcessConnector, appContext.getBeansOfType(SpringProcessConnectorRemote.class).values());
new CopilotAgentCommandHandler(server, projectFinder,responseModifier);
docSymbolProvider = params -> springSymbolIndex.getSymbols(params.getTextDocument().getUri());
docSymbolProvider = params -> springSymbolIndex.getDocumentSymbols(params.getTextDocument().getUri());
workspaceService.onWorkspaceSymbol(new BootJavaWorkspaceSymbolHandler(springSymbolIndex,
new LiveAppURLSymbolProvider(liveDataProvider)));

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019, 2022 Pivotal, Inc.
* Copyright (c) 2019, 2025 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
@@ -46,7 +46,7 @@ public class SpringXMLLanguageServerComponents implements LanguageServerComponen
SpelReconciler spelReconciler) {
this.projectFinder = serverParams.projectFinder;
this.docSymbolProvider = params -> springIndexer.getSymbols(params.getTextDocument().getUri());
this.docSymbolProvider = params -> springIndexer.getDocumentSymbols(params.getTextDocument().getUri());
server.doOnInitialized(this::initialized);
server.onShutdown(this::shutdown);