diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingIndexElement.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingIndexElement.java index f2ff26c47b..2560b7733a 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingIndexElement.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingIndexElement.java @@ -10,20 +10,28 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.java.requestmapping; +import org.eclipse.lsp4j.DocumentSymbol; +import org.eclipse.lsp4j.Range; +import org.eclipse.lsp4j.SymbolKind; import org.springframework.ide.vscode.commons.protocol.spring.AbstractSpringIndexElement; +import org.springframework.ide.vscode.commons.protocol.spring.SymbolElement; -public class RequestMappingIndexElement extends AbstractSpringIndexElement { +public class RequestMappingIndexElement extends AbstractSpringIndexElement implements SymbolElement { private final String path; private final String[] httpMethods; private final String[] contentTypes; private final String[] acceptTypes; + private final String symbolLabel; + private final Range range; - public RequestMappingIndexElement(String path, String[] httpMethods, String[] contentTypes, String[] acceptTypes) { + public RequestMappingIndexElement(String path, String[] httpMethods, String[] contentTypes, String[] acceptTypes, Range range, String symbolLabel) { this.path = path; this.httpMethods = httpMethods; this.contentTypes = contentTypes; this.acceptTypes = acceptTypes; + this.range = range; + this.symbolLabel = symbolLabel; } public String getPath() { @@ -42,4 +50,16 @@ public String[] getAcceptTypes() { return acceptTypes; } + @Override + public DocumentSymbol getDocumentSymbol() { + DocumentSymbol symbol = new DocumentSymbol(); + + symbol.setName(symbolLabel); + symbol.setKind(SymbolKind.Method); + symbol.setRange(range); + symbol.setSelectionRange(range); + + return symbol; + } + } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingSymbolProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingSymbolProvider.java index 3ad207f620..506eca18a1 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingSymbolProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingSymbolProvider.java @@ -39,6 +39,8 @@ import org.springframework.ide.vscode.boot.java.utils.ASTUtils; import org.springframework.ide.vscode.boot.java.utils.CachedSymbol; import org.springframework.ide.vscode.boot.java.utils.SpringIndexerJavaContext; +import org.springframework.ide.vscode.commons.protocol.spring.Bean; +import org.springframework.ide.vscode.commons.protocol.spring.SpringIndexElement; import org.springframework.ide.vscode.commons.util.text.TextDocument; /** @@ -77,20 +79,39 @@ protected void addSymbolsPass1(Annotation node, ITypeBinding annotationType, Col context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), symbol)); // index element for request mapping - List beans = context.getBeans(); - if (beans.size() > 0 ) { - CachedBean cachedBean = beans.get(beans.size() - 1); - if (cachedBean.getDocURI().equals(doc.getUri())) { - cachedBean.getBean().addChild(new RequestMappingIndexElement(p, methods, contentTypes, acceptTypes)); - } + SpringIndexElement parent = getPotentialParentIndexNode(context); + if (parent != null) { + parent.addChild(new RequestMappingIndexElement(p, methods, contentTypes, acceptTypes, location.getRange(), symbol.getName())); + } + else { + context.getBeans().add(new CachedBean(doc.getUri(), new RequestMappingIndexElement(p, methods, contentTypes, acceptTypes, location.getRange(), symbol.getName()))); } }); + } catch (Exception e) { log.error("problem occured while scanning for request mapping symbols from " + doc.getUri(), e); } } } + private SpringIndexElement getPotentialParentIndexNode(SpringIndexerJavaContext context) { + List beans = context.getBeans(); + + for (int i = beans.size() - 1; i >= 0; i--) { + CachedBean cachedBean = beans.get(i); + + if (!cachedBean.getDocURI().equals(context.getDocURI())) { + return null; + } + + if (cachedBean.getBean() instanceof Bean bean) { + return bean; + } + } + + return null; + } + private String combinePath(String parent, String path) { String separator = !parent.endsWith("/") && !path.startsWith("/") && !path.isEmpty() ? "/" : ""; String resultPath = parent + separator + path;