GH-1431: enable index elements to compute document symbols on-demand
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2025 Broadcom
|
||||
* 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
|
||||
* https://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Broadcom - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.protocol.spring;
|
||||
|
||||
import org.eclipse.lsp4j.DocumentSymbol;
|
||||
import org.eclipse.lsp4j.Range;
|
||||
import org.eclipse.lsp4j.WorkspaceSymbol;
|
||||
|
||||
public class SimpleSymbolElement extends AbstractSpringIndexElement implements SymbolElement {
|
||||
|
||||
private final WorkspaceSymbol symbol;
|
||||
|
||||
public SimpleSymbolElement(WorkspaceSymbol symbol) {
|
||||
this.symbol = symbol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DocumentSymbol getDocumentSymbol() {
|
||||
DocumentSymbol documentSymbol = new DocumentSymbol();
|
||||
documentSymbol.setName(symbol.getName());
|
||||
documentSymbol.setKind(symbol.getKind());
|
||||
documentSymbol.setTags(symbol.getTags());
|
||||
|
||||
Range range = symbol.getLocation().isLeft() ? symbol.getLocation().getLeft().getRange() : new Range();
|
||||
documentSymbol.setRange(range);
|
||||
documentSymbol.setSelectionRange(range);
|
||||
|
||||
return documentSymbol;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2025 Broadcom
|
||||
* 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
|
||||
* https://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Broadcom - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.protocol.spring;
|
||||
|
||||
import org.eclipse.lsp4j.DocumentSymbol;
|
||||
|
||||
public interface SymbolElement {
|
||||
|
||||
public DocumentSymbol getDocumentSymbol();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2025 Broadcom
|
||||
* 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
|
||||
* https://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Broadcom - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.index;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.lsp4j.DocumentSymbol;
|
||||
import org.eclipse.lsp4j.Position;
|
||||
import org.eclipse.lsp4j.Range;
|
||||
import org.eclipse.lsp4j.SymbolKind;
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.SpringIndexElement;
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.SymbolElement;
|
||||
|
||||
public class SpringIndexToSymbolsConverter {
|
||||
|
||||
public static List<DocumentSymbol> createDocumentSymbols(List<SpringIndexElement> indexElements) {
|
||||
List<DocumentSymbol> result = new ArrayList<>();
|
||||
|
||||
for (SpringIndexElement indexElement : indexElements) {
|
||||
result.add(createSymbol(indexElement));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static DocumentSymbol createSymbol(SpringIndexElement indexElement) {
|
||||
|
||||
DocumentSymbol symbol = null;
|
||||
if (indexElement instanceof SymbolElement symbolElement) {
|
||||
symbol = symbolElement.getDocumentSymbol();
|
||||
}
|
||||
else {
|
||||
symbol = new DocumentSymbol(indexElement.toString(), SymbolKind.String,
|
||||
new Range(new Position(), new Position()),
|
||||
new Range(new Position(), new Position()));
|
||||
}
|
||||
|
||||
List<SpringIndexElement> children = indexElement.getChildren();
|
||||
if (children != null && children.size() > 0) {
|
||||
List<DocumentSymbol> childSymbols = new ArrayList<>();
|
||||
|
||||
for (SpringIndexElement child : children) {
|
||||
DocumentSymbol childSymbol = createSymbol(child);
|
||||
if (childSymbol != null) {
|
||||
childSymbols.add(childSymbol);
|
||||
}
|
||||
}
|
||||
|
||||
if (childSymbols.size() > 0) {
|
||||
symbol.setChildren(childSymbols);
|
||||
}
|
||||
}
|
||||
|
||||
return symbol;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,7 +22,9 @@ import org.eclipse.lsp4j.WorkspaceSymbol;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.boot.java.Annotations;
|
||||
import org.springframework.ide.vscode.boot.java.beans.CachedBean;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.AbstractSymbolProvider;
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.SimpleSymbolElement;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
/**
|
||||
@@ -41,6 +43,7 @@ public class RestrictedDefaultSymbolProvider extends AbstractSymbolProvider {
|
||||
try {
|
||||
WorkspaceSymbol symbol = DefaultSymbolProvider.provideDefaultSymbol(node, doc);
|
||||
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), symbol));
|
||||
context.getBeans().add(new CachedBean(context.getDocURI(), new SimpleSymbolElement(symbol)));
|
||||
} catch (Exception e) {
|
||||
log.warn(e.getMessage());
|
||||
}
|
||||
|
||||
@@ -28,10 +28,12 @@ import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.eclipse.lsp4j.DocumentSymbol;
|
||||
import org.eclipse.lsp4j.Location;
|
||||
import org.eclipse.lsp4j.Range;
|
||||
import org.eclipse.lsp4j.SymbolKind;
|
||||
import org.eclipse.lsp4j.WorkspaceSymbol;
|
||||
import org.eclipse.lsp4j.WorkspaceSymbolLocation;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.Either;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -100,6 +102,28 @@ public class SpringFactoriesIndexer implements SpringIndexer {
|
||||
return computeSymbols(docURI, content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DocumentSymbol> computeDocumentSymbols(IJavaProject project, String docURI, String content) throws Exception {
|
||||
return computeSymbols(docURI, content).stream()
|
||||
.map(workspaceSymbol -> convertToDocumentSymbol(workspaceSymbol))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private DocumentSymbol convertToDocumentSymbol(WorkspaceSymbol workspaceSymbol) {
|
||||
Either<Location, WorkspaceSymbolLocation> location = workspaceSymbol.getLocation();
|
||||
|
||||
Range range = null;
|
||||
if (location.isLeft()) {
|
||||
Location l = location.getLeft();
|
||||
range = l.getRange();
|
||||
}
|
||||
else if (location.isRight()) {
|
||||
range = new Range();
|
||||
}
|
||||
|
||||
return new DocumentSymbol(workspaceSymbol.getName(), workspaceSymbol.getKind(), range, range);
|
||||
}
|
||||
|
||||
private List<WorkspaceSymbol> computeSymbols(String docURI, String content) {
|
||||
ImmutableList.Builder<WorkspaceSymbol> symbols = ImmutableList.builder();
|
||||
PropertiesAst ast = new AntlrParser().parse(content).ast;
|
||||
@@ -287,5 +311,5 @@ public class SpringFactoriesIndexer implements SpringIndexer {
|
||||
IndexCacheKey key = getCacheKey(project);
|
||||
cache.removeFiles(key, files, CachedSymbol.class);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ package org.springframework.ide.vscode.boot.java.utils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.lsp4j.DocumentSymbol;
|
||||
import org.eclipse.lsp4j.WorkspaceSymbol;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
|
||||
@@ -24,6 +25,7 @@ public interface SpringIndexer {
|
||||
boolean isInterestedIn(String resource); // note that this might be a document URI or a standard file path on the system
|
||||
|
||||
List<WorkspaceSymbol> computeSymbols(IJavaProject project, String docURI, String content) throws Exception;
|
||||
List<DocumentSymbol> computeDocumentSymbols(IJavaProject project, String docURI, String string) throws Exception;
|
||||
|
||||
void initializeProject(IJavaProject project, boolean clean) throws Exception;
|
||||
void removeProject(IJavaProject project) throws Exception;
|
||||
|
||||
@@ -49,9 +49,11 @@ import org.eclipse.jdt.core.dom.NormalAnnotation;
|
||||
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
|
||||
import org.eclipse.jdt.core.dom.TypeDeclaration;
|
||||
import org.eclipse.lsp4j.Diagnostic;
|
||||
import org.eclipse.lsp4j.DocumentSymbol;
|
||||
import org.eclipse.lsp4j.WorkspaceSymbol;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.boot.index.SpringIndexToSymbolsConverter;
|
||||
import org.springframework.ide.vscode.boot.index.cache.IndexCache;
|
||||
import org.springframework.ide.vscode.boot.index.cache.IndexCacheKey;
|
||||
import org.springframework.ide.vscode.boot.java.Annotations;
|
||||
@@ -71,6 +73,7 @@ import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFin
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblem;
|
||||
import org.springframework.ide.vscode.commons.protocol.java.Classpath;
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.SimpleSymbolElement;
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.SpringIndexElement;
|
||||
import org.springframework.ide.vscode.commons.util.UriUtil;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
@@ -366,6 +369,47 @@ public class SpringIndexerJava implements SpringIndexer {
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DocumentSymbol> computeDocumentSymbols(IJavaProject project, String docURI, String content) throws Exception {
|
||||
if (content != null) {
|
||||
URI uri = URI.create(docURI);
|
||||
|
||||
return cuCache.withCompilationUnit(project, uri, cu -> {
|
||||
List<CachedSymbol> generatedSymbols = new ArrayList<CachedSymbol>();
|
||||
List<CachedBean> generatedBeans = new ArrayList<CachedBean>();
|
||||
|
||||
IProblemCollector voidProblemCollector = new IProblemCollector() {
|
||||
@Override
|
||||
public void endCollecting() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginCollecting() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(ReconcileProblem problem) {
|
||||
}
|
||||
};
|
||||
|
||||
AtomicReference<TextDocument> docRef = new AtomicReference<>();
|
||||
String file = UriUtil.toFileString(docURI);
|
||||
SpringIndexerJavaContext context = new SpringIndexerJavaContext(project, cu, docURI, file,
|
||||
0, docRef, content, generatedSymbols, generatedBeans, voidProblemCollector, SCAN_PASS.ONE, new ArrayList<>(), true);
|
||||
|
||||
scanAST(context, false);
|
||||
|
||||
List<SpringIndexElement> indexElements = generatedBeans.stream()
|
||||
.map(cachedBean -> cachedBean.getBean())
|
||||
.toList();
|
||||
|
||||
return SpringIndexToSymbolsConverter.createDocumentSymbols(indexElements);
|
||||
});
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private Set<String> scanFilesInternally(IJavaProject project, DocumentDescriptor[] docs) throws Exception {
|
||||
final boolean ignoreMethodBodies = false;
|
||||
@@ -770,6 +814,7 @@ public class SpringIndexerJava implements SpringIndexer {
|
||||
WorkspaceSymbol symbol = provideDefaultSymbol(node, context);
|
||||
if (symbol != null) {
|
||||
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), symbol));
|
||||
context.getBeans().add(new CachedBean(context.getDocURI(), new SimpleSymbolElement(symbol)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -965,5 +1010,5 @@ public class SpringIndexerJava implements SpringIndexer {
|
||||
fileScanListener.fileScanned(file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -31,9 +31,11 @@ import org.apache.commons.io.FileUtils;
|
||||
import org.eclipse.lemminx.dom.DOMDocument;
|
||||
import org.eclipse.lemminx.dom.DOMNode;
|
||||
import org.eclipse.lemminx.dom.DOMParser;
|
||||
import org.eclipse.lsp4j.DocumentSymbol;
|
||||
import org.eclipse.lsp4j.WorkspaceSymbol;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.boot.index.SpringIndexToSymbolsConverter;
|
||||
import org.springframework.ide.vscode.boot.index.cache.IndexCache;
|
||||
import org.springframework.ide.vscode.boot.index.cache.IndexCacheKey;
|
||||
import org.springframework.ide.vscode.boot.java.beans.CachedBean;
|
||||
@@ -352,8 +354,7 @@ public class SpringIndexerXML implements SpringIndexer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<WorkspaceSymbol> computeSymbols(IJavaProject project, String docURI, String content)
|
||||
throws Exception {
|
||||
public List<WorkspaceSymbol> computeSymbols(IJavaProject project, String docURI, String content) throws Exception {
|
||||
if (content != null) {
|
||||
List<CachedSymbol> generatedSymbols = new ArrayList<>();
|
||||
List<CachedBean> generatedBeans = new ArrayList<>();
|
||||
@@ -361,7 +362,24 @@ public class SpringIndexerXML implements SpringIndexer {
|
||||
scanFile(project, content, docURI, 0, generatedSymbols, generatedBeans);
|
||||
return generatedSymbols.stream().map(s -> s.getEnhancedSymbol()).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DocumentSymbol> computeDocumentSymbols(IJavaProject project, String docURI, String content) throws Exception {
|
||||
if (content != null) {
|
||||
List<CachedSymbol> generatedSymbols = new ArrayList<>();
|
||||
List<CachedBean> generatedBeans = new ArrayList<>();
|
||||
|
||||
scanFile(project, content, docURI, 0, generatedSymbols, generatedBeans);
|
||||
|
||||
return SpringIndexToSymbolsConverter.createDocumentSymbols(generatedBeans.stream().map(cachedBean -> cachedBean.getBean()).toList());
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user