Skip to content

Commit 1863a16

Browse files
committed
add request mapping details as index child elements to controller bean
1 parent 85afe5c commit 1863a16

File tree

6 files changed

+119
-36
lines changed

6 files changed

+119
-36
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Broadcom
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v1.0
5+
* which accompanies this distribution, and is available at
6+
* https://www.eclipse.org/legal/epl-v10.html
7+
*
8+
* Contributors:
9+
* Broadcom - initial API and implementation
10+
*******************************************************************************/
11+
package org.springframework.ide.vscode.boot.java.requestmapping;
12+
13+
import org.springframework.ide.vscode.commons.protocol.spring.AbstractSpringIndexElement;
14+
15+
public class RequestMappingIndexElement extends AbstractSpringIndexElement {
16+
17+
private final String path;
18+
private final String[] httpMethods;
19+
private final String[] contentTypes;
20+
private final String[] acceptTypes;
21+
22+
public RequestMappingIndexElement(String path, String[] httpMethods, String[] contentTypes, String[] acceptTypes) {
23+
this.path = path;
24+
this.httpMethods = httpMethods;
25+
this.contentTypes = contentTypes;
26+
this.acceptTypes = acceptTypes;
27+
}
28+
29+
public String getPath() {
30+
return path;
31+
}
32+
33+
public String[] getHttpMethods() {
34+
return httpMethods;
35+
}
36+
37+
public String[] getContentTypes() {
38+
return contentTypes;
39+
}
40+
41+
public String[] getAcceptTypes() {
42+
return acceptTypes;
43+
}
44+
45+
}

headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingSymbolProvider.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@
3333
import org.slf4j.Logger;
3434
import org.slf4j.LoggerFactory;
3535
import org.springframework.ide.vscode.boot.java.Annotations;
36+
import org.springframework.ide.vscode.boot.java.beans.CachedBean;
3637
import org.springframework.ide.vscode.boot.java.handlers.AbstractSymbolProvider;
38+
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
3739
import org.springframework.ide.vscode.boot.java.utils.ASTUtils;
3840
import org.springframework.ide.vscode.boot.java.utils.CachedSymbol;
3941
import org.springframework.ide.vscode.boot.java.utils.SpringIndexerJavaContext;
@@ -69,8 +71,20 @@ protected void addSymbolsPass1(Annotation node, ITypeBinding annotationType, Col
6971
.filter(Objects::nonNull).map(p -> {
7072
return combinePath(parent, p);
7173
}))
72-
.map(p -> RouteUtils.createRouteSymbol(location, p, methods, contentTypes, acceptTypes))
73-
.forEach((enhancedSymbol) -> context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), enhancedSymbol)));
74+
.forEach(p -> {
75+
// symbol
76+
EnhancedSymbolInformation symbol = RouteUtils.createRouteSymbol(location, p, methods, contentTypes, acceptTypes);
77+
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), symbol));
78+
79+
// index element for request mapping
80+
List<CachedBean> beans = context.getBeans();
81+
if (beans.size() > 0 ) {
82+
CachedBean cachedBean = beans.get(beans.size() - 1);
83+
if (cachedBean.getDocURI().equals(doc.getUri())) {
84+
cachedBean.getBean().addChild(new RequestMappingIndexElement(p, methods, contentTypes, acceptTypes));
85+
}
86+
}
87+
});
7488
} catch (Exception e) {
7589
log.error("problem occured while scanning for request mapping symbols from " + doc.getUri(), e);
7690
}

headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxHandlerMethodIndexElement.java

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,16 @@
1010
*******************************************************************************/
1111
package org.springframework.ide.vscode.boot.java.requestmapping;
1212

