Skip to content

Commit

Permalink
add request mapping details as index child elements to controller bean
Browse files Browse the repository at this point in the history
  • Loading branch information
martinlippert committed Jan 27, 2025
1 parent 85afe5c commit 1863a16
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 36 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*******************************************************************************
* Copyright (c) 2025 Broadcom
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.requestmapping;

import org.springframework.ide.vscode.commons.protocol.spring.AbstractSpringIndexElement;

public class RequestMappingIndexElement extends AbstractSpringIndexElement {

private final String path;
private final String[] httpMethods;
private final String[] contentTypes;
private final String[] acceptTypes;

public RequestMappingIndexElement(String path, String[] httpMethods, String[] contentTypes, String[] acceptTypes) {
this.path = path;
this.httpMethods = httpMethods;
this.contentTypes = contentTypes;
this.acceptTypes = acceptTypes;
}

public String getPath() {
return path;
}

public String[] getHttpMethods() {
return httpMethods;
}

public String[] getContentTypes() {
return contentTypes;
}

public String[] getAcceptTypes() {
return acceptTypes;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.java.Annotations;
import org.springframework.ide.vscode.boot.java.beans.CachedBean;
import org.springframework.ide.vscode.boot.java.handlers.AbstractSymbolProvider;
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
import org.springframework.ide.vscode.boot.java.utils.ASTUtils;
import org.springframework.ide.vscode.boot.java.utils.CachedSymbol;
import org.springframework.ide.vscode.boot.java.utils.SpringIndexerJavaContext;
Expand Down Expand Up @@ -69,8 +71,20 @@ protected void addSymbolsPass1(Annotation node, ITypeBinding annotationType, Col
.filter(Objects::nonNull).map(p -> {
return combinePath(parent, p);
}))
.map(p -> RouteUtils.createRouteSymbol(location, p, methods, contentTypes, acceptTypes))
.forEach((enhancedSymbol) -> context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), enhancedSymbol)));
.forEach(p -> {
// symbol
EnhancedSymbolInformation symbol = RouteUtils.createRouteSymbol(location, p, methods, contentTypes, acceptTypes);
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), symbol));

