added option to generate additional information while parsing symbols and do that for handler methods in webflux definitions

This commit is contained in:
Martin Lippert
2018-02-27 17:13:34 +01:00
parent 27859bf670
commit 79c71128a1
10 changed files with 271 additions and 50 deletions

View File

@@ -23,6 +23,7 @@ import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.lsp4j.SymbolKind;
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider;
import org.springframework.ide.vscode.boot.java.utils.ASTUtils;
import org.springframework.ide.vscode.boot.java.utils.FunctionUtils;
@@ -46,17 +47,19 @@ public class BeansSymbolProvider implements SymbolProvider {
private static final String[] NAME_ATTRIBUTES = {"value", "name"};
@Override
public Collection<SymbolInformation> getSymbols(Annotation node, ITypeBinding annotationType, Collection<ITypeBinding> metaAnnotations, TextDocument doc) {
public Collection<EnhancedSymbolInformation> getSymbols(Annotation node, ITypeBinding annotationType, Collection<ITypeBinding> metaAnnotations, TextDocument doc) {
boolean isFunction = isFunctionBean(node);
ImmutableList.Builder<SymbolInformation> symbols = ImmutableList.builder();
ImmutableList.Builder<EnhancedSymbolInformation> symbols = ImmutableList.builder();
String beanType = getBeanType(node);
for (Tuple2<String, DocumentRegion> nameAndRegion : getBeanNames(node, doc)) {
try {
symbols.add(new SymbolInformation(
beanLabel(isFunction, nameAndRegion.getT1(), beanType, "@Bean"),
SymbolKind.Interface,
new Location(doc.getUri(), doc.toRange(nameAndRegion.getT2()))
symbols.add(new EnhancedSymbolInformation(
new SymbolInformation(
beanLabel(isFunction, nameAndRegion.getT1(), beanType, "@Bean"),
SymbolKind.Interface,
new Location(doc.getUri(), doc.toRange(nameAndRegion.getT2()))),
null
));
} catch (BadLocationException e) {
Log.log(e);
@@ -66,7 +69,7 @@ public class BeansSymbolProvider implements SymbolProvider {
}
@Override
public Collection<SymbolInformation> getSymbols(TypeDeclaration typeDeclaration, TextDocument doc) {
public Collection<EnhancedSymbolInformation> getSymbols(TypeDeclaration typeDeclaration, TextDocument doc) {
// this checks function beans that are defined as implementations of Function interfaces
Tuple3<String, String, DocumentRegion> functionBean = FunctionUtils.getFunctionBean(typeDeclaration, doc);
if (functionBean != null) {
@@ -75,7 +78,7 @@ public class BeansSymbolProvider implements SymbolProvider {
beanLabel(true, functionBean.getT1(), functionBean.getT2(), null),
SymbolKind.Interface,
new Location(doc.getUri(), doc.toRange(functionBean.getT3())));
return ImmutableList.of(symbol);
return ImmutableList.of(new EnhancedSymbolInformation(symbol, null));
} catch (BadLocationException e) {
Log.log(e);
}
@@ -166,7 +169,7 @@ public class BeansSymbolProvider implements SymbolProvider {
}
@Override
public Collection<SymbolInformation> getSymbols(MethodDeclaration methodDeclaration, TextDocument doc) {
public Collection<EnhancedSymbolInformation> getSymbols(MethodDeclaration methodDeclaration, TextDocument doc) {
return null;
}

View File

@@ -21,6 +21,7 @@ import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.lsp4j.SymbolKind;
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.Log;
@@ -35,7 +36,7 @@ import com.google.common.collect.ImmutableList;
public class ComponentSymbolProvider implements SymbolProvider {
@Override
public Collection<SymbolInformation> getSymbols(Annotation node, ITypeBinding annotationType, Collection<ITypeBinding> metaAnnotations, TextDocument doc) {
public Collection<EnhancedSymbolInformation> getSymbols(Annotation node, ITypeBinding annotationType, Collection<ITypeBinding> metaAnnotations, TextDocument doc) {
try {
return ImmutableList.of(
createSymbol(node, annotationType, metaAnnotations, doc)
@@ -47,7 +48,7 @@ public class ComponentSymbolProvider implements SymbolProvider {
return ImmutableList.of();
}
protected SymbolInformation createSymbol(Annotation node, ITypeBinding annotationType, Collection<ITypeBinding> metaAnnotations, TextDocument doc) throws BadLocationException {
protected EnhancedSymbolInformation createSymbol(Annotation node, ITypeBinding annotationType, Collection<ITypeBinding> metaAnnotations, TextDocument doc) throws BadLocationException {
String annotationTypeName = annotationType.getName();
Collection<String> metaAnnotationNames = metaAnnotations.stream()
.map(ITypeBinding::getName)
@@ -58,7 +59,7 @@ public class ComponentSymbolProvider implements SymbolProvider {
SymbolInformation symbol = new SymbolInformation(
beanLabel("+", annotationTypeName, metaAnnotationNames, beanName, beanType), SymbolKind.Interface,
new Location(doc.getUri(), doc.toRange(node.getStartPosition(), node.getLength())));
return symbol;
return new EnhancedSymbolInformation(symbol, null);
}
protected String beanLabel(String searchPrefix, String annotationTypeName, Collection<String> metaAnnotationNames, String beanName, String beanType) {
@@ -113,12 +114,12 @@ public class ComponentSymbolProvider implements SymbolProvider {
}
@Override
public Collection<SymbolInformation> getSymbols(TypeDeclaration typeDeclaration, TextDocument doc) {
public Collection<EnhancedSymbolInformation> getSymbols(TypeDeclaration typeDeclaration, TextDocument doc) {
return null;
}
@Override
public Collection<SymbolInformation> getSymbols(MethodDeclaration methodDeclaration, TextDocument doc) {
public Collection<EnhancedSymbolInformation> getSymbols(MethodDeclaration methodDeclaration, TextDocument doc) {
return null;
}

View File

@@ -19,6 +19,7 @@ import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.lsp4j.SymbolKind;
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider;
import org.springframework.ide.vscode.boot.java.utils.ASTUtils;
import org.springframework.ide.vscode.commons.util.BadLocationException;
@@ -38,14 +39,8 @@ public class DataRepositorySymbolProvider implements SymbolProvider {
private static final String REPOSITORY_TYPE = "org.springframework.data.repository.Repository";
@Override
public Collection<SymbolInformation> getSymbols(Annotation node, ITypeBinding annotationType, Collection<ITypeBinding> metaAnnotations, TextDocument doc) {
return null;
}
@Override
public Collection<SymbolInformation> getSymbols(TypeDeclaration typeDeclaration, TextDocument doc) {
public Collection<EnhancedSymbolInformation> getSymbols(TypeDeclaration typeDeclaration, TextDocument doc) {
// this checks spring data repository beans that are defined as extensions of the repository interface
Tuple4<String, String, String, DocumentRegion> repositoryBean = getRepositoryBean(typeDeclaration, doc);
if (repositoryBean != null) {
@@ -54,7 +49,7 @@ public class DataRepositorySymbolProvider implements SymbolProvider {
beanLabel(true, repositoryBean.getT1(), repositoryBean.getT2(), repositoryBean.getT3()),
SymbolKind.Interface,
new Location(doc.getUri(), doc.toRange(repositoryBean.getT4())));
return ImmutableList.of(symbol);
return ImmutableList.of(new EnhancedSymbolInformation(symbol, null));
} catch (BadLocationException e) {
Log.log(e);
}
@@ -142,7 +137,12 @@ public class DataRepositorySymbolProvider implements SymbolProvider {
}
@Override
public Collection<SymbolInformation> getSymbols(MethodDeclaration methodDeclaration, TextDocument doc) {
public Collection<EnhancedSymbolInformation> getSymbols(Annotation node, ITypeBinding annotationType, Collection<ITypeBinding> metaAnnotations, TextDocument doc) {
return null;
}
@Override
public Collection<EnhancedSymbolInformation> getSymbols(MethodDeclaration methodDeclaration, TextDocument doc) {
return null;
}
}

View File

@@ -0,0 +1,36 @@
/*******************************************************************************
* Copyright (c) 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.handlers;
import org.eclipse.lsp4j.SymbolInformation;
/**
* @author Martin Lippert
*/
public class EnhancedSymbolInformation {
private final SymbolInformation symbol;
private final Object additionalInformation;
public EnhancedSymbolInformation(SymbolInformation symbol, Object additionalInformation) {
this.symbol = symbol;
this.additionalInformation = additionalInformation;
}
public SymbolInformation getSymbol() {
return symbol;
}
public Object getAdditionalInformation() {
return additionalInformation;
}
}

View File

@@ -16,7 +16,6 @@ import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.lsp4j.SymbolInformation;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
/**
@@ -25,8 +24,8 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument;
*/
public interface SymbolProvider {
Collection<SymbolInformation> getSymbols(Annotation node, ITypeBinding typeBinding, Collection<ITypeBinding> metaAnnotations, TextDocument doc);
Collection<SymbolInformation> getSymbols(TypeDeclaration typeDeclaration, TextDocument doc);
Collection<SymbolInformation> getSymbols(MethodDeclaration methodDeclaration, TextDocument doc);
Collection<EnhancedSymbolInformation> getSymbols(Annotation node, ITypeBinding typeBinding, Collection<ITypeBinding> metaAnnotations, TextDocument doc);
Collection<EnhancedSymbolInformation> getSymbols(TypeDeclaration typeDeclaration, TextDocument doc);
Collection<EnhancedSymbolInformation> getSymbols(MethodDeclaration methodDeclaration, TextDocument doc);
}

View File

@@ -31,6 +31,7 @@ import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.lsp4j.SymbolKind;
import org.springframework.ide.vscode.boot.java.Annotations;
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider;
import org.springframework.ide.vscode.boot.java.utils.ASTUtils;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
@@ -41,7 +42,7 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument;
public class RequestMappingSymbolProvider implements SymbolProvider {
@Override
public Collection<SymbolInformation> getSymbols(Annotation node, ITypeBinding annotationType, Collection<ITypeBinding> metaAnnotations, TextDocument doc) {
public Collection<EnhancedSymbolInformation> getSymbols(Annotation node, ITypeBinding annotationType, Collection<ITypeBinding> metaAnnotations, TextDocument doc) {
if (node.getParent() instanceof MethodDeclaration) {
try {
Location location = new Location(doc.getUri(), doc.toRange(node.getStartPosition(), node.getLength()));
@@ -62,7 +63,7 @@ public class RequestMappingSymbolProvider implements SymbolProvider {
return resultPath.startsWith("/") ? resultPath : "/" + resultPath;
}))
.map(p -> "@" + p + (methodStr.isEmpty() ? "" : " -- " + methodStr))
.map(symbolLabel -> new SymbolInformation(symbolLabel, SymbolKind.Interface, location))
.map(symbolLabel -> new EnhancedSymbolInformation(new SymbolInformation(symbolLabel, SymbolKind.Interface, location), null))
.collect(Collectors.toList());
} catch (Exception e) {
e.printStackTrace();
@@ -177,12 +178,12 @@ public class RequestMappingSymbolProvider implements SymbolProvider {
}
@Override
public Collection<SymbolInformation> getSymbols(TypeDeclaration typeDeclaration, TextDocument doc) {
public Collection<EnhancedSymbolInformation> getSymbols(TypeDeclaration typeDeclaration, TextDocument doc) {
return null;
}
@Override
public Collection<SymbolInformation> getSymbols(MethodDeclaration methodDeclaration, TextDocument doc) {
public Collection<EnhancedSymbolInformation> getSymbols(MethodDeclaration methodDeclaration, TextDocument doc) {
return null;
}

View File

@@ -0,0 +1,40 @@
/*******************************************************************************
* Copyright (c) 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.requestmapping;
/**
* @author Martin Lippert
*/
public class WebfluxHandlerInformation {
private final String symbol;
private String destinationClass;
private String methodKey;
public WebfluxHandlerInformation(String symbol, String destinationClass, String methodKey) {
this.symbol = symbol;
this.destinationClass = destinationClass;
this.methodKey = methodKey;
}
public String getSymbol() {
return symbol;
}
public String getDestinationClass() {
return destinationClass;
}
public String getMethodKey() {
return methodKey;
}
}

View File

@@ -18,15 +18,18 @@ import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.ExpressionMethodReference;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.MethodReference;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.lsp4j.SymbolKind;
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
@@ -37,18 +40,18 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument;
public class WebfluxRouterSymbolProvider implements SymbolProvider {
@Override
public Collection<SymbolInformation> getSymbols(Annotation node, ITypeBinding typeBinding,
public Collection<EnhancedSymbolInformation> getSymbols(Annotation node, ITypeBinding typeBinding,
Collection<ITypeBinding> metaAnnotations, TextDocument doc) {
return null;
}
@Override
public Collection<SymbolInformation> getSymbols(TypeDeclaration typeDeclaration, TextDocument doc) {
public Collection<EnhancedSymbolInformation> getSymbols(TypeDeclaration typeDeclaration, TextDocument doc) {
return null;
}
@Override
public Collection<SymbolInformation> getSymbols(MethodDeclaration methodDeclaration, TextDocument doc) {
public Collection<EnhancedSymbolInformation> getSymbols(MethodDeclaration methodDeclaration, TextDocument doc) {
Type returnType = methodDeclaration.getReturnType2();
if (returnType != null) {
ITypeBinding resolvedBinding = returnType.resolveBinding();
@@ -61,9 +64,9 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider {
return null;
}
private Collection<SymbolInformation> getSymbolsForRouterFunction(MethodDeclaration methodDeclaration,
private Collection<EnhancedSymbolInformation> getSymbolsForRouterFunction(MethodDeclaration methodDeclaration,
TextDocument doc) {
List<SymbolInformation> result = new ArrayList<>();
List<EnhancedSymbolInformation> result = new ArrayList<>();
Block body = methodDeclaration.getBody();
body.accept(new ASTVisitor() {
@@ -84,7 +87,7 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider {
return result;
}
protected void extractMappingSymbol(MethodInvocation node, TextDocument doc, List<SymbolInformation> result) {
protected void extractMappingSymbol(MethodInvocation node, TextDocument doc, List<EnhancedSymbolInformation> result) {
String foundPath = extractPathFromRouterFunction(node);
String path = extractPath(node, foundPath);
String httpMethod = extractMethod(node);
@@ -96,7 +99,10 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider {
try {
Location location = new Location(doc.getUri(), doc.toRange(methodNameStart, node.getLength() - (methodNameStart - invocationStart)));
String label = "@" + (path.startsWith("/") ? path : ("/" + path)) + (httpMethod == null || httpMethod.isEmpty() ? "" : " -- " + httpMethod);
result.add(new SymbolInformation(label, SymbolKind.Interface, location));
WebfluxHandlerInformation handler = extractHandlerInformation(node, label);
result.add(new EnhancedSymbolInformation(new SymbolInformation(label, SymbolKind.Interface, location), handler));
} catch (BadLocationException e) {
e.printStackTrace();
}
@@ -155,5 +161,28 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider {
String method = methodFinder.getMethod();
return method;
}
private WebfluxHandlerInformation extractHandlerInformation(MethodInvocation node, String symbol) {
List<?> arguments = node.arguments();
if (arguments != null) {
for (Object argument : arguments) {
if (argument instanceof ExpressionMethodReference) {
ExpressionMethodReference methodReference = (ExpressionMethodReference) argument;
IMethodBinding methodBinding = methodReference.resolveMethodBinding();
if (methodBinding != null && methodBinding.getDeclaringClass() != null && methodBinding.getMethodDeclaration() != null) {
ITypeBinding declaringClass = methodBinding.getDeclaringClass();
String destinationClass = declaringClass.getBinaryName();
String methodKey = methodBinding.getMethodDeclaration().getKey();
return new WebfluxHandlerInformation(symbol, destinationClass, methodKey);
}
}
}
}
return null;
}
}

View File

@@ -29,6 +29,7 @@ import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -56,6 +57,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.BootLanguageServerParams;
import org.springframework.ide.vscode.boot.java.annotations.AnnotationHierarchies;
import org.springframework.ide.vscode.boot.java.annotations.AnnotationHierarchyAwareLookup;
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider;
import org.springframework.ide.vscode.commons.java.IClasspath;
import org.springframework.ide.vscode.commons.java.IJavaProject;
@@ -80,7 +82,9 @@ public class SpringIndexer {
private final AnnotationHierarchyAwareLookup<SymbolProvider> symbolProviders;
private final List<SymbolInformation> symbols;
private final List<Object> addonInformation;
private final ConcurrentMap<String, List<SymbolInformation>> symbolsByDoc;
private final ConcurrentMap<String, List<Object>> addonInformationByDoc;
private final Thread updateWorker;
private final BlockingQueue<WorkerItem> updateQueue;
@@ -119,6 +123,8 @@ public class SpringIndexer {
this.symbols = Collections.synchronizedList(new ArrayList<>());
this.symbolsByDoc = new ConcurrentHashMap<>();
this.addonInformation = Collections.synchronizedList(new ArrayList<>());
this.addonInformationByDoc = new ConcurrentHashMap<>();
this.updateQueue = new LinkedBlockingQueue<>();
this.updateWorker = new Thread(new Runnable() {
@@ -208,6 +214,9 @@ public class SpringIndexer {
symbols.clear();
symbolsByDoc.clear();
addonInformation.clear();
addonInformationByDoc.clear();
Collection<WorkspaceFolder> roots = server.getWorkspaceRoots();
log.debug("refresh spring indexer for roots: {}", roots.toString());
initialize(roots);
@@ -305,6 +314,22 @@ public class SpringIndexer {
return this.symbolsByDoc.get(docURI);
}
public List<Object> getAllAdditionalInformation(Predicate<Object> filter) {
waitForInitializeTask();
if (filter != null) {
return addonInformation.stream().filter(filter).collect(Collectors.toList());
}
else {
return null;
}
}
public List<? extends Object> getAdditonalInformation(String docURI) {
waitForInitializeTask();
return this.addonInformationByDoc.get(docURI);
}
private List<SymbolInformation> searchMatchingSymbols(List<SymbolInformation> allsymbols, String query) {
waitForInitializeTask();
return allsymbols.stream()
@@ -365,6 +390,11 @@ public class SpringIndexer {
symbols.removeAll(oldSymbols);
}
List<Object> oldAddInInformation = addonInformationByDoc.remove(docURI);
if (oldAddInInformation != null) {
addonInformation.removeAll(oldAddInInformation);
}
AtomicReference<TextDocument> docRef = new AtomicReference<>();
scanAST(cu, docURI, docRef, content);
}
@@ -464,11 +494,16 @@ public class SpringIndexer {
if (!providers.isEmpty()) {
TextDocument doc = getTempTextDocument(docURI, docRef, content);
for (SymbolProvider provider : providers) {
Collection<SymbolInformation> sbls = provider.getSymbols(typeDeclaration, doc);
Collection<EnhancedSymbolInformation> sbls = provider.getSymbols(typeDeclaration, doc);
if (sbls != null) {
sbls.forEach(symbol -> {
symbols.add(symbol);
symbolsByDoc.computeIfAbsent(docURI, s -> new ArrayList<SymbolInformation>()).add(symbol);
sbls.forEach(enhancedSymbol -> {
symbols.add(enhancedSymbol.getSymbol());
symbolsByDoc.computeIfAbsent(docURI, s -> new ArrayList<SymbolInformation>()).add(enhancedSymbol.getSymbol());
if (enhancedSymbol.getAdditionalInformation() != null) {
addonInformation.add(enhancedSymbol.getAdditionalInformation());
addonInformationByDoc.computeIfAbsent(docURI, s -> new ArrayList<Object>()).add(enhancedSymbol.getAdditionalInformation());
}
});
}
}
@@ -480,11 +515,16 @@ public class SpringIndexer {
if (!providers.isEmpty()) {
TextDocument doc = getTempTextDocument(docURI, docRef, content);
for (SymbolProvider provider : providers) {
Collection<SymbolInformation> sbls = provider.getSymbols(methodDeclaration, doc);
Collection<EnhancedSymbolInformation> sbls = provider.getSymbols(methodDeclaration, doc);
if (sbls != null) {
sbls.forEach(symbol -> {
symbols.add(symbol);
symbolsByDoc.computeIfAbsent(docURI, s -> new ArrayList<SymbolInformation>()).add(symbol);
sbls.forEach(enhancedSymbol -> {
symbols.add(enhancedSymbol.getSymbol());
symbolsByDoc.computeIfAbsent(docURI, s -> new ArrayList<SymbolInformation>()).add(enhancedSymbol.getSymbol());
if (enhancedSymbol.getAdditionalInformation() != null) {
addonInformation.add(enhancedSymbol.getAdditionalInformation());
addonInformationByDoc.computeIfAbsent(docURI, s -> new ArrayList<Object>()).add(enhancedSymbol.getAdditionalInformation());
}
});
}
}
@@ -500,11 +540,16 @@ public class SpringIndexer {
if (!providers.isEmpty()) {
TextDocument doc = getTempTextDocument(docURI, docRef, content);
for (SymbolProvider provider : providers) {
Collection<SymbolInformation> sbls = provider.getSymbols(node, typeBinding, metaAnnotations, doc);
Collection<EnhancedSymbolInformation> sbls = provider.getSymbols(node, typeBinding, metaAnnotations, doc);
if (sbls != null) {
sbls.forEach(symbol -> {
symbols.add(symbol);
symbolsByDoc.computeIfAbsent(docURI, s -> new ArrayList<SymbolInformation>()).add(symbol);
sbls.forEach(enhancedSymbol -> {
symbols.add(enhancedSymbol.getSymbol());
symbolsByDoc.computeIfAbsent(docURI, s -> new ArrayList<SymbolInformation>()).add(enhancedSymbol.getSymbol());
if (enhancedSymbol.getAdditionalInformation() != null) {
addonInformation.add(enhancedSymbol.getAdditionalInformation());
addonInformationByDoc.computeIfAbsent(docURI, s -> new ArrayList<Object>()).add(enhancedSymbol.getAdditionalInformation());
}
});
}
}
@@ -660,10 +705,17 @@ public class SpringIndexer {
@Override
public void run() {
try {
List<SymbolInformation> oldSymbols = symbolsByDoc.remove(docURI);
if (oldSymbols != null) {
symbols.removeAll(oldSymbols);
}
List<Object> oldAddInInformation = addonInformationByDoc.remove(docURI);
if (oldAddInInformation != null) {
addonInformation.removeAll(oldAddInInformation);
}
} catch (Exception e) {
log.error("{}", e);
}

View File

@@ -11,15 +11,18 @@
package org.springframework.ide.vscode.boot.java.requestmapping.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import org.eclipse.lsp4j.SymbolInformation;
import org.junit.Before;
import org.junit.Test;
import org.springframework.ide.vscode.boot.java.requestmapping.WebfluxHandlerInformation;
import org.springframework.ide.vscode.project.harness.BootJavaLanguageServerHarness;
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
@@ -45,6 +48,9 @@ public class WebFluxMappingSymbolProviderTest {
assertEquals(4, symbols.size());
assertTrue(containsSymbol(symbols, "@/users", docUri, 19, 1, 19, 74));
assertTrue(containsSymbol(symbols, "@/users/{username}", docUri, 24, 1, 24, 85));
List<? extends Object> addons = getAdditionalInformation(docUri);
assertNull(addons);
}
@Test
@@ -59,6 +65,29 @@ public class WebFluxMappingSymbolProviderTest {
assertTrue(containsSymbol(symbols, "@/echo -- POST", docUri, 23, 5, 23, 101));
assertTrue(containsSymbol(symbols, "@/quotes -- GET", docUri, 24, 5, 24, 86));
assertTrue(containsSymbol(symbols, "@/quotes -- GET", docUri, 25, 5, 25, 94));
List<? extends Object> addons = getAdditionalInformation(docUri);
assertEquals(4, addons.size());
WebfluxHandlerInformation handlerInfo1 = getWebfluxHandler(addons, "@/hello -- GET").get(0);
assertEquals("@/hello -- GET", handlerInfo1.getSymbol());
assertEquals("org.test.QuoteHandler", handlerInfo1.getDestinationClass());
assertEquals("Lorg/test/QuoteHandler;.hello(Lorg/springframework/web/reactive/function/server/ServerRequest;)Lreactor/core/publisher/Mono<Lorg/springframework/web/reactive/function/server/ServerResponse;>;", handlerInfo1.getMethodKey());
WebfluxHandlerInformation handlerInfo2 = getWebfluxHandler(addons, "@/echo -- POST").get(0);
assertEquals("@/echo -- POST", handlerInfo2.getSymbol());
assertEquals("org.test.QuoteHandler", handlerInfo2.getDestinationClass());
assertEquals("Lorg/test/QuoteHandler;.echo(Lorg/springframework/web/reactive/function/server/ServerRequest;)Lreactor/core/publisher/Mono<Lorg/springframework/web/reactive/function/server/ServerResponse;>;", handlerInfo2.getMethodKey());
WebfluxHandlerInformation handlerInfo3 = getWebfluxHandler(addons, "@/quotes -- GET").get(0);
assertEquals("@/quotes -- GET", handlerInfo3.getSymbol());
assertEquals("org.test.QuoteHandler", handlerInfo3.getDestinationClass());
assertEquals("Lorg/test/QuoteHandler;.streamQuotes(Lorg/springframework/web/reactive/function/server/ServerRequest;)Lreactor/core/publisher/Mono<Lorg/springframework/web/reactive/function/server/ServerResponse;>;", handlerInfo3.getMethodKey());
WebfluxHandlerInformation handlerInfo4 = getWebfluxHandler(addons, "@/quotes -- GET").get(1);
assertEquals("@/quotes -- GET", handlerInfo4.getSymbol());
assertEquals("org.test.QuoteHandler", handlerInfo4.getDestinationClass());
assertEquals("Lorg/test/QuoteHandler;.fetchQuotes(Lorg/springframework/web/reactive/function/server/ServerRequest;)Lreactor/core/publisher/Mono<Lorg/springframework/web/reactive/function/server/ServerResponse;>;", handlerInfo4.getMethodKey());
}
@Test
@@ -72,6 +101,24 @@ public class WebFluxMappingSymbolProviderTest {
assertTrue(containsSymbol(symbols, "@/person/{id} -- GET", docUri, 27, 6, 27, 45));
assertTrue(containsSymbol(symbols, "@/person/ -- POST", docUri, 29, 6, 29, 83));
assertTrue(containsSymbol(symbols, "@/person -- GET", docUri, 28, 7, 28, 60));
List<? extends Object> addons = getAdditionalInformation(docUri);
assertEquals(3, addons.size());
WebfluxHandlerInformation handlerInfo1 = getWebfluxHandler(addons, "@/person/{id} -- GET").get(0);
assertEquals("@/person/{id} -- GET", handlerInfo1.getSymbol());
assertEquals("org.test.PersonHandler", handlerInfo1.getDestinationClass());
assertEquals("Lorg/test/PersonHandler;.getPerson(Lorg/springframework/web/reactive/function/server/ServerRequest;)Lreactor/core/publisher/Mono<Lorg/springframework/web/reactive/function/server/ServerResponse;>;", handlerInfo1.getMethodKey());
WebfluxHandlerInformation handlerInfo2 = getWebfluxHandler(addons, "@/person/ -- POST").get(0);
assertEquals("@/person/ -- POST", handlerInfo2.getSymbol());
assertEquals("org.test.PersonHandler", handlerInfo2.getDestinationClass());
assertEquals("Lorg/test/PersonHandler;.createPerson(Lorg/springframework/web/reactive/function/server/ServerRequest;)Lreactor/core/publisher/Mono<Lorg/springframework/web/reactive/function/server/ServerResponse;>;", handlerInfo2.getMethodKey());
WebfluxHandlerInformation handlerInfo3 = getWebfluxHandler(addons, "@/person -- GET").get(0);
assertEquals("@/person -- GET", handlerInfo3.getSymbol());
assertEquals("org.test.PersonHandler", handlerInfo3.getDestinationClass());
assertEquals("Lorg/test/PersonHandler;.listPeople(Lorg/springframework/web/reactive/function/server/ServerRequest;)Lreactor/core/publisher/Mono<Lorg/springframework/web/reactive/function/server/ServerResponse;>;", handlerInfo3.getMethodKey());
}
private boolean containsSymbol(List<? extends SymbolInformation> symbols, String name, String uri, int startLine, int startCHaracter, int endLine, int endCharacter) {
@@ -94,4 +141,17 @@ public class WebFluxMappingSymbolProviderTest {
private List<? extends SymbolInformation> getSymbols(String docUri) {
return harness.getServerWrapper().getComponents().getSpringIndexer().getSymbols(docUri);
}
private List<? extends Object> getAdditionalInformation(String docUri) {
return harness.getServerWrapper().getComponents().getSpringIndexer().getAdditonalInformation(docUri);
}
private List<WebfluxHandlerInformation> getWebfluxHandler(List<? extends Object> addons, String symbol) {
return addons.stream()
.filter((obj) -> obj instanceof WebfluxHandlerInformation)
.map((obj -> (WebfluxHandlerInformation) obj))
.filter((addon) -> addon.getSymbol().equals(symbol))
.collect(Collectors.toList());
}
}