From 8adb26325f8799c893a7d9567ccb600ea5e975b7 Mon Sep 17 00:00:00 2001 From: Martin Lippert Date: Thu, 16 Jan 2025 12:17:16 +0100 Subject: [PATCH] GH-1449: webflux index elements gets updated correctly on file changes Fixes GH-1449 --- .../boot/java/beans/BeansSymbolProvider.java | 22 +++++++------ .../WebFluxMappingSymbolProviderTest.java | 32 +++++++++++++++++++ 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/BeansSymbolProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/BeansSymbolProvider.java index dd5105303..dd8efdf31 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/BeansSymbolProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/BeansSymbolProvider.java @@ -18,6 +18,7 @@ import java.util.Set; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.Annotation; +import org.eclipse.jdt.core.dom.Block; import org.eclipse.jdt.core.dom.IAnnotationBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.MethodDeclaration; @@ -62,7 +63,6 @@ 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 @@ -73,21 +73,23 @@ public class BeansSymbolProvider extends AbstractSymbolProvider { if (parent == null || !(parent instanceof MethodDeclaration)) return; MethodDeclaration method = (MethodDeclaration) parent; - if (isMethodAbstract(method)) return; + List childElements = new ArrayList<>(); + 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 childElements = new ArrayList<>(); - if (isWebfluxRouter) { - WebfluxRouterSymbolProvider.createWebfluxElements(method, context, doc, childElements); + Block methodBody = method.getBody(); + if ((methodBody == null || methodBody.statements() == null || methodBody.statements().size() == 0) + && SCAN_PASS.ONE.equals(context.getPass())) { + context.getNextPassFiles().add(context.getFile()); + return; + } + else { + WebfluxRouterSymbolProvider.createWebfluxElements(method, context, doc, childElements); + } } boolean isFunction = isFunctionBean(method); diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java index 838fb7478..30afb4c44 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebFluxMappingSymbolProviderTest.java @@ -14,6 +14,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; +import java.net.URI; +import java.nio.charset.Charset; import java.util.Arrays; import java.util.Iterator; import java.util.List; @@ -21,6 +23,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; +import org.apache.commons.io.FileUtils; import org.eclipse.lsp4j.TextDocumentIdentifier; import org.eclipse.lsp4j.WorkspaceSymbol; import org.junit.jupiter.api.BeforeEach; @@ -36,6 +39,7 @@ import org.springframework.ide.vscode.boot.java.requestmapping.WebfluxHandlerMet 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.InjectionPoint; 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; @@ -284,6 +288,34 @@ public class WebFluxMappingSymbolProviderTest { assertEquals("org.test.PersonHandler3", handlerElement6.getHandlerClass()); assertEquals("public Mono deletePerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerElement6.getHandlerMethod()); } + + @Test + void testUpdatedRouteInChangedDocument() throws Exception { + // update document and update index + String changedDocURI = directory.toPath().resolve("src/main/java/org/test/QuoteRouter.java").toUri().toString(); + + String newContent = FileUtils.readFileToString(new File(new URI(changedDocURI)), Charset.defaultCharset()).replace("/hello", "/hello-updated"); + CompletableFuture updateFuture = indexer.updateDocument(changedDocURI, newContent, "test triggered"); + updateFuture.get(5, TimeUnit.SECONDS); + + Bean[] routeBeans = springIndex.getBeansWithName(project.getElementName(), "route"); + assertEquals(1, routeBeans.length); + assertEquals("route", routeBeans[0].getName()); + + SpringIndexElement[] children = routeBeans[0].getChildren(); + assertEquals(8, children.length); + + WebfluxHandlerMethodIndexElement handlerElement1 = getWebfluxIndexElements(children, "/hello-updated", "GET").get(0); + assertEquals("/hello-updated", 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 hello(org.springframework.web.reactive.function.server.ServerRequest)", handlerElement1.getHandlerMethod()); + + } + + private boolean containsSymbol(List symbols, String name, String uri, int startLine, int startCHaracter, int endLine, int endCharacter) { for (Iterator iterator = symbols.iterator(); iterator.hasNext();) {