GH-1041: replaced webflux symbol addon information objects with new index child nodes

some additional groundwork for nested structure inside of spring index, in support of GH-1425, GH-1431, GH-1424
This commit is contained in:
Martin Lippert
2025-01-15 14:27:25 +01:00
parent c1b1a06fba
commit 21accaebf3
17 changed files with 465 additions and 333 deletions

View File

@@ -0,0 +1,28 @@
/*******************************************************************************
* Copyright (c) 2024 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;
public abstract class AbstractSpringIndexElement implements SpringIndexElement {
public static final SpringIndexElement[] NO_CHILDREN = new SpringIndexElement[0];
private final SpringIndexElement[] children;
public AbstractSpringIndexElement(SpringIndexElement[] children) {
this.children = children != null ? children : NO_CHILDREN;
}
@Override
public SpringIndexElement[] getChildren() {
return children;
}
}

View File

@@ -16,7 +16,7 @@ import org.eclipse.lsp4j.Location;
import com.google.gson.Gson;
public class Bean {
public class Bean extends AbstractSpringIndexElement {
private final String name;
private final String type;
@@ -32,7 +32,11 @@ public class Bean {
Location location,
InjectionPoint[] injectionPoints,
Set<String> supertypes,
AnnotationMetadata[] annotations, boolean isConfiguration) {
AnnotationMetadata[] annotations,
boolean isConfiguration,
SpringIndexElement[] children) {
super(children);
this.name = name;
this.type = type;
@@ -64,6 +68,18 @@ public class Bean {
}
}
public Bean(
String name,
String type,
Location location,
InjectionPoint[] injectionPoints,
Set<String> supertypes,
AnnotationMetadata[] annotations,
boolean isConfiguration) {
this(name, type, location, injectionPoints, supertypes, annotations, isConfiguration, AbstractSpringIndexElement.NO_CHILDREN);
}
public String getName() {
return name;
}

View File

@@ -0,0 +1,17 @@
/*******************************************************************************
* Copyright (c) 2024 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;
public interface SpringIndexElement {
SpringIndexElement[] getChildren();
}

View File

@@ -21,7 +21,6 @@ import org.springframework.ide.vscode.boot.java.beans.FeignClientSymbolProvider;
import org.springframework.ide.vscode.boot.java.data.DataRepositorySymbolProvider;
import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider;
import org.springframework.ide.vscode.boot.java.requestmapping.RequestMappingSymbolProvider;
import org.springframework.ide.vscode.boot.java.requestmapping.WebfluxRouterSymbolProvider;
import org.springframework.ide.vscode.boot.java.utils.RestrictedDefaultSymbolProvider;
@Configuration(proxyBeanMethods = false)
@@ -36,7 +35,6 @@ public class SpringSymbolIndexerConfig {
ComponentSymbolProvider componentSymbolProvider = new ComponentSymbolProvider();
RestrictedDefaultSymbolProvider restrictedDefaultSymbolProvider = new RestrictedDefaultSymbolProvider();
DataRepositorySymbolProvider dataRepositorySymbolProvider = new DataRepositorySymbolProvider();
WebfluxRouterSymbolProvider webfluxRouterSymbolProvider = new WebfluxRouterSymbolProvider();
providers.put(Annotations.SPRING_REQUEST_MAPPING, requestMappingSymbolProvider);
providers.put(Annotations.SPRING_GET_MAPPING, requestMappingSymbolProvider);
@@ -72,7 +70,6 @@ public class SpringSymbolIndexerConfig {
providers.put(Annotations.CONDITIONAL_ON_SINGLE_CANDIDATE, restrictedDefaultSymbolProvider);
providers.put(Annotations.REPOSITORY, dataRepositorySymbolProvider);
providers.put("", webfluxRouterSymbolProvider);
providers.put(Annotations.FEIGN_CLIENT, new FeignClientSymbolProvider());

View File

@@ -46,6 +46,7 @@ import org.springframework.ide.vscode.commons.protocol.spring.AnnotationMetadata
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
import org.springframework.ide.vscode.commons.protocol.spring.DefaultValues;
import org.springframework.ide.vscode.commons.protocol.spring.InjectionPoint;
import org.springframework.ide.vscode.commons.protocol.spring.SpringIndexElement;
import org.springframework.ide.vscode.commons.util.UriUtil;
import com.google.common.collect.ImmutableMultimap;
@@ -374,6 +375,7 @@ public class IndexCacheOnDiscDeltaBased implements IndexCache {
.registerTypeAdapter(Bean.class, new BeanJsonAdapter())
.registerTypeAdapter(InjectionPoint.class, new InjectionPointJsonAdapter())
.registerTypeAdapter(IndexCacheStore.class, new IndexCacheStoreAdapter())
.registerTypeAdapter(SpringIndexElement.class, new SpringIndexElementAdapter())
.create();
}
@@ -575,6 +577,7 @@ public class IndexCacheOnDiscDeltaBased implements IndexCache {
// GSON serialize / deserialize adapters for the various types involved here that have special needs around JSON
//
//
private static class IndexCacheStoreAdapter implements JsonDeserializer<IndexCacheStore<?>> {
@@ -610,9 +613,6 @@ public class IndexCacheOnDiscDeltaBased implements IndexCache {
}
/**
* gson adapter to store subtype information for symbol addon informations
*/
private static class DeltaStorageAdapter implements JsonSerializer<DeltaStorage<?>>, JsonDeserializer<DeltaStorage<?>> {
@Override
@@ -637,9 +637,6 @@ public class IndexCacheOnDiscDeltaBased implements IndexCache {
}
}
/**
* gson adapter to store subtype information for symbol addon informations
*/
private static class SymbolAddOnInformationAdapter implements JsonSerializer<SymbolAddOnInformation>, JsonDeserializer<SymbolAddOnInformation> {
@Override
@@ -664,9 +661,6 @@ public class IndexCacheOnDiscDeltaBased implements IndexCache {
}
}
/**
* gson adapter to store subtype information for beans
*/
private static class BeanJsonAdapter implements JsonDeserializer<Bean> {
@Override
@@ -690,8 +684,11 @@ public class IndexCacheOnDiscDeltaBased implements IndexCache {
JsonElement isConfigurationObject = parsedObject.get("isConfiguration");
boolean isConfiguration = context.deserialize(isConfigurationObject, boolean.class);
JsonElement childrenObject = parsedObject.get("children");
SpringIndexElement[] children = context.deserialize(childrenObject, SpringIndexElement[].class);
return new Bean(beanName, beanType, location, injectionPoints, supertypes, annotations, isConfiguration);
return new Bean(beanName, beanType, location, injectionPoints, supertypes, annotations, isConfiguration, children);
}
}
@@ -714,4 +711,27 @@ public class IndexCacheOnDiscDeltaBased implements IndexCache {
}
}
private static class SpringIndexElementAdapter implements JsonSerializer<SpringIndexElement>, JsonDeserializer<SpringIndexElement> {
@Override
public JsonElement serialize(SpringIndexElement element, Type typeOfSrc, JsonSerializationContext context) {
JsonElement elem = context.serialize(element);
elem.getAsJsonObject().addProperty("type", element.getClass().getName());
return elem;
}
@Override
public SpringIndexElement deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
JsonObject jsonObject = json.getAsJsonObject();
String typeName = jsonObject.get("type").getAsString();
try {
return context.deserialize(jsonObject, (Class<?>) Class.forName(typeName));
} catch (ClassNotFoundException e) {
throw new JsonParseException(e);
}
}
}
}

View File