// index element for request mapping
List<CachedBean> beans = context.getBeans();
if (beans.size() > 0 ) {
CachedBean cachedBean = beans.get(beans.size() - 1);
if (cachedBean.getDocURI().equals(doc.getUri())) {
cachedBean.getBean().addChild(new RequestMappingIndexElement(p, methods, contentTypes, acceptTypes));
}
}
});
} catch (Exception e) {
log.error("problem occured while scanning for request mapping symbols from " + doc.getUri(), e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,16 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.requestmapping;

import org.springframework.ide.vscode.commons.protocol.spring.AbstractSpringIndexElement;

public class WebfluxHandlerMethodIndexElement extends AbstractSpringIndexElement {
public class WebfluxHandlerMethodIndexElement extends RequestMappingIndexElement {

private final String handlerClass;
private final String handlerMethod;

private final String path;
private final String[] httpMethods;
private final String[] contentTypes;
private final String[] acceptTypes;

public WebfluxHandlerMethodIndexElement(String handlerClass, String handlerMethod, String path, String[] httpMethods, String[] contentTypes, String[] acceptTypes) {
super(path, httpMethods, contentTypes, acceptTypes);

this.handlerClass = handlerClass;
this.handlerMethod = handlerMethod;

this.path = path;
this.httpMethods = httpMethods;
this.contentTypes = contentTypes;
this.acceptTypes = acceptTypes;
}

public String getHandlerClass() {
Expand All @@ -40,20 +30,4 @@ public String getHandlerMethod() {
return handlerMethod;
}

public String getPath() {
return path;
}

public String[] getHttpMethods() {
return httpMethods;
}

public String[] getContentTypes() {
return contentTypes;
}

public String[] getAcceptTypes() {
return acceptTypes;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017, 2024 Pivotal, Inc.
* Copyright (c) 2017, 2025 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
Expand Down Expand Up @@ -35,9 +35,13 @@
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.requestmapping.RequestMappingIndexElement;
import org.springframework.ide.vscode.boot.java.utils.SpringIndexerJavaDependencyTracker;
import org.springframework.ide.vscode.boot.java.utils.test.TestFileScanListener;
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.commons.util.UriUtil;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
Expand All @@ -58,6 +62,7 @@ public class RequestMappingSymbolProviderTest {
@Autowired private BootLanguageServerHarness harness;
@Autowired private JavaProjectFinder projectFinder;
@Autowired private SpringSymbolIndex indexer;
@Autowired private SpringMetamodelIndex springIndex;

private File directory;

Expand All @@ -79,8 +84,24 @@ public void setup() throws Exception {
void testSimpleRequestMappingSymbol() throws Exception {
String docUri = directory.toPath().resolve("src/main/java/org/test/SimpleMappingClass.java").toUri().toString();
List<? extends WorkspaceSymbol> symbols = indexer.getSymbols(docUri);
assertEquals(1, symbols.size());
assertTrue(containsSymbol(symbols, "@/greeting", docUri, 6, 1, 6, 29));
assertEquals(2, symbols.size());
assertTrue(containsSymbol(symbols, "@/greeting", docUri, 8, 1, 8, 29));
}

@Test
void testRequestMappingIndexElements() throws Exception {
Bean[] beans = springIndex.getBeansWithName("test-request-mapping-symbols", "simpleMappingClass");
assertEquals(1, beans.length);

List<SpringIndexElement> children = beans[0].getChildren();
List<SpringIndexElement> mappingChildren = children.stream()
.filter(child -> child instanceof RequestMappingIndexElement)
.toList();

assertEquals(1, mappingChildren.size());

RequestMappingIndexElement mappingElement = (RequestMappingIndexElement) mappingChildren.get(0);
assertEquals("/greeting", mappingElement.getPath());
}

@Test
Expand Down Expand Up @@ -248,8 +269,33 @@ void testMappingPathFromMultiLevelClassHierarchy() throws Exception {
void testMappingPathFromSuperInterfaceEvenIfSuperclassContainsMappingPath() throws Exception {
String docUri = directory.toPath().resolve("src/main/java/org/test/inheritance/ControllerAsSubclassAndInterfaceHierarchy.java").toUri().toString();
List<? extends WorkspaceSymbol> symbols = indexer.getSymbols(docUri);
assertEquals(1, symbols.size());
assertTrue(containsSymbol(symbols, "@/superinterface-path/last-path-segment -- GET - Accept: testconsume - Content-Type: text/plain", docUri, 6, 1, 6, 33));
assertEquals(2, symbols.size());
assertTrue(containsSymbol(symbols, "@/superinterface-path/last-path-segment -- GET - Accept: testconsume - Content-Type: text/plain", docUri, 8, 1, 8, 33));
}

@Test
void testMapoingIndexElementsWithDetails() throws Exception {
Bean[] beans = springIndex.getBeansWithName("test-request-mapping-symbols", "controllerAsSubclassAndInterfaceHierarchy");
assertEquals(1, beans.length);

List<SpringIndexElement> children = beans[0].getChildren();
List<SpringIndexElement> mappingChildren = children.stream()
.filter(child -> child instanceof RequestMappingIndexElement)
.toList();

assertEquals(1, mappingChildren.size());

RequestMappingIndexElement mappingElement = (RequestMappingIndexElement) mappingChildren.get(0);
assertEquals("/superinterface-path/last-path-segment", mappingElement.getPath());

assertEquals(1, mappingElement.getHttpMethods().length);
assertEquals("GET", mappingElement.getHttpMethods()[0]);

assertEquals(1, mappingElement.getAcceptTypes().length);
assertEquals("testconsume", mappingElement.getAcceptTypes()[0]);

assertEquals(1, mappingElement.getContentTypes().length);
assertEquals("text/plain", mappingElement.getContentTypes()[0]);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.test;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class SimpleMappingClass {

@RequestMapping("/greeting")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.test.inheritance;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ControllerAsSubclassAndInterfaceHierarchy extends SuperclassWithMappingPath implements EmptyInterfaceWithinHierarchy {

@GetMapping("last-path-segment")
Expand Down

0 comments on commit 1863a16

Please sign in to comment.