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:
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -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)));
|
||||
}
|
||||
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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)));
|
||||
Reference in New Issue
Block a user