@@ -187,7 +187,7 @@ public class BootJavaLanguageServerComponents implements LanguageServerComponent
spelSemanticTokens = appContext.getBean(SpelSemanticTokens.class);
codeLensHandler = createCodeLensEngine(springSymbolIndex, projectFinder, server, spelSemanticTokens);
codeLensHandler = createCodeLensEngine(springIndex, projectFinder, server, spelSemanticTokens);
highlightsEngine = createDocumentHighlightEngine(appContext);
documents.onDocumentHighlight(highlightsEngine);
@@ -328,9 +328,9 @@ public class BootJavaLanguageServerComponents implements LanguageServerComponent
return new BootJavaReferencesHandler(this, cuCache, projectFinder, providers);
}
protected BootJavaCodeLensEngine createCodeLensEngine(SpringSymbolIndex index, JavaProjectFinder projectFinder, SimpleLanguageServer server, SpelSemanticTokens spelSemanticTokens) {
protected BootJavaCodeLensEngine createCodeLensEngine(SpringMetamodelIndex springIndex, JavaProjectFinder projectFinder, SimpleLanguageServer server, SpelSemanticTokens spelSemanticTokens) {
Collection<CodeLensProvider> codeLensProvider = new ArrayList<>();
codeLensProvider.add(new WebfluxHandlerCodeLensProvider(index));
codeLensProvider.add(new WebfluxHandlerCodeLensProvider(springIndex));
codeLensProvider.add(new CopilotCodeLensProvider(projectFinder, server, spelSemanticTokens));
return new BootJavaCodeLensEngine(this, codeLensProvider);
@@ -338,7 +338,7 @@ public class BootJavaLanguageServerComponents implements LanguageServerComponent
protected BootJavaDocumentHighlightEngine createDocumentHighlightEngine(ApplicationContext appContext) {
Collection<HighlightProvider> highlightProvider = new ArrayList<>();
highlightProvider.add(new WebfluxRouteHighlightProdivder(appContext.getBean(SpringSymbolIndex.class)));
highlightProvider.add(new WebfluxRouteHighlightProdivder(appContext.getBean(SpringMetamodelIndex.class)));
Map<String, JdtAstDocHighlightsProvider> astHighlightProviders = appContext.getBeansOfType(JdtAstDocHighlightsProvider.class);
if (!astHighlightProviders.isEmpty()) {

View File

@@ -10,6 +10,7 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.beans;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
@@ -34,13 +35,16 @@ import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.java.Annotations;
import org.springframework.ide.vscode.boot.java.handlers.AbstractSymbolProvider;
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
import org.springframework.ide.vscode.boot.java.requestmapping.WebfluxRouterSymbolProvider;
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.FunctionUtils;
import org.springframework.ide.vscode.boot.java.utils.SpringIndexerJavaContext;
import org.springframework.ide.vscode.boot.java.utils.SpringIndexerJava.SCAN_PASS;
import org.springframework.ide.vscode.commons.protocol.spring.AnnotationMetadata;
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
import org.springframework.ide.vscode.commons.protocol.spring.InjectionPoint;
import org.springframework.ide.vscode.commons.protocol.spring.SpringIndexElement;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.text.DocumentRegion;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
@@ -57,13 +61,12 @@ import reactor.util.function.Tuples;
*/
public class BeansSymbolProvider extends AbstractSymbolProvider {
private static final Logger log = LoggerFactory.getLogger(BeansSymbolProvider.class);
private static final String[] NAME_ATTRIBUTES = {"value", "name"};
@Override
protected void addSymbolsPass1(Annotation node, ITypeBinding annotationType, Collection<ITypeBinding> metaAnnotations, SpringIndexerJavaContext context, TextDocument doc) {
public void addSymbols(Annotation node, ITypeBinding typeBinding, Collection<ITypeBinding> metaAnnotations, SpringIndexerJavaContext context, TextDocument doc) {
if (node == null) return;
ASTNode parent = node.getParent();
@@ -73,7 +76,22 @@ public class BeansSymbolProvider extends AbstractSymbolProvider {
if (isMethodAbstract(method)) return;
boolean isWebfluxRouter = WebfluxRouterSymbolProvider.isWebfluxRouterBean(method);
// for webflux details, we need full method body ASTs
if (isWebfluxRouter && SCAN_PASS.ONE.equals(context.getPass())) {
context.getNextPassFiles().add(context.getFile());
return;
}
List<SpringIndexElement> childElements = new ArrayList<>();
if (isWebfluxRouter) {
WebfluxRouterSymbolProvider.createWebfluxElements(method, context, doc, childElements);
}
boolean isFunction = isFunctionBean(method);
ITypeBinding beanType = getBeanType(method);
String markerString = getAnnotations(method);
@@ -97,7 +115,7 @@ public class BeansSymbolProvider extends AbstractSymbolProvider {
Collection<Annotation> annotationsOnMethod = ASTUtils.getAnnotations(method);
AnnotationMetadata[] annotations = ASTUtils.getAnnotationsMetadata(annotationsOnMethod, doc);
Bean beanDefinition = new Bean(nameAndRegion.getT1(), beanType.getQualifiedName(), location, injectionPoints, supertypes, annotations, false);
Bean beanDefinition = new Bean(nameAndRegion.getT1(), beanType.getQualifiedName(), location, injectionPoints, supertypes, annotations, false, childElements.toArray(SpringIndexElement[]::new));
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), enhancedSymbol));
context.getBeans().add(new CachedBean(context.getDocURI(), beanDefinition));

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2018, 2021 Pivotal, Inc.
* Copyright (c) 2018, 2024 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
@@ -9,7 +9,7 @@
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.requestmapping;
import java.util.Arrays;
import java.util.List;
import org.eclipse.jdt.core.dom.ASTVisitor;
@@ -19,9 +19,9 @@ import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.lsp4j.CodeLens;
import org.eclipse.lsp4j.Command;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import org.springframework.ide.vscode.boot.app.SpringSymbolIndex;
import org.springframework.ide.vscode.boot.index.SpringMetamodelIndex;
import org.springframework.ide.vscode.boot.java.handlers.CodeLensProvider;
import org.springframework.ide.vscode.boot.java.handlers.SymbolAddOnInformation;
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
@@ -30,10 +30,10 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument;
*/
public class WebfluxHandlerCodeLensProvider implements CodeLensProvider {
private final SpringSymbolIndex springIndexer;
private final SpringMetamodelIndex springIndex;
public WebfluxHandlerCodeLensProvider(SpringSymbolIndex springIndexer) {
this.springIndexer = springIndexer;
public WebfluxHandlerCodeLensProvider(SpringMetamodelIndex springIndex) {
this.springIndex = springIndex;
}
@Override
@@ -59,21 +59,11 @@ public class WebfluxHandlerCodeLensProvider implements CodeLensProvider {
final String handlerMethod = methodBinding.getMethodDeclaration().toString().trim();
cancelToken.checkCanceled();
List<SymbolAddOnInformation> handlerInfos = this.springIndexer.getAllAdditionalInformation((addon) -> {
if (addon instanceof WebfluxHandlerInformation) {
WebfluxHandlerInformation handlerInfo = (WebfluxHandlerInformation) addon;
return handlerInfo.getHandlerClass() != null && handlerInfo.getHandlerClass().equals(handlerClass)
&& handlerInfo.getHandlerMethod() != null && handlerInfo.getHandlerMethod().equals(handlerMethod);
}
return false;
});
if (handlerInfos != null && handlerInfos.size() > 0) {
for (Object object : handlerInfos) {
List<WebfluxHandlerMethodIndexElement> matchingHandlerMethods = findMatchingHandlerMethogs(handlerClass, handlerMethod);
if (matchingHandlerMethods.size() > 0) {
for (WebfluxHandlerMethodIndexElement handlerInfo : matchingHandlerMethods) {
try {
WebfluxHandlerInformation handlerInfo = (WebfluxHandlerInformation) object;
CodeLens codeLens = new CodeLens();
codeLens.setRange(document.toRange(node.getName().getStartPosition(), node.getName().getLength()));
@@ -101,4 +91,16 @@ public class WebfluxHandlerCodeLensProvider implements CodeLensProvider {
}
}
private List<WebfluxHandlerMethodIndexElement> findMatchingHandlerMethogs(String handlerClass, String handlerMethod) {
Bean[] beans = springIndex.getBeans();
return Arrays.stream(beans)
.flatMap(bean -> Arrays.stream(bean.getChildren()))
.filter(element -> element instanceof WebfluxHandlerMethodIndexElement)
.map(element -> (WebfluxHandlerMethodIndexElement) element)
.filter(webfluxElement -> webfluxElement.getHandlerClass() != null && webfluxElement.getHandlerClass().equals(handlerClass)
&& webfluxElement.getHandlerMethod() != null && webfluxElement.getHandlerMethod().equals(handlerMethod))
.toList();
}
}

View File

@@ -1,22 +1,19 @@
/*******************************************************************************
* Copyright (c) 2018 Pivotal, Inc.
* Copyright (c) 2024 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:
* Pivotal, Inc. - initial API and implementation
* Broadcom - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.requestmapping;
import org.springframework.ide.vscode.boot.java.handlers.SymbolAddOnInformation;
import org.springframework.ide.vscode.commons.protocol.spring.AbstractSpringIndexElement;
public class WebfluxHandlerMethodIndexElement extends AbstractSpringIndexElement {
/**
* @author Martin Lippert
*/
public class WebfluxHandlerInformation implements SymbolAddOnInformation {
private final String handlerClass;
private final String handlerMethod;
@@ -25,7 +22,9 @@ public class WebfluxHandlerInformation implements SymbolAddOnInformation {
private final String[] contentTypes;
private final String[] acceptTypes;
public WebfluxHandlerInformation(String handlerClass, String handlerMethod, String path, String[] httpMethods, String[] contentTypes, String[] acceptTypes) {
public WebfluxHandlerMethodIndexElement(String handlerClass, String handlerMethod, String path, String[] httpMethods, String[] contentTypes, String[] acceptTypes) {
super(AbstractSpringIndexElement.NO_CHILDREN);
this.handlerClass = handlerClass;
this.handlerMethod = handlerMethod;

View File

@@ -1,30 +1,30 @@
/*******************************************************************************
* Copyright (c) 2018 Pivotal, Inc.
* Copyright (c) 2024 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:
* Pivotal, Inc. - initial API and implementation
* Broadcom - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.requestmapping;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.springframework.ide.vscode.boot.java.handlers.SymbolAddOnInformation;
import org.springframework.ide.vscode.commons.protocol.spring.AbstractSpringIndexElement;
public class WebfluxRouteElementRangesIndexElement extends AbstractSpringIndexElement {
private static final Range[] NO_RANGES = new Range[0];
/**
* @author Martin Lippert
*/
public class WebfluxElementsInformation implements SymbolAddOnInformation {
private Range[] ranges;
public WebfluxElementsInformation(Range... ranges) {
this.ranges = ranges;
public WebfluxRouteElementRangesIndexElement(Range... ranges) {
super(AbstractSpringIndexElement.NO_CHILDREN);
this.ranges = ranges != null ? ranges : NO_RANGES;
}
public Range[] getRanges() {
return ranges;
}
@@ -35,10 +35,10 @@ public class WebfluxElementsInformation implements SymbolAddOnInformation {
return true;
}
}
return false;
}
/**
* returns true if position1 is the same or before position2 in a document
*/

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2018, 2019 Pivotal, Inc.
* Copyright (c) 2018, 2024 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
@@ -18,8 +18,9 @@ import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.app.SpringSymbolIndex;
import org.springframework.ide.vscode.boot.index.SpringMetamodelIndex;
import org.springframework.ide.vscode.boot.java.handlers.HighlightProvider;
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
/**
@@ -29,10 +30,10 @@ public class WebfluxRouteHighlightProdivder implements HighlightProvider {
private static final Logger log = LoggerFactory.getLogger(WebfluxRouteHighlightProdivder.class);
private final SpringSymbolIndex springIndexer;
private final SpringMetamodelIndex springIndex;
public WebfluxRouteHighlightProdivder(SpringSymbolIndex indexer) {
this.springIndexer = indexer;
public WebfluxRouteHighlightProdivder(SpringMetamodelIndex springIndex) {
this.springIndex = springIndex;
}
@Override
@@ -41,19 +42,13 @@ public class WebfluxRouteHighlightProdivder implements HighlightProvider {
cancelToken.checkCanceled();
this.springIndexer.getAdditonalInformation(document.getUri())
.stream()
.filter(addon -> {
if (addon instanceof WebfluxElementsInformation) {
WebfluxElementsInformation handlerInfo = (WebfluxElementsInformation) addon;
if (handlerInfo.contains(position)) {
return true;
}
}
return false;
})
.flatMap(addon -> Arrays.asList(((WebfluxElementsInformation) addon).getRanges()).stream())
Bean[] beans = springIndex.getBeans();
Arrays.stream(beans)
.flatMap(bean -> Arrays.stream(bean.getChildren()))
.filter(element -> element instanceof WebfluxRouteElementRangesIndexElement)
.map(element -> (WebfluxRouteElementRangesIndexElement) element)
.filter(rangesElement -> rangesElement.contains(position))
.flatMap(rangesElement -> Arrays.stream(rangesElement.getRanges()))
.forEach(range -> resultAccumulator.add(new DocumentHighlight(range)));
}

View File

@@ -32,24 +32,42 @@ import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.Range;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.java.handlers.AbstractSymbolProvider;
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
import org.springframework.ide.vscode.boot.java.handlers.SymbolAddOnInformation;
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.SpringIndexerJava.SCAN_PASS;
import org.springframework.ide.vscode.boot.java.utils.SpringIndexerJavaContext;
import org.springframework.ide.vscode.commons.protocol.spring.SpringIndexElement;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
/**
* @author Martin Lippert
*/
public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider {
public class WebfluxRouterSymbolProvider {
private static final Logger log = LoggerFactory.getLogger(WebfluxRouterSymbolProvider.class);
public static boolean isWebfluxRouterBean(MethodDeclaration method) {
Type returnType = method.getReturnType2();
if (returnType != null) {
ITypeBinding resolvedBinding = returnType.resolveBinding();
if (resolvedBinding != null && WebfluxUtils.ROUTER_FUNCTION_TYPE.equals(resolvedBinding.getBinaryName())) {
return true;
}
}
return false;
}
public static SpringIndexElement[] createWebfluxElements(MethodDeclaration methodDeclaration, SpringIndexerJavaContext context, TextDocument doc, List<SpringIndexElement> childElements) {
Block methodBody = methodDeclaration.getBody();
if (methodBody != null && methodBody.statements() != null && methodBody.statements().size() > 0) {
addSymbolsForRouterFunction(methodBody, context, doc, childElements);
}
return new SpringIndexElement[0];
}
@Override
public void addSymbols(MethodDeclaration methodDeclaration, SpringIndexerJavaContext context, TextDocument doc) {
Type returnType = methodDeclaration.getReturnType2();
if (returnType != null) {
@@ -60,7 +78,7 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider {
Block methodBody = methodDeclaration.getBody();
if (methodBody != null && methodBody.statements() != null && methodBody.statements().size() > 0) {
addSymbolsForRouterFunction(methodBody, context, doc);
addSymbolsForRouterFunction(methodBody, context, doc, new ArrayList<>());
}
else if (SCAN_PASS.ONE.equals(context.getPass())) {
context.getNextPassFiles().add(context.getFile());
@@ -70,7 +88,7 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider {
}
}
private void addSymbolsForRouterFunction(Block methodBody, SpringIndexerJavaContext context, TextDocument doc) {
private static void addSymbolsForRouterFunction(Block methodBody, SpringIndexerJavaContext context, TextDocument doc, List<SpringIndexElement> indexElementsCollector) {
methodBody.accept(new ASTVisitor() {
@Override
@@ -78,7 +96,7 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider {
IMethodBinding methodBinding = node.resolveMethodBinding();
if (methodBinding != null && WebfluxUtils.isRouteMethodInvocation(methodBinding)) {
extractMappingSymbol(node, doc, context);
extractMappingSymbol(node, doc, context, indexElementsCollector);
}
return super.visit(node);
@@ -87,7 +105,7 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider {
});
}
protected void extractMappingSymbol(MethodInvocation node, TextDocument doc, SpringIndexerJavaContext context) {
protected static void extractMappingSymbol(MethodInvocation node, TextDocument doc, SpringIndexerJavaContext context, List<SpringIndexElement> indexElementsCollector) {
WebfluxRouteElement[] pathElements = extractPath(node, doc);
WebfluxRouteElement[] httpMethods = extractMethods(node, doc);
WebfluxRouteElement[] contentTypes = extractContentTypes(node, doc);
@@ -107,15 +125,14 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider {
try {
Location location = new Location(doc.getUri(), doc.toRange(methodNameStart, node.getLength() - (methodNameStart - invocationStart)));
WebfluxHandlerInformation handler = extractHandlerInformation(node, path, httpMethods, contentTypes, acceptTypes);
WebfluxElementsInformation elements = extractElementsInformation(pathElements, httpMethods, contentTypes, acceptTypes);
WebfluxHandlerMethodIndexElement handler = extractHandlerInformation(node, path, httpMethods, contentTypes, acceptTypes);
WebfluxRouteElementRangesIndexElement elements = extractElementsInformation(pathElements, httpMethods, contentTypes, acceptTypes);
if (handler != null) indexElementsCollector.add(handler);
if (elements != null) indexElementsCollector.add(elements);
SymbolAddOnInformation[] addon = handler != null ?
new SymbolAddOnInformation[] {handler, elements} :
new SymbolAddOnInformation[] {elements};
EnhancedSymbolInformation enhancedSymbol = RouteUtils.createRouteSymbol(location, path, getElementStrings(httpMethods),
getElementStrings(contentTypes), getElementStrings(acceptTypes), addon);
getElementStrings(contentTypes), getElementStrings(acceptTypes), null);
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), enhancedSymbol));
@@ -125,7 +142,7 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider {
}
}
private WebfluxElementsInformation extractElementsInformation(WebfluxRouteElement[] path, WebfluxRouteElement[] methods,
private static WebfluxRouteElementRangesIndexElement extractElementsInformation(WebfluxRouteElement[] path, WebfluxRouteElement[] methods,
WebfluxRouteElement[] contentTypes, WebfluxRouteElement[] acceptTypes) {
List<Range> allRanges = new ArrayList<>();
@@ -136,10 +153,10 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider {
}
}
return new WebfluxElementsInformation((Range[]) allRanges.toArray(new Range[allRanges.size()]));
return new WebfluxRouteElementRangesIndexElement((Range[]) allRanges.toArray(new Range[allRanges.size()]));
}
private WebfluxRouteElement[] extractPath(MethodInvocation routerInvocation, TextDocument doc) {
private static WebfluxRouteElement[] extractPath(MethodInvocation routerInvocation, TextDocument doc) {
WebfluxPathFinder pathFinder = new WebfluxPathFinder(routerInvocation, doc);
List<?> arguments = routerInvocation.arguments();
for (Object argument : arguments) {
@@ -171,7 +188,7 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider {
return (WebfluxRouteElement[]) path.toArray(new WebfluxRouteElement[path.size()]);
}
private WebfluxRouteElement[] extractMethods(MethodInvocation routerInvocation, TextDocument doc) {
private static WebfluxRouteElement[] extractMethods(MethodInvocation routerInvocation, TextDocument doc) {
WebfluxMethodFinder methodFinder = new WebfluxMethodFinder(routerInvocation, doc);
List<?> arguments = routerInvocation.arguments();
for (Object argument : arguments) {
@@ -204,7 +221,7 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider {
return (WebfluxRouteElement[]) methods.toArray(new WebfluxRouteElement[methods.size()]);
}
private WebfluxRouteElement[] extractAcceptTypes(MethodInvocation routerInvocation, TextDocument doc) {
private static WebfluxRouteElement[] extractAcceptTypes(MethodInvocation routerInvocation, TextDocument doc) {
WebfluxAcceptTypeFinder typeFinder = new WebfluxAcceptTypeFinder(doc);
List<?> arguments = routerInvocation.arguments();
for (Object argument : arguments) {
@@ -237,7 +254,7 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider {
return (WebfluxRouteElement[]) acceptTypes.toArray(new WebfluxRouteElement[acceptTypes.size()]);
}
private WebfluxRouteElement[] extractContentTypes(MethodInvocation routerInvocation, TextDocument doc) {
private static WebfluxRouteElement[] extractContentTypes(MethodInvocation routerInvocation, TextDocument doc) {
WebfluxContentTypeFinder contentTypeFinder = new WebfluxContentTypeFinder(doc);
List<?> arguments = routerInvocation.arguments();
for (Object argument : arguments) {
@@ -270,7 +287,7 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider {
return (WebfluxRouteElement[]) contentTypes.toArray(new WebfluxRouteElement[contentTypes.size()]);
}
private void extractNestedValue(ASTNode node, Collection<WebfluxRouteElement> values, Function<MethodInvocation, WebfluxRouteElement> extractor) {
private static void extractNestedValue(ASTNode node, Collection<WebfluxRouteElement> values, Function<MethodInvocation, WebfluxRouteElement> extractor) {
if (node == null || node instanceof TypeDeclaration) {
return;
}
@@ -301,7 +318,7 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider {
extractNestedValue(node.getParent(), values, extractor);
}
private WebfluxHandlerInformation extractHandlerInformation(MethodInvocation node, String path, WebfluxRouteElement[] httpMethods,
private static WebfluxHandlerMethodIndexElement extractHandlerInformation(MethodInvocation node, String path, WebfluxRouteElement[] httpMethods,
WebfluxRouteElement[] contentTypes, WebfluxRouteElement[] acceptTypes) {
List<?> arguments = node.arguments();
@@ -319,7 +336,7 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider {
String handlerMethod = methodBinding.getMethodDeclaration().toString();
if (handlerMethod != null) handlerMethod = handlerMethod.trim();
return new WebfluxHandlerInformation(handlerClass, handlerMethod, path, getElementStrings(httpMethods), getElementStrings(contentTypes), getElementStrings(acceptTypes));
return new WebfluxHandlerMethodIndexElement(handlerClass, handlerMethod, path, getElementStrings(httpMethods), getElementStrings(contentTypes), getElementStrings(acceptTypes));
}
}
}
@@ -328,7 +345,7 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider {
return null;
}
private String[] getElementStrings(WebfluxRouteElement[] routeElements) {
private static String[] getElementStrings(WebfluxRouteElement[] routeElements) {
List<String> result = new ArrayList<>();
for (int i = 0; i < routeElements.length; i++) {

View File

@@ -40,8 +40,6 @@ import org.springframework.ide.vscode.boot.index.cache.AbstractIndexCacheable;
import org.springframework.ide.vscode.boot.index.cache.IndexCacheKey;
import org.springframework.ide.vscode.boot.index.cache.IndexCacheOnDiscDeltaBased;
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
import org.springframework.ide.vscode.boot.java.handlers.SymbolAddOnInformation;
import org.springframework.ide.vscode.boot.java.requestmapping.WebfluxElementsInformation;
import org.springframework.ide.vscode.boot.java.utils.CachedSymbol;
import org.springframework.ide.vscode.commons.util.UriUtil;
@@ -257,44 +255,6 @@ public class IndexCacheOnDiscDeltaBasedTest {
assertTrue(Files.exists(tempDir.resolve(Paths.get(key1.toString() + STORAGE_FILE_EXTENSION))));
}
@Test
void testEnhancedInformationSubclasses() throws Exception {
Path file1 = Paths.get(tempDir.toAbsolutePath().toString(), "tempFile1");
Files.createFile(file1);
FileTime timeFile1 = Files.getLastModifiedTime(file1);
String[] files = {file1.toString()};
String doc1URI = UriUtil.toUri(file1.toFile()).toString();
List<CachedSymbol> generatedSymbols = new ArrayList<>();
WorkspaceSymbol symbol = new WorkspaceSymbol("symbol1", SymbolKind.Field, Either.forLeft(new Location(doc1URI, new Range(new Position(3, 10), new Position(3, 20)))));
WebfluxElementsInformation addon = new WebfluxElementsInformation(new Range(new Position(4, 4), new Position(5, 5)), new Range(new Position(6, 6), new Position(7, 7)));
EnhancedSymbolInformation enhancedSymbol = new EnhancedSymbolInformation(symbol, new SymbolAddOnInformation[]{addon});
generatedSymbols.add(new CachedSymbol(doc1URI, timeFile1.toMillis(), enhancedSymbol));
cache.store(CACHE_KEY_VERSION_1, files, generatedSymbols, null, CachedSymbol.class);
CachedSymbol[] cachedSymbols = cache.retrieveSymbols(CACHE_KEY_VERSION_1, files, CachedSymbol.class);
assertNotNull(cachedSymbols);
assertEquals(1, cachedSymbols.length);
assertEquals("symbol1", cachedSymbols[0].getEnhancedSymbol().getSymbol().getName());
assertEquals(SymbolKind.Field, cachedSymbols[0].getEnhancedSymbol().getSymbol().getKind());
assertEquals(new Location(doc1URI, new Range(new Position(3, 10), new Position(3, 20))), cachedSymbols[0].getEnhancedSymbol().getSymbol().getLocation().getLeft());
SymbolAddOnInformation[] retrievedAddOns = cachedSymbols[0].getEnhancedSymbol().getAdditionalInformation();
assertNotNull(retrievedAddOns);
assertEquals(1, retrievedAddOns.length);
assertTrue(retrievedAddOns[0] instanceof WebfluxElementsInformation);
Range[] ranges = ((WebfluxElementsInformation) retrievedAddOns[0]).getRanges();
assertEquals(2, ranges.length);
assertEquals(new Range(new Position(4, 4), new Position(5, 5)), ranges[0]);
assertEquals(new Range(new Position(6, 6), new Position(7, 7)), ranges[1]);
}
@Test
void testSymbolAddedToExistingFile() throws Exception {
Path file1 = Paths.get(tempDir.toAbsolutePath().toString(), "tempFile1");

View File

@@ -40,8 +40,6 @@ import org.springframework.ide.vscode.boot.index.cache.AbstractIndexCacheable;
import org.springframework.ide.vscode.boot.index.cache.IndexCacheKey;
import org.springframework.ide.vscode.boot.index.cache.IndexCacheOnDisc;
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
import org.springframework.ide.vscode.boot.java.handlers.SymbolAddOnInformation;
import org.springframework.ide.vscode.boot.java.requestmapping.WebfluxElementsInformation;
import org.springframework.ide.vscode.boot.java.utils.CachedSymbol;
import org.springframework.ide.vscode.commons.util.UriUtil;
@@ -255,44 +253,6 @@ public class IndexCacheOnDiscTest {
assertTrue(Files.exists(tempDir.resolve(Paths.get(key1.toString() + ".json"))));
}
@Test
void testEnhancedInformationSubclasses() throws Exception {
Path file1 = Paths.get(tempDir.toAbsolutePath().toString(), "tempFile1");
Files.createFile(file1);
FileTime timeFile1 = Files.getLastModifiedTime(file1);
String[] files = {file1.toString()};
String doc1URI = UriUtil.toUri(file1.toFile()).toString();
List<CachedSymbol> generatedSymbols = new ArrayList<>();
WorkspaceSymbol symbol = new WorkspaceSymbol("symbol1", SymbolKind.Field, Either.forLeft(new Location(doc1URI, new Range(new Position(3, 10), new Position(3, 20)))));
WebfluxElementsInformation addon = new WebfluxElementsInformation(new Range(new Position(4, 4), new Position(5, 5)), new Range(new Position(6, 6), new Position(7, 7)));
EnhancedSymbolInformation enhancedSymbol = new EnhancedSymbolInformation(symbol, new SymbolAddOnInformation[]{addon});
generatedSymbols.add(new CachedSymbol(doc1URI, timeFile1.toMillis(), enhancedSymbol));
cache.store(CACHE_KEY_VERSION_1, files, generatedSymbols, null, CachedSymbol.class);
CachedSymbol[] cachedSymbols = cache.retrieveSymbols(CACHE_KEY_VERSION_1, files, CachedSymbol.class);
assertNotNull(cachedSymbols);
assertEquals(1, cachedSymbols.length);
assertEquals("symbol1", cachedSymbols[0].getEnhancedSymbol().getSymbol().getName());
assertEquals(SymbolKind.Field, cachedSymbols[0].getEnhancedSymbol().getSymbol().getKind());
assertEquals(new Location(doc1URI, new Range(new Position(3, 10), new Position(3, 20))), cachedSymbols[0].getEnhancedSymbol().getSymbol().getLocation().getLeft());
SymbolAddOnInformation[] retrievedAddOns = cachedSymbols[0].getEnhancedSymbol().getAdditionalInformation();
assertNotNull(retrievedAddOns);
assertEquals(1, retrievedAddOns.length);
assertTrue(retrievedAddOns[0] instanceof WebfluxElementsInformation);
Range[] ranges = ((WebfluxElementsInformation) retrievedAddOns[0]).getRanges();
assertEquals(2, ranges.length);
assertEquals(new Range(new Position(4, 4), new Position(5, 5)), ranges[0]);
assertEquals(new Range(new Position(6, 6), new Position(7, 7)), ranges[1]);
}
@Test
void testSymbolAddedToExistingFile() throws Exception {
Path file1 = Paths.get(tempDir.toAbsolutePath().toString(), "tempFile1");

View File

@@ -29,12 +29,15 @@ import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.junit.jupiter.api.Test;
import org.springframework.ide.vscode.boot.index.SpringMetamodelIndex;
import org.springframework.ide.vscode.boot.index.cache.IndexCacheOnDisc;
import org.springframework.ide.vscode.boot.index.cache.IndexCacheOnDiscDeltaBased;
import org.springframework.ide.vscode.commons.protocol.spring.AbstractSpringIndexElement;
import org.springframework.ide.vscode.commons.protocol.spring.AnnotationAttributeValue;
import org.springframework.ide.vscode.commons.protocol.spring.AnnotationMetadata;
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
import org.springframework.ide.vscode.commons.protocol.spring.DefaultValues;
import org.springframework.ide.vscode.commons.protocol.spring.InjectionPoint;
import org.springframework.ide.vscode.commons.protocol.spring.RequestMapping;
import org.springframework.ide.vscode.commons.protocol.spring.SpringIndexElement;
import com.google.gson.Gson;
@@ -250,7 +253,7 @@ public class SpringMetamodelIndexTest {
Bean bean1 = new Bean("beanName1", "beanType", locationForDoc1, new InjectionPoint[] {point1, point2}, Set.of("supertype1", "supertype2"), emptyAnnotations, true);
String serialized = bean1.toString();
Gson gson = IndexCacheOnDisc.createGson();
Gson gson = IndexCacheOnDiscDeltaBased.createGson();
Bean deserializedBean = gson.fromJson(serialized, Bean.class);
assertEquals("beanName1", deserializedBean.getName());
@@ -301,7 +304,7 @@ public class SpringMetamodelIndexTest {
Bean bean1 = new Bean("beanName1", "beanType", locationForDoc1, emptyInjectionPoints, emptySupertypes, emptyAnnotations, false);
String serialized = bean1.toString();
Gson gson = IndexCacheOnDisc.createGson();
Gson gson = IndexCacheOnDiscDeltaBased.createGson();
Bean deserializedBean = gson.fromJson(serialized, Bean.class);
assertEquals("beanName1", deserializedBean.getName());
@@ -395,5 +398,90 @@ public class SpringMetamodelIndexTest {
matchingBeans = index.getMatchingBeans("otherProject", "supertype1");
}
@Test
void testBasicSpringIndexStructure() {
SubType1 child1 = new SubType1(AbstractSpringIndexElement.NO_CHILDREN);
SpringIndexElement[] children = new SpringIndexElement[] {child1};
Bean bean1 = new Bean("beanName1", "beanType1", locationForDoc1, emptyInjectionPoints, Set.of("supertype1", "supertype2"), emptyAnnotations, false, children);
SpringIndexElement[] children2 = bean1.getChildren();
assertEquals(1, children2.length);
assertSame(child1, children2[0]);
}
@Test
void testSpringIndexStructurePolymorphicSerialization() {
Gson gson = IndexCacheOnDiscDeltaBased.createGson();
SubType2 subNode = new SubType2(null);
SubType1 node1 = new SubType1(new SpringIndexElement[] {subNode});
SubType2 node2 = new SubType2(null);
Root root = new Root(new SpringIndexElement[] {node1, node2});
String json = gson.toJson(root);
Root deserializedRoot = gson.fromJson(json, Root.class);
SpringIndexElement[] children = deserializedRoot.getChildren();
assertEquals(2, children.length);
SubType1 deserializedNode1 = (SubType1) java.util.Arrays.stream(children).filter(node -> node instanceof SubType1).findAny().get();
SubType2 deserializedNode2 = (SubType2) java.util.Arrays.stream(children).filter(node -> node instanceof SubType2).findAny().get();
assertNotNull(deserializedNode1);
assertNotNull(deserializedNode2);
SpringIndexElement[] deserializedChild2 = deserializedNode1.getChildren();
assertEquals(1, deserializedChild2.length);
assertTrue(deserializedChild2[0] instanceof SubType2);
}
@Test
void testSerializeDeserializeBeansWithChildElements() {
Gson gson = IndexCacheOnDiscDeltaBased.createGson();
SubType2 childOfChild = new SubType2(null);
SubType1 child1 = new SubType1(new SpringIndexElement[] {childOfChild});
SubType2 child2 = new SubType2(null);
Bean bean1 = new Bean("beanName1", "beanType", locationForDoc1, emptyInjectionPoints, emptySupertypes, emptyAnnotations, true, new SpringIndexElement[] {child1, child2});
String serialized = gson.toJson(bean1);
Bean deserializedBean = gson.fromJson(serialized, Bean.class);
SpringIndexElement[] children = deserializedBean.getChildren();
assertEquals(2, children.length);
SpringIndexElement deserializedChild1 = java.util.Arrays.stream(children).filter(element -> element instanceof SubType1).findAny().get();
assertNotNull(deserializedChild1);
SpringIndexElement[] childrenOfChild = deserializedChild1.getChildren();
assertEquals(1, childrenOfChild.length);
assertTrue(childrenOfChild[0] instanceof SubType2);
SpringIndexElement deserializedChild2 = java.util.Arrays.stream(children).filter(element -> element instanceof SubType2).findAny().get();
assertNotNull(deserializedChild2);
assertEquals(0, deserializedChild2.getChildren().length);
}
static class SubType1 extends AbstractSpringIndexElement {
public SubType1(SpringIndexElement[] children) {
super(children);
}
}
static class SubType2 extends AbstractSpringIndexElement {
public SubType2(SpringIndexElement[] children) {
super(children);
}
}
static class Root extends AbstractSpringIndexElement {
public Root(SpringIndexElement[] children) {
super(children);
}
}
}

View File

@@ -32,10 +32,11 @@ import org.springframework.ide.vscode.boot.app.SpringSymbolIndex;
import org.springframework.ide.vscode.boot.bootiful.BootLanguageServerTest;
import org.springframework.ide.vscode.boot.bootiful.SymbolProviderTestConf;
import org.springframework.ide.vscode.boot.index.SpringMetamodelIndex;
import org.springframework.ide.vscode.boot.java.handlers.SymbolAddOnInformation;
import org.springframework.ide.vscode.boot.java.requestmapping.WebfluxHandlerInformation;
import org.springframework.ide.vscode.boot.java.requestmapping.WebfluxHandlerMethodIndexElement;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
import org.springframework.ide.vscode.commons.protocol.spring.SpringIndexElement;
import org.springframework.ide.vscode.project.harness.BootLanguageServerHarness;
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@@ -54,6 +55,7 @@ public class WebFluxMappingSymbolProviderTest {
@Autowired private SpringMetamodelIndex springIndex;
private File directory;
private IJavaProject project;
@BeforeEach
public void setup() throws Exception {
@@ -62,7 +64,7 @@ public class WebFluxMappingSymbolProviderTest {
String projectDir = directory.toURI().toString();
// trigger project creation
projectFinder.find(new TextDocumentIdentifier(projectDir)).get();
project = projectFinder.find(new TextDocumentIdentifier(projectDir)).get();
CompletableFuture<Void> initProject = indexer.waitOperation();
initProject.get(5, TimeUnit.SECONDS);
@@ -91,41 +93,45 @@ public class WebFluxMappingSymbolProviderTest {
assertTrue(containsSymbol(symbols, "@/echo -- POST - Accept: text/plain - Content-Type: text/plain", docUri, 23, 5, 23, 101));
assertTrue(containsSymbol(symbols, "@/quotes -- GET - Accept: application/json", docUri, 24, 5, 24, 86));
assertTrue(containsSymbol(symbols, "@/quotes -- GET - Accept: application/stream+json", docUri, 25, 5, 25, 94));
Bean[] routeBeans = springIndex.getBeansWithName(project.getElementName(), "route");
assertEquals(1, routeBeans.length);
assertEquals("route", routeBeans[0].getName());
List<? extends SymbolAddOnInformation> addons = indexer.getAdditonalInformation(docUri);
assertEquals(8, addons.size());
SpringIndexElement[] children = routeBeans[0].getChildren();
assertEquals(8, children.length);
WebfluxHandlerMethodIndexElement handlerElement1 = getWebfluxIndexElements(children, "/hello", "GET").get(0);
assertEquals("/hello", handlerElement1.getPath());
assertEquals("[GET]", Arrays.toString(handlerElement1.getHttpMethods()));
assertEquals(0, handlerElement1.getContentTypes().length);
assertEquals("[TEXT_PLAIN]", Arrays.toString(handlerElement1.getAcceptTypes()));
assertEquals("org.test.QuoteHandler", handlerElement1.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> hello(org.springframework.web.reactive.function.server.ServerRequest)", handlerElement1.getHandlerMethod());
WebfluxHandlerInformation handlerInfo1 = getWebfluxHandler(addons, "/hello", "GET").get(0);
assertEquals("/hello", handlerInfo1.getPath());
assertEquals("[GET]", Arrays.toString(handlerInfo1.getHttpMethods()));
assertEquals(0, handlerInfo1.getContentTypes().length);
assertEquals("[TEXT_PLAIN]", Arrays.toString(handlerInfo1.getAcceptTypes()));
assertEquals("org.test.QuoteHandler", handlerInfo1.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> hello(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo1.getHandlerMethod());
WebfluxHandlerMethodIndexElement handlerElement2 = getWebfluxIndexElements(children, "/echo", "POST").get(0);
assertEquals("/echo", handlerElement2.getPath());
assertEquals("[POST]", Arrays.toString(handlerElement2.getHttpMethods()));
assertEquals("[TEXT_PLAIN]", Arrays.toString(handlerElement2.getContentTypes()));
assertEquals("[TEXT_PLAIN]", Arrays.toString(handlerElement2.getAcceptTypes()));
assertEquals("org.test.QuoteHandler", handlerElement2.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> echo(org.springframework.web.reactive.function.server.ServerRequest)", handlerElement2.getHandlerMethod());
WebfluxHandlerInformation handlerInfo2 = getWebfluxHandler(addons, "/echo", "POST").get(0);
assertEquals("/echo", handlerInfo2.getPath());
assertEquals("[POST]", Arrays.toString(handlerInfo2.getHttpMethods()));
assertEquals("[TEXT_PLAIN]", Arrays.toString(handlerInfo2.getContentTypes()));
assertEquals("[TEXT_PLAIN]", Arrays.toString(handlerInfo2.getAcceptTypes()));
assertEquals("org.test.QuoteHandler", handlerInfo2.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> echo(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo2.getHandlerMethod());
WebfluxHandlerMethodIndexElement handlerElement3 = getWebfluxIndexElements(children, "/quotes", "GET").get(0);
assertEquals("/quotes", handlerElement3.getPath());
assertEquals("[GET]", Arrays.toString(handlerElement3.getHttpMethods()));
assertEquals(0, handlerElement3.getContentTypes().length);
assertEquals("[APPLICATION_STREAM_JSON]", Arrays.toString(handlerElement3.getAcceptTypes()));
assertEquals("org.test.QuoteHandler", handlerElement3.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> streamQuotes(org.springframework.web.reactive.function.server.ServerRequest)", handlerElement3.getHandlerMethod());
WebfluxHandlerInformation handlerInfo3 = getWebfluxHandler(addons, "/quotes", "GET").get(0);
assertEquals("/quotes", handlerInfo3.getPath());
assertEquals("[GET]", Arrays.toString(handlerInfo3.getHttpMethods()));
assertEquals(0, handlerInfo3.getContentTypes().length);
assertEquals("[APPLICATION_STREAM_JSON]", Arrays.toString(handlerInfo3.getAcceptTypes()));
assertEquals("org.test.QuoteHandler", handlerInfo3.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> streamQuotes(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo3.getHandlerMethod());
WebfluxHandlerInformation handlerInfo4 = getWebfluxHandler(addons, "/quotes", "GET").get(1);
assertEquals("/quotes", handlerInfo4.getPath());
assertEquals("[GET]", Arrays.toString(handlerInfo4.getHttpMethods()));
assertEquals(0, handlerInfo4.getContentTypes().length);
assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerInfo4.getAcceptTypes()));
assertEquals("org.test.QuoteHandler", handlerInfo4.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> fetchQuotes(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo4.getHandlerMethod());
WebfluxHandlerMethodIndexElement handlerElement4 = getWebfluxIndexElements(children, "/quotes", "GET").get(1);
assertEquals("/quotes", handlerElement4.getPath());
assertEquals("[GET]", Arrays.toString(handlerElement4.getHttpMethods()));
assertEquals(0, handlerElement4.getContentTypes().length);
assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerElement4.getAcceptTypes()));
assertEquals("org.test.QuoteHandler", handlerElement4.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> fetchQuotes(org.springframework.web.reactive.function.server.ServerRequest)", handlerElement4.getHandlerMethod());
}
@Test
@@ -136,33 +142,37 @@ public class WebFluxMappingSymbolProviderTest {
assertTrue(containsSymbol(symbols, "@/person/{id} -- GET - Accept: application/json", docUri, 27, 6, 27, 45));
assertTrue(containsSymbol(symbols, "@/person/ -- POST - Content-Type: application/json", docUri, 29, 6, 29, 83));
assertTrue(containsSymbol(symbols, "@/person -- GET - Accept: application/json", docUri, 28, 7, 28, 60));
Bean[] routeBeans = springIndex.getBeansWithName(project.getElementName(), "routingFunction1");
assertEquals(1, routeBeans.length);
assertEquals("routingFunction1", routeBeans[0].getName());
List<? extends SymbolAddOnInformation> addons = indexer.getAdditonalInformation(docUri);
assertEquals(6, addons.size());
SpringIndexElement[] children = routeBeans[0].getChildren();
assertEquals(6, children.length);
WebfluxHandlerMethodIndexElement handlerElement1 = getWebfluxIndexElements(children, "/person/{id}", "GET").get(0);
assertEquals("/person/{id}", handlerElement1.getPath());
assertEquals("[GET]", Arrays.toString(handlerElement1.getHttpMethods()));
assertEquals(0, handlerElement1.getContentTypes().length);
assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerElement1.getAcceptTypes()));
assertEquals("org.test.PersonHandler1", handlerElement1.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> getPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerElement1.getHandlerMethod());
WebfluxHandlerInformation handlerInfo1 = getWebfluxHandler(addons, "/person/{id}", "GET").get(0);
assertEquals("/person/{id}", handlerInfo1.getPath());
assertEquals("[GET]", Arrays.toString(handlerInfo1.getHttpMethods()));
assertEquals(0, handlerInfo1.getContentTypes().length);
assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerInfo1.getAcceptTypes()));
assertEquals("org.test.PersonHandler1", handlerInfo1.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> getPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo1.getHandlerMethod());
WebfluxHandlerMethodIndexElement handlerElement2 = getWebfluxIndexElements(children, "/person/", "POST").get(0);
assertEquals("/person/", handlerElement2.getPath());
assertEquals("[POST]", Arrays.toString(handlerElement2.getHttpMethods()));
assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerElement2.getContentTypes()));
assertEquals(0, handlerElement2.getAcceptTypes().length);
assertEquals("org.test.PersonHandler1", handlerElement2.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> createPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerElement2.getHandlerMethod());
WebfluxHandlerInformation handlerInfo2 = getWebfluxHandler(addons, "/person/", "POST").get(0);
assertEquals("/person/", handlerInfo2.getPath());
assertEquals("[POST]", Arrays.toString(handlerInfo2.getHttpMethods()));
assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerInfo2.getContentTypes()));
assertEquals(0, handlerInfo2.getAcceptTypes().length);
assertEquals("org.test.PersonHandler1", handlerInfo2.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> createPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo2.getHandlerMethod());
WebfluxHandlerInformation handlerInfo3 = getWebfluxHandler(addons, "/person", "GET").get(0);
assertEquals("/person", handlerInfo3.getPath());
assertEquals("[GET]", Arrays.toString(handlerInfo3.getHttpMethods()));
assertEquals(0, handlerInfo3.getContentTypes().length);
assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerInfo3.getAcceptTypes()));
assertEquals("org.test.PersonHandler1", handlerInfo3.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> listPeople(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo3.getHandlerMethod());
WebfluxHandlerMethodIndexElement handlerElement3 = getWebfluxIndexElements(children, "/person", "GET").get(0);
assertEquals("/person", handlerElement3.getPath());
assertEquals("[GET]", Arrays.toString(handlerElement3.getHttpMethods()));
assertEquals(0, handlerElement3.getContentTypes().length);
assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerElement3.getAcceptTypes()));
assertEquals("org.test.PersonHandler1", handlerElement3.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> listPeople(org.springframework.web.reactive.function.server.ServerRequest)", handlerElement3.getHandlerMethod());
}
@Test
@@ -173,33 +183,37 @@ public class WebFluxMappingSymbolProviderTest {
assertTrue(containsSymbol(symbols, "@/person/{id} -- GET - Accept: application/json", docUri, 29, 6, 29, 45));
assertTrue(containsSymbol(symbols, "@/ -- POST - Accept: application/json - Content-Type: application/json,application/pdf", docUri, 31, 6, 31, 117));
assertTrue(containsSymbol(symbols, "@/person -- GET,HEAD - Accept: text/plain,application/json", docUri, 30, 7, 30, 113));
Bean[] routeBeans = springIndex.getBeansWithName(project.getElementName(), "routingFunction2");
assertEquals(1, routeBeans.length);
assertEquals("routingFunction2", routeBeans[0].getName());
List<? extends SymbolAddOnInformation> addons = indexer.getAdditonalInformation(docUri);
assertEquals(6, addons.size());
SpringIndexElement[] children = routeBeans[0].getChildren();
assertEquals(6, children.length);
WebfluxHandlerMethodIndexElement handlerelement1 = getWebfluxIndexElements(children, "/person/{id}", "GET").get(0);
assertEquals("/person/{id}", handlerelement1.getPath());
assertEquals("[GET]", Arrays.toString(handlerelement1.getHttpMethods()));
assertEquals(0, handlerelement1.getContentTypes().length);
assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerelement1.getAcceptTypes()));
assertEquals("org.test.PersonHandler2", handlerelement1.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> getPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerelement1.getHandlerMethod());
WebfluxHandlerInformation handlerInfo1 = getWebfluxHandler(addons, "/person/{id}", "GET").get(0);
assertEquals("/person/{id}", handlerInfo1.getPath());
assertEquals("[GET]", Arrays.toString(handlerInfo1.getHttpMethods()));
assertEquals(0, handlerInfo1.getContentTypes().length);
assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerInfo1.getAcceptTypes()));
assertEquals("org.test.PersonHandler2", handlerInfo1.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> getPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo1.getHandlerMethod());
WebfluxHandlerMethodIndexElement handlerElement2 = getWebfluxIndexElements(children, "/", "POST").get(0);
assertEquals("/", handlerElement2.getPath());
assertEquals("[POST]", Arrays.toString(handlerElement2.getHttpMethods()));
assertEquals("[APPLICATION_JSON, APPLICATION_PDF]", Arrays.toString(handlerElement2.getContentTypes()));
assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerElement2.getAcceptTypes()));
assertEquals("org.test.PersonHandler2", handlerElement2.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> createPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerElement2.getHandlerMethod());
WebfluxHandlerInformation handlerInfo2 = getWebfluxHandler(addons, "/", "POST").get(0);
assertEquals("/", handlerInfo2.getPath());
assertEquals("[POST]", Arrays.toString(handlerInfo2.getHttpMethods()));
assertEquals("[APPLICATION_JSON, APPLICATION_PDF]", Arrays.toString(handlerInfo2.getContentTypes()));
assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerInfo2.getAcceptTypes()));
assertEquals("org.test.PersonHandler2", handlerInfo2.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> createPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo2.getHandlerMethod());
WebfluxHandlerInformation handlerInfo3 = getWebfluxHandler(addons, "/person", "HEAD").get(0);
assertEquals("/person", handlerInfo3.getPath());
assertEquals("[GET, HEAD]", Arrays.toString(handlerInfo3.getHttpMethods()));
assertEquals(0, handlerInfo3.getContentTypes().length);
assertEquals("[TEXT_PLAIN, APPLICATION_JSON]", Arrays.toString(handlerInfo3.getAcceptTypes()));
assertEquals("org.test.PersonHandler2", handlerInfo3.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> listPeople(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo3.getHandlerMethod());
WebfluxHandlerMethodIndexElement handlerElement3 = getWebfluxIndexElements(children, "/person", "HEAD").get(0);
assertEquals("/person", handlerElement3.getPath());
assertEquals("[GET, HEAD]", Arrays.toString(handlerElement3.getHttpMethods()));
assertEquals(0, handlerElement3.getContentTypes().length);
assertEquals("[TEXT_PLAIN, APPLICATION_JSON]", Arrays.toString(handlerElement3.getAcceptTypes()));
assertEquals("org.test.PersonHandler2", handlerElement3.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> listPeople(org.springframework.web.reactive.function.server.ServerRequest)", handlerElement3.getHandlerMethod());
}
@Test
@@ -214,57 +228,61 @@ public class WebFluxMappingSymbolProviderTest {
assertTrue(containsSymbol(symbols, "@/person/sub1/andNestPath/andNestPathGET -- GET", docUri, 33, 5, 33, 54));
assertTrue(containsSymbol(symbols, "@/person/ -- POST - Content-Type: application/json", docUri, 34, 5, 34, 82));
assertTrue(containsSymbol(symbols, "@/nestedDelete -- DELETE", docUri, 35, 42, 35, 93));
Bean[] routeBeans = springIndex.getBeansWithName(project.getElementName(), "routingFunction");
assertEquals(1, routeBeans.length);
assertEquals("routingFunction", routeBeans[0].getName());
List<? extends SymbolAddOnInformation> addons = indexer.getAdditonalInformation(docUri);
assertEquals(12, addons.size());
SpringIndexElement[] children = routeBeans[0].getChildren();
assertEquals(12, children.length);
WebfluxHandlerMethodIndexElement handlerElement1 = getWebfluxIndexElements(children, "/person/sub1/sub2/{id}", "GET").get(0);
assertEquals("/person/sub1/sub2/{id}", handlerElement1.getPath());
assertEquals("[GET]", Arrays.toString(handlerElement1.getHttpMethods()));
assertEquals(0, handlerElement1.getContentTypes().length);
assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerElement1.getAcceptTypes()));
assertEquals("org.test.PersonHandler3", handlerElement1.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> getPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerElement1.getHandlerMethod());
WebfluxHandlerInformation handlerInfo1 = getWebfluxHandler(addons, "/person/sub1/sub2/{id}", "GET").get(0);
assertEquals("/person/sub1/sub2/{id}", handlerInfo1.getPath());
assertEquals("[GET]", Arrays.toString(handlerInfo1.getHttpMethods()));
assertEquals(0, handlerInfo1.getContentTypes().length);
assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerInfo1.getAcceptTypes()));
assertEquals("org.test.PersonHandler3", handlerInfo1.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> getPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo1.getHandlerMethod());
WebfluxHandlerMethodIndexElement handlerElement2 = getWebfluxIndexElements(children, "/person/sub1/sub2", "GET").get(0);
assertEquals("/person/sub1/sub2", handlerElement2.getPath());
assertEquals("[GET]", Arrays.toString(handlerElement2.getHttpMethods()));
assertEquals(0, handlerElement2.getContentTypes().length);
assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerElement2.getAcceptTypes()));
assertEquals("org.test.PersonHandler3", handlerElement1.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> listPeople(org.springframework.web.reactive.function.server.ServerRequest)", handlerElement2.getHandlerMethod());
WebfluxHandlerInformation handlerInfo2 = getWebfluxHandler(addons, "/person/sub1/sub2", "GET").get(0);
assertEquals("/person/sub1/sub2", handlerInfo2.getPath());
assertEquals("[GET]", Arrays.toString(handlerInfo2.getHttpMethods()));
assertEquals(0, handlerInfo2.getContentTypes().length);
assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerInfo2.getAcceptTypes()));
assertEquals("org.test.PersonHandler3", handlerInfo1.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> listPeople(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo2.getHandlerMethod());
WebfluxHandlerMethodIndexElement handlerElement3 = getWebfluxIndexElements(children, "/person/sub1/sub2/nestedGet", "GET").get(0);
assertEquals("/person/sub1/sub2/nestedGet", handlerElement3.getPath());
assertEquals("[GET]", Arrays.toString(handlerElement3.getHttpMethods()));
assertEquals(0, handlerElement3.getContentTypes().length);
assertEquals(0, handlerElement3.getAcceptTypes().length);
assertEquals("org.test.PersonHandler3", handlerElement1.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> getPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerElement3.getHandlerMethod());
WebfluxHandlerInformation handlerInfo3 = getWebfluxHandler(addons, "/person/sub1/sub2/nestedGet", "GET").get(0);
assertEquals("/person/sub1/sub2/nestedGet", handlerInfo3.getPath());
assertEquals("[GET]", Arrays.toString(handlerInfo3.getHttpMethods()));
assertEquals(0, handlerInfo3.getContentTypes().length);
assertEquals(0, handlerInfo3.getAcceptTypes().length);
assertEquals("org.test.PersonHandler3", handlerInfo1.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> getPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo3.getHandlerMethod());
WebfluxHandlerMethodIndexElement handlerElement4 = getWebfluxIndexElements(children, "/person/sub1/andNestPath/andNestPathGET", "GET").get(0);
assertEquals("/person/sub1/andNestPath/andNestPathGET", handlerElement4.getPath());
assertEquals("[GET]", Arrays.toString(handlerElement4.getHttpMethods()));
assertEquals(0, handlerElement4.getContentTypes().length);
assertEquals(0, handlerElement4.getAcceptTypes().length);
assertEquals("org.test.PersonHandler3", handlerElement4.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> getPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerElement4.getHandlerMethod());
WebfluxHandlerInformation handlerInfo4 = getWebfluxHandler(addons, "/person/sub1/andNestPath/andNestPathGET", "GET").get(0);
assertEquals("/person/sub1/andNestPath/andNestPathGET", handlerInfo4.getPath());
assertEquals("[GET]", Arrays.toString(handlerInfo4.getHttpMethods()));
assertEquals(0, handlerInfo4.getContentTypes().length);
assertEquals(0, handlerInfo4.getAcceptTypes().length);
assertEquals("org.test.PersonHandler3", handlerInfo4.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> getPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo4.getHandlerMethod());
WebfluxHandlerMethodIndexElement handlerElement5 = getWebfluxIndexElements(children, "/person/", "POST").get(0);
assertEquals("/person/", handlerElement5.getPath());
assertEquals("[POST]", Arrays.toString(handlerElement5.getHttpMethods()));
assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerElement5.getContentTypes()));
assertEquals(0, handlerElement5.getAcceptTypes().length);
assertEquals("org.test.PersonHandler3", handlerElement5.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> createPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerElement5.getHandlerMethod());
WebfluxHandlerInformation handlerInfo5 = getWebfluxHandler(addons, "/person/", "POST").get(0);
assertEquals("/person/", handlerInfo5.getPath());
assertEquals("[POST]", Arrays.toString(handlerInfo5.getHttpMethods()));
assertEquals("[APPLICATION_JSON]", Arrays.toString(handlerInfo5.getContentTypes()));
assertEquals(0, handlerInfo5.getAcceptTypes().length);
assertEquals("org.test.PersonHandler3", handlerInfo5.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> createPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo5.getHandlerMethod());
WebfluxHandlerInformation handlerInfo6 = getWebfluxHandler(addons, "/nestedDelete", "DELETE").get(0);
assertEquals("/nestedDelete", handlerInfo6.getPath());
assertEquals("[DELETE]", Arrays.toString(handlerInfo6.getHttpMethods()));
assertEquals(0, handlerInfo6.getContentTypes().length);
assertEquals(0, handlerInfo6.getAcceptTypes().length);
assertEquals("org.test.PersonHandler3", handlerInfo6.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> deletePerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo6.getHandlerMethod());
WebfluxHandlerMethodIndexElement handlerElement6 = getWebfluxIndexElements(children, "/nestedDelete", "DELETE").get(0);
assertEquals("/nestedDelete", handlerElement6.getPath());
assertEquals("[DELETE]", Arrays.toString(handlerElement6.getHttpMethods()));
assertEquals(0, handlerElement6.getContentTypes().length);
assertEquals(0, handlerElement6.getAcceptTypes().length);
assertEquals("org.test.PersonHandler3", handlerElement6.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> deletePerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerElement6.getHandlerMethod());
}
private boolean containsSymbol(List<? extends WorkspaceSymbol> symbols, String name, String uri, int startLine, int startCHaracter, int endLine, int endCharacter) {
@@ -284,10 +302,10 @@ public class WebFluxMappingSymbolProviderTest {
return false;
}
private List<WebfluxHandlerInformation> getWebfluxHandler(List<? extends SymbolAddOnInformation> addons, String path, String httpMethod) {
return addons.stream()
.filter((obj) -> obj instanceof WebfluxHandlerInformation)
.map((obj -> (WebfluxHandlerInformation) obj))
private List<WebfluxHandlerMethodIndexElement> getWebfluxIndexElements(SpringIndexElement[] indexElements, String path, String httpMethod) {
return Arrays.stream(indexElements)
.filter((obj) -> obj instanceof WebfluxHandlerMethodIndexElement)
.map((obj -> (WebfluxHandlerMethodIndexElement) obj))
.filter((addon) -> addon.getPath().equals(path) && Arrays.asList(addon.getHttpMethods()).contains(httpMethod))
.collect(Collectors.toList());
}

View File

@@ -1,12 +1,12 @@
/*******************************************************************************
* Copyright (c) 2018 Pivotal, Inc.
* Copyright (c) 2024 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:
* Pivotal, Inc. - initial API and implementation
* Broadcom - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.requestmapping.test;
@@ -16,20 +16,17 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.junit.jupiter.api.Test;
import org.springframework.ide.vscode.boot.java.requestmapping.WebfluxElementsInformation;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.assertFalse;
import org.springframework.ide.vscode.boot.java.requestmapping.WebfluxRouteElementRangesIndexElement;
/**
* @author Martin Lippert
*/
public class WebfluxElementsInformationTest {
public class WebfluxRouteElementRangesIndexElementTest {
@Test
void testContainsSingleCharacterRange() {
Range range = new Range(new Position(3, 10), new Position(3, 10));
WebfluxElementsInformation information = new WebfluxElementsInformation(new Range[]{range});
WebfluxRouteElementRangesIndexElement information = new WebfluxRouteElementRangesIndexElement(new Range[]{range});
assertFalse(information.contains(new Position(3, 9)));
assertTrue(information.contains(new Position(3, 10)));
@@ -39,7 +36,7 @@ public class WebfluxElementsInformationTest {
@Test
void testContainsSingleLineRange() {
Range range = new Range(new Position(3, 10), new Position(3, 20));
WebfluxElementsInformation information = new WebfluxElementsInformation(new Range[]{range});
WebfluxRouteElementRangesIndexElement information = new WebfluxRouteElementRangesIndexElement(new Range[]{range});
assertFalse(information.contains(new Position(3, 5)));
assertTrue(information.contains(new Position(3, 11)));
@@ -53,7 +50,7 @@ public class WebfluxElementsInformationTest {
@Test
void testContainsMultipleLineRange() {
Range range = new Range(new Position(2, 10), new Position(4, 5));
WebfluxElementsInformation information = new WebfluxElementsInformation(new Range[]{range});
WebfluxRouteElementRangesIndexElement information = new WebfluxRouteElementRangesIndexElement(new Range[]{range});
assertFalse(information.contains(new Position(1, 1)));
assertFalse(information.contains(new Position(1, 11)));
@@ -82,7 +79,7 @@ public class WebfluxElementsInformationTest {
Range range3 = new Range(new Position(10, 10), new Position(20, 20));
Range range4 = new Range(new Position(4, 40), new Position(6, 3));
WebfluxElementsInformation information = new WebfluxElementsInformation(new Range[]{range1, range2, range3, range4});
WebfluxRouteElementRangesIndexElement information = new WebfluxRouteElementRangesIndexElement(new Range[]{range1, range2, range3, range4});
assertFalse(information.contains(new Position(2, 9)));
assertTrue(information.contains(new Position(2, 10)));