Skip to content

Commit 1dabd89

Browse files
committed
GH-1599: basic indexing of http exchange methods added
1 parent 88cda2a commit 1dabd89

File tree

23 files changed

+1194
-269
lines changed

23 files changed

+1194
-269
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.springframework.ide.vscode.boot.java.data.DataRepositorySymbolProvider;
2424
import org.springframework.ide.vscode.boot.java.events.EventListenerSymbolProvider;
2525
import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider;
26+
import org.springframework.ide.vscode.boot.java.requestmapping.HttpExchangeSymbolProvider;
2627
import org.springframework.ide.vscode.boot.java.requestmapping.RequestMappingSymbolProvider;
2728
import org.springframework.ide.vscode.boot.java.utils.RestrictedDefaultSymbolProvider;
2829

@@ -80,6 +81,7 @@ AnnotationHierarchyAwareLookup<SymbolProvider> symbolProviders(IndexCache cache,
8081
providers.put(Annotations.EVENT_LISTENER, eventListenerSymbolProvider);
8182

8283
providers.put(Annotations.FEIGN_CLIENT, new FeignClientSymbolProvider());
84+
providers.put(Annotations.HTTP_EXCHANGE, new HttpExchangeSymbolProvider());
8385

8486
return providers;
8587
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ public class Annotations {
6161
public static final String SPRING_PUT_MAPPING = "org.springframework.web.bind.annotation.PutMapping";
6262
public static final String SPRING_DELETE_MAPPING = "org.springframework.web.bind.annotation.DeleteMapping";
6363
public static final String SPRING_PATCH_MAPPING = "org.springframework.web.bind.annotation.PatchMapping";
64+
65+
public static final String HTTP_EXCHANGE = "org.springframework.web.service.annotation.HttpExchange";
66+
public static final String GET_EXCHANGE = "org.springframework.web.service.annotation.GetExchange";
67+
public static final String POST_EXCHANGE = "org.springframework.web.service.annotation.PostExchange";
68+
public static final String PUT_EXCHANGE = "org.springframework.web.service.annotation.PutExchange";
69+
public static final String DELETE_EXCHANGE = "org.springframework.web.service.annotation.DeleteExchange";
70+
public static final String PATCH_EXCHANGE = "org.springframework.web.service.annotation.PatchExchange";
71+
6472
public static final String SPRING_BOOT_TEST = "org.springframework.boot.test.context.SpringBootTest";
6573

6674
public static final String CONDITIONAL_ON_BEAN = "org.springframework.boot.autoconfigure.condition.ConditionalOnBean";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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.eclipse.lsp4j.Range;
14+
15+
public class HttpExchangeIndexElement extends WebEndpointIndexElement {
16+
17+
public HttpExchangeIndexElement(String path, String[] httpMethods, String[] contentTypes, String[] acceptTypes, Range range, String symbolLabel) {
18+
super(path, httpMethods, contentTypes, acceptTypes, range, symbolLabel);
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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 java.util.Map;
14+
import java.util.Set;
15+
16+
import org.eclipse.jdt.core.dom.Annotation;
17+
import org.springframework.ide.vscode.boot.java.Annotations;
18+
import org.springframework.ide.vscode.boot.java.utils.SpringIndexerJavaContext;
19+
20+
/**
21+
* @author Martin Lippert
22+
*/
23+
public class HttpExchangeIndexer {
24+
25+
private static final Set<String> ATTRIBUTE_NAME_VALUE_PATH = Set.of("value", "url");
26+
27+
private static final Set<String> ATTRIBUTE_NAME_METHOD = Set.of("method");
28+
private static final Set<String> ATTRIBUTE_NAME_ACCEPT = Set.of("accept");
29+
private static final Set<String> ATTRIBUTE_NAME_CONTENT_TYPE = Set.of("contentType");
30+
31+
private static final Map<String, String[]> METHOD_MAPPING = Map.of(
32+
Annotations.GET_EXCHANGE, new String[] { "GET" },
33+
Annotations.POST_EXCHANGE, new String[] { "POST" },
34+
Annotations.DELETE_EXCHANGE, new String[] { "DELETE" },
35+
Annotations.PUT_EXCHANGE, new String[] { "PUT" },
36+
Annotations.PATCH_EXCHANGE, new String[] { "PATCH" }
37+
);
38+
39+
40+
public static String[] getPath(Annotation node, SpringIndexerJavaContext context) {
41+
return WebEndpointIndexer.getPath(node, context, ATTRIBUTE_NAME_VALUE_PATH);
42+
}
43+
44+
public static String[] getParentPath(Annotation node, SpringIndexerJavaContext context) {
45+
return WebEndpointIndexer.getParentPath(node, context, ATTRIBUTE_NAME_VALUE_PATH, Annotations.HTTP_EXCHANGE);
46+
}
47+
48+
public static String[] getAcceptTypes(Annotation node, SpringIndexerJavaContext context) {
49+
return WebEndpointIndexer.getAttributeValues(node, context, ATTRIBUTE_NAME_ACCEPT, Annotations.HTTP_EXCHANGE);
50+
}
51+
52+
public static String[] getContentTypes(Annotation node, SpringIndexerJavaContext context) {
53+
return WebEndpointIndexer.getAttributeValues(node, context, ATTRIBUTE_NAME_CONTENT_TYPE, Annotations.HTTP_EXCHANGE);
54+
}
55+
56+
public static String[] getMethod(Annotation node, SpringIndexerJavaContext context) {
57+
return WebEndpointIndexer.getMethod(node, context, ATTRIBUTE_NAME_METHOD, METHOD_MAPPING, Annotations.HTTP_EXCHANGE);
58+
}
59+
60+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
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 java.util.Arrays;
14+
import java.util.Collection;
15+
import java.util.Objects;
16+
import java.util.stream.Stream;
17+
18+
import org.eclipse.jdt.core.dom.Annotation;
19+
import org.eclipse.jdt.core.dom.ITypeBinding;
20+
import org.eclipse.jdt.core.dom.MethodDeclaration;
21+
import org.eclipse.lsp4j.Location;
22+
import org.eclipse.lsp4j.WorkspaceSymbol;
23+
import org.slf4j.Logger;
24+
import org.slf4j.LoggerFactory;
25+
import org.springframework.ide.vscode.boot.java.beans.CachedBean;
26+
import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider;
27+
import org.springframework.ide.vscode.boot.java.utils.CachedSymbol;
28+
import org.springframework.ide.vscode.boot.java.utils.SpringIndexerJavaContext;
29+
import org.springframework.ide.vscode.commons.util.BadLocationException;
30+
import org.springframework.ide.vscode.commons.util.text.TextDocument;
31+
32+
public class HttpExchangeSymbolProvider implements SymbolProvider {
33+
34+
private static final Logger log = LoggerFactory.getLogger(HttpExchangeSymbolProvider.class);
35+
36+
@Override
37+
public void addSymbols(Annotation node, ITypeBinding typeBinding, Collection<ITypeBinding> metaAnnotations, SpringIndexerJavaContext context, TextDocument doc) {
38+
if (node.getParent() instanceof MethodDeclaration) {
39+
try {
40+
Location location = new Location(doc.getUri(), doc.toRange(node.getStartPosition(), node.getLength()));
41+
42+
String[] path = HttpExchangeIndexer.getPath(node, context);
43+
String[] parentPath = HttpExchangeIndexer.getParentPath(node, context);
44+
String[] methods = HttpExchangeIndexer.getMethod(node, context);
45+
String[] contentTypes = HttpExchangeIndexer.getContentTypes(node, context);
46+
String[] acceptTypes = HttpExchangeIndexer.getAcceptTypes(node, context);
47+
48+
Stream<String> stream = parentPath == null ? Stream.of("") : Arrays.stream(parentPath);
49+
stream.filter(Objects::nonNull)
50+
.flatMap(parent -> (path == null ? Stream.<String>empty() : Arrays.stream(path))
51+
.filter(Objects::nonNull).map(p -> {
52+
return WebEndpointIndexer.combinePath(parent, p);
53+
}))
54+
.forEach(p -> {
55+
// symbol
56+
WorkspaceSymbol symbol = RouteUtils.createRouteSymbol(location, p, methods, contentTypes, acceptTypes);
57+
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), symbol));
58+
59+
// index element
60+
HttpExchangeIndexElement requestMappingIndexElement = new HttpExchangeIndexElement(p, methods, contentTypes, acceptTypes, location.getRange(), symbol.getName());
61+
context.getBeans().add(new CachedBean(doc.getUri(), requestMappingIndexElement));
62+
});
63+
64+
} catch (BadLocationException e) {
65+
log.error("problem occured while scanning for request mapping symbols from " + doc.getUri(), e);
66+
}
67+
}
68+
}
69+
70+
71+
}

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

Lines changed: 2 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -10,56 +10,11 @@
1010
*******************************************************************************/
1111
package org.springframework.ide.vscode.boot.java.requestmapping;
1212

13-
import org.eclipse.lsp4j.DocumentSymbol;
1413
import org.eclipse.lsp4j.Range;
15-
import org.eclipse.lsp4j.SymbolKind;
16-
import org.springframework.ide.vscode.commons.protocol.spring.AbstractSpringIndexElement;
17-
import org.springframework.ide.vscode.commons.protocol.spring.SymbolElement;
1814

19-
public class RequestMappingIndexElement extends AbstractSpringIndexElement implements SymbolElement {
15+
public class RequestMappingIndexElement extends WebEndpointIndexElement {
2016

21-
private final String path;
22-
private final String[] httpMethods;
23-
private final String[] contentTypes;
24-
private final String[] acceptTypes;
25-
private final String symbolLabel;
26-
private final Range range;
27-
2817
public RequestMappingIndexElement(String path, String[] httpMethods, String[] contentTypes, String[] acceptTypes, Range range, String symbolLabel) {
29-
this.path = path;
30-
this.httpMethods = httpMethods;
31-
this.contentTypes = contentTypes;
32-
this.acceptTypes = acceptTypes;
33-
this.range = range;
34-
this.symbolLabel = symbolLabel;
18+
super(path, httpMethods, contentTypes, acceptTypes, range, symbolLabel);
3519
}
36-
37-
public String getPath() {
38-
return path;
39-
}
40-
41-
public String[] getHttpMethods() {
42-
return httpMethods;
43-
}
44-
45-
public String[] getContentTypes() {
46-
return contentTypes;
47-
}
48-
49-
public String[] getAcceptTypes() {
50-
return acceptTypes;
51-
}
52-
53-
@Override
54-
public DocumentSymbol getDocumentSymbol() {
55-
DocumentSymbol symbol = new DocumentSymbol();
56-
57-
symbol.setName(symbolLabel);
58-
symbol.setKind(SymbolKind.Method);
59-
symbol.setRange(range);
60-
symbol.setSelectionRange(range);
61-
62-
return symbol;
63-
}
64-
6520
}

0 commit comments

Comments
 (0)