13-
import org.springframework.ide.vscode.commons.protocol.spring.AbstractSpringIndexElement;
14-
15-
public class WebfluxHandlerMethodIndexElement extends AbstractSpringIndexElement {
13+
public class WebfluxHandlerMethodIndexElement extends RequestMappingIndexElement {
1614

1715
private final String handlerClass;
1816
private final String handlerMethod;
1917

20-
private final String path;
21-
private final String[] httpMethods;
22-
private final String[] contentTypes;
23-
private final String[] acceptTypes;
24-
2518
public WebfluxHandlerMethodIndexElement(String handlerClass, String handlerMethod, String path, String[] httpMethods, String[] contentTypes, String[] acceptTypes) {
19+
super(path, httpMethods, contentTypes, acceptTypes);
20+
2621
this.handlerClass = handlerClass;
2722
this.handlerMethod = handlerMethod;
28-
29-
this.path = path;
30-
this.httpMethods = httpMethods;
31-
this.contentTypes = contentTypes;
32-
this.acceptTypes = acceptTypes;
3323
}
3424

3525
public String getHandlerClass() {
@@ -40,20 +30,4 @@ public String getHandlerMethod() {
4030
return handlerMethod;
4131
}
4232

43-
public String getPath() {
44-
return path;
45-
}
46-
47-
public String[] getHttpMethods() {
48-
return httpMethods;
49-
}
50-
51-
public String[] getContentTypes() {
52-
return contentTypes;
53-
}
54-
55-
public String[] getAcceptTypes() {
56-
return acceptTypes;
57-
}
58-
5933
}

headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/RequestMappingSymbolProviderTest.java

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2017, 2024 Pivotal, Inc.
2+
* Copyright (c) 2017, 2025 Pivotal, Inc.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v1.0
55
* which accompanies this distribution, and is available at
@@ -35,9 +35,13 @@
3535
import org.springframework.ide.vscode.boot.app.SpringSymbolIndex;
3636
import org.springframework.ide.vscode.boot.bootiful.BootLanguageServerTest;
3737
import org.springframework.ide.vscode.boot.bootiful.SymbolProviderTestConf;
38+
import org.springframework.ide.vscode.boot.index.SpringMetamodelIndex;
39+
import org.springframework.ide.vscode.boot.java.requestmapping.RequestMappingIndexElement;
3840
import org.springframework.ide.vscode.boot.java.utils.SpringIndexerJavaDependencyTracker;
3941
import org.springframework.ide.vscode.boot.java.utils.test.TestFileScanListener;
4042
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
43+
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
44+
import org.springframework.ide.vscode.commons.protocol.spring.SpringIndexElement;
4145
import org.springframework.ide.vscode.commons.util.UriUtil;
4246
import org.springframework.ide.vscode.commons.util.text.LanguageId;
4347
import org.springframework.ide.vscode.commons.util.text.TextDocument;
@@ -58,6 +62,7 @@ public class RequestMappingSymbolProviderTest {
5862
@Autowired private BootLanguageServerHarness harness;
5963
@Autowired private JavaProjectFinder projectFinder;
6064
@Autowired private SpringSymbolIndex indexer;
65+
@Autowired private SpringMetamodelIndex springIndex;
6166

6267
private File directory;
6368

@@ -79,8 +84,24 @@ public void setup() throws Exception {
7984
void testSimpleRequestMappingSymbol() throws Exception {
8085
String docUri = directory.toPath().resolve("src/main/java/org/test/SimpleMappingClass.java").toUri().toString();
8186
List<? extends WorkspaceSymbol> symbols = indexer.getSymbols(docUri);
82-
assertEquals(1, symbols.size());
83-
assertTrue(containsSymbol(symbols, "@/greeting", docUri, 6, 1, 6, 29));
87+
assertEquals(2, symbols.size());
88+
assertTrue(containsSymbol(symbols, "@/greeting", docUri, 8, 1, 8, 29));
89+
}
90+
91+
@Test
92+
void testRequestMappingIndexElements() throws Exception {
93+
Bean[] beans = springIndex.getBeansWithName("test-request-mapping-symbols", "simpleMappingClass");
94+
assertEquals(1, beans.length);
95+
96+
List<SpringIndexElement> children = beans[0].getChildren();
97+
List<SpringIndexElement> mappingChildren = children.stream()
98+
.filter(child -> child instanceof RequestMappingIndexElement)
99+
.toList();
100+
101+
assertEquals(1, mappingChildren.size());
102+
103+
RequestMappingIndexElement mappingElement = (RequestMappingIndexElement) mappingChildren.get(0);
104+
assertEquals("/greeting", mappingElement.getPath());
84105
}
85106

86107
@Test
@@ -248,8 +269,33 @@ void testMappingPathFromMultiLevelClassHierarchy() throws Exception {
248269
void testMappingPathFromSuperInterfaceEvenIfSuperclassContainsMappingPath() throws Exception {
249270
String docUri = directory.toPath().resolve("src/main/java/org/test/inheritance/ControllerAsSubclassAndInterfaceHierarchy.java").toUri().toString();
250271
List<? extends WorkspaceSymbol> symbols = indexer.getSymbols(docUri);
251-
assertEquals(1, symbols.size());
252-
assertTrue(containsSymbol(symbols, "@/superinterface-path/last-path-segment -- GET - Accept: testconsume - Content-Type: text/plain", docUri, 6, 1, 6, 33));
272+
assertEquals(2, symbols.size());
273+
assertTrue(containsSymbol(symbols, "@/superinterface-path/last-path-segment -- GET - Accept: testconsume - Content-Type: text/plain", docUri, 8, 1, 8, 33));
274+
}
275+
276+
@Test
277+
void testMapoingIndexElementsWithDetails() throws Exception {
278+
Bean[] beans = springIndex.getBeansWithName("test-request-mapping-symbols", "controllerAsSubclassAndInterfaceHierarchy");
279+
assertEquals(1, beans.length);
280+
281+
List<SpringIndexElement> children = beans[0].getChildren();
282+
List<SpringIndexElement> mappingChildren = children.stream()
283+
.filter(child -> child instanceof RequestMappingIndexElement)
284+
.toList();
285+
286+
assertEquals(1, mappingChildren.size());
287+
288+
RequestMappingIndexElement mappingElement = (RequestMappingIndexElement) mappingChildren.get(0);
289+
assertEquals("/superinterface-path/last-path-segment", mappingElement.getPath());
290+
291+
assertEquals(1, mappingElement.getHttpMethods().length);
292+
assertEquals("GET", mappingElement.getHttpMethods()[0]);
293+
294+
assertEquals(1, mappingElement.getAcceptTypes().length);
295+
assertEquals("testconsume", mappingElement.getAcceptTypes()[0]);
296+
297+
assertEquals(1, mappingElement.getContentTypes().length);
298+
assertEquals("text/plain", mappingElement.getContentTypes()[0]);
253299
}
254300

255301
@Test

headless-services/spring-boot-language-server/src/test/resources/test-projects/test-request-mapping-symbols/src/main/java/org/test/SimpleMappingClass.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package org.test;
22

3+
import org.springframework.stereotype.Controller;
34
import org.springframework.web.bind.annotation.RequestMapping;
45

6+
@Controller
57
public class SimpleMappingClass {
68

79
@RequestMapping("/greeting")

headless-services/spring-boot-language-server/src/test/resources/test-projects/test-request-mapping-symbols/src/main/java/org/test/inheritance/ControllerAsSubclassAndInterfaceHierarchy.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package org.test.inheritance;
22

33
import org.springframework.web.bind.annotation.GetMapping;
4+
import org.springframework.web.bind.annotation.RestController;
45

6+
@RestController
57
public class ControllerAsSubclassAndInterfaceHierarchy extends SuperclassWithMappingPath implements EmptyInterfaceWithinHierarchy {
68

79
@GetMapping("last-path-segment")

0 commit comments

Comments
 (0)