From 24492fe231e8124105a63fcbbda644ad1c548961 Mon Sep 17 00:00:00 2001 From: Martin Lippert Date: Sat, 21 Dec 2024 20:37:05 +0100 Subject: [PATCH] switch xml bean hyperlink provider to new spring index --- .../app/XmlBeansConfigDefinitionHandler.java | 24 ++++-- .../hyperlinks/BeanRefHyperlinkProvider.java | 74 ++++--------------- .../hyperlinks/JavaTypeHyperlinkProvider.java | 7 +- .../PropertyNameHyperlinkProvider.java | 10 ++- .../xml/hyperlinks/XMLHyperlinkProvider.java | 6 +- .../boot/xml/test/XMLBeansHyperlinkTest.java | 3 +- 6 files changed, 45 insertions(+), 79 deletions(-) diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/XmlBeansConfigDefinitionHandler.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/XmlBeansConfigDefinitionHandler.java index c1af3a8d9d..4ee45eb4e2 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/XmlBeansConfigDefinitionHandler.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/XmlBeansConfigDefinitionHandler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019, 2021 Pivotal, Inc. + * Copyright (c) 2019, 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 @@ -61,6 +61,7 @@ import org.eclipse.lsp4j.jsonrpc.CancelChecker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.ide.vscode.boot.index.SpringMetamodelIndex; import org.springframework.ide.vscode.boot.java.links.JavaElementLocationProvider; import org.springframework.ide.vscode.boot.xml.XMLElementKey; import org.springframework.ide.vscode.boot.xml.hyperlinks.BeanRefHyperlinkProvider; @@ -93,7 +94,7 @@ public class XmlBeansConfigDefinitionHandler implements DefinitionHandler, Langu public XmlBeansConfigDefinitionHandler(SimpleTextDocumentService documents, BootJavaConfig config, JavaElementLocationProvider locationProvider, - SpringSymbolIndex symbolIndex, + SpringMetamodelIndex springIndex, BootLanguageServerParams serverParams) { this.documents = documents; this.config = config; @@ -101,7 +102,7 @@ public XmlBeansConfigDefinitionHandler(SimpleTextDocumentService documents, JavaTypeHyperlinkProvider javaTypeHyperlinkProvider = new JavaTypeHyperlinkProvider(projectFinder, locationProvider); PropertyNameHyperlinkProvider propertyNameHyperlinkProvider = new PropertyNameHyperlinkProvider(projectFinder, locationProvider); - BeanRefHyperlinkProvider beanRefHyperlinkProvider = new BeanRefHyperlinkProvider(projectFinder, symbolIndex); + BeanRefHyperlinkProvider beanRefHyperlinkProvider = new BeanRefHyperlinkProvider(projectFinder, springIndex); List typeHandlersOnly = Arrays.asList(javaTypeHyperlinkProvider); List propertyNameHandlers = Arrays.asList(propertyNameHyperlinkProvider); @@ -184,15 +185,22 @@ public List handle(CancelChecker cancelToken, DefinitionParams par List providers = hyperlinkProviders.get(key); if (providers != null) { + ImmutableList.Builder listBuilder = ImmutableList.builder(); for (XMLHyperlinkProvider provider : providers) { - Location location = provider.getDefinition(doc, namespace, node, attributeAt); - if (location != null) { + + List locations = provider.getDefinition(doc, namespace, node, attributeAt); + if (locations != null) { + int start = attributeAt.getNodeAttrValue().getStart() + 1; int end = attributeAt.getNodeAttrValue().getEnd() - 1; - listBuilder.add(new LocationLink(location.getUri(), - location.getRange(), location.getRange(), - doc.toRange(start, Math.max(0, end - start)))); + + for (Location location : locations) { + listBuilder.add(new LocationLink(location.getUri(), + location.getRange(), location.getRange(), + doc.toRange(start, Math.max(0, end - start)))); + + } } } return listBuilder.build(); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/xml/hyperlinks/BeanRefHyperlinkProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/xml/hyperlinks/BeanRefHyperlinkProvider.java index cc2b39cf86..de701de953 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/xml/hyperlinks/BeanRefHyperlinkProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/xml/hyperlinks/BeanRefHyperlinkProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019, 2021 Pivotal, Inc. + * Copyright (c) 2019, 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 @@ -10,22 +10,17 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.xml.hyperlinks; +import java.util.Arrays; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; import org.eclipse.lemminx.dom.DOMAttr; import org.eclipse.lemminx.dom.DOMNode; import org.eclipse.lsp4j.Location; -import org.eclipse.lsp4j.WorkspaceSymbol; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.ide.vscode.boot.app.SpringSymbolIndex; -import org.springframework.ide.vscode.boot.java.beans.BeansSymbolAddOnInformation; -import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation; -import org.springframework.ide.vscode.boot.java.handlers.SymbolAddOnInformation; +import org.springframework.ide.vscode.boot.index.SpringMetamodelIndex; 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.util.text.TextDocument; /** @@ -33,71 +28,30 @@ */ public class BeanRefHyperlinkProvider implements XMLHyperlinkProvider { - private static final Logger log = LoggerFactory.getLogger(BeanRefHyperlinkProvider.class); - private final JavaProjectFinder projectFinder; - private final SpringSymbolIndex symbolIndex; + private final SpringMetamodelIndex springIndex; - public BeanRefHyperlinkProvider(JavaProjectFinder projectFinder, SpringSymbolIndex symbolIndex) { + public BeanRefHyperlinkProvider(JavaProjectFinder projectFinder, SpringMetamodelIndex springIndex) { this.projectFinder = projectFinder; - this.symbolIndex = symbolIndex; + this.springIndex = springIndex; } @Override - public Location getDefinition(TextDocument doc, String namespace, DOMNode node, DOMAttr attributeAt) { + public List getDefinition(TextDocument doc, String namespace, DOMNode node, DOMAttr attributeAt) { Optional foundProject = this.projectFinder.find(doc.getId()); if (foundProject.isPresent()) { final IJavaProject project = foundProject.get(); - String projectLocation = project.getLocationUri() != null ? project.getLocationUri().toASCIIString() : ""; - - // make sure the project and the symbol location share the same prefix "file:///" - // looks like project locations are containing a "file:/" only - if (!projectLocation.startsWith("file:///")) { - projectLocation = "file:///" + projectLocation.substring("file:/".length()); - } - // make sure that only exact project locations are matched - if (!projectLocation.endsWith("/")) { - projectLocation = projectLocation + "/"; - } + String beanID = attributeAt.getValue(); + Bean[] beans = springIndex.getBeansWithName(project.getElementName(), beanID); - List symbols = symbolIndex.getSymbols(data -> symbolsFilter(data, attributeAt.getValue())).collect(Collectors.toList()); - if (!symbols.isEmpty()) { - for (WorkspaceSymbol symbol : symbols) { - if (symbol.getLocation().isLeft()) { - Location location = symbol.getLocation().getLeft(); - String uri = location.getUri(); - - if (uri != null && uri.startsWith(projectLocation)) { - return location; - } - } - } - // TODO: need better handling for the WorkspaceSymbolLocation case - for (WorkspaceSymbol symbol : symbols) { - if (symbol.getLocation().isLeft()) { - return symbol.getLocation().getLeft(); - } - } - } else { - log.debug("No Symbols!!!"); + if (beans != null && beans.length > 0) { + return Arrays.stream(beans) + .map(bean -> bean.getLocation()) + .toList(); } } return null; } - private boolean symbolsFilter(EnhancedSymbolInformation data, String beanId) { - SymbolAddOnInformation[] additionalInformation = data.getAdditionalInformation(); - if (beanId != null && additionalInformation != null) { - for (SymbolAddOnInformation info : additionalInformation) { - if (info instanceof BeansSymbolAddOnInformation) { - String id = ((BeansSymbolAddOnInformation)info).getBeanID(); - log.debug("Bean symbol id = " + id); - return beanId.equals(id); - } - } - } - return false; - } - } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/xml/hyperlinks/JavaTypeHyperlinkProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/xml/hyperlinks/JavaTypeHyperlinkProvider.java index f36c976d53..07091da3c5 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/xml/hyperlinks/JavaTypeHyperlinkProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/xml/hyperlinks/JavaTypeHyperlinkProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019, 2020 Pivotal, Inc. + * Copyright (c) 2019, 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 @@ -10,6 +10,7 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.xml.hyperlinks; +import java.util.List; import java.util.Optional; import org.eclipse.lemminx.dom.DOMAttr; @@ -35,7 +36,7 @@ public JavaTypeHyperlinkProvider(JavaProjectFinder projectFinder, JavaElementLoc } @Override - public Location getDefinition(TextDocument doc, String namespace, DOMNode node, DOMAttr attributeAt) { + public List getDefinition(TextDocument doc, String namespace, DOMNode node, DOMAttr attributeAt) { Optional foundProject = this.projectFinder.find(doc.getId()); if (foundProject.isPresent()) { IJavaProject project = foundProject.get(); @@ -43,7 +44,7 @@ public Location getDefinition(TextDocument doc, String namespace, DOMNode node, if (fqName != null) { IType type = project.getIndex().findType(fqName); if (type != null) { - return locationProvider.findLocation(project, type); + return List.of(locationProvider.findLocation(project, type)); } } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/xml/hyperlinks/PropertyNameHyperlinkProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/xml/hyperlinks/PropertyNameHyperlinkProvider.java index f308842158..6d72228203 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/xml/hyperlinks/PropertyNameHyperlinkProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/xml/hyperlinks/PropertyNameHyperlinkProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019, 2020 Pivotal, Inc. + * Copyright (c) 2019, 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 @@ -10,6 +10,7 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.xml.hyperlinks; +import java.util.List; import java.util.Optional; import org.eclipse.lemminx.dom.DOMAttr; @@ -35,18 +36,19 @@ public PropertyNameHyperlinkProvider(JavaProjectFinder projectFinder, JavaElemen } @Override - public Location getDefinition(TextDocument doc, String namespace, DOMNode node, DOMAttr attributeAt) { + public List getDefinition(TextDocument doc, String namespace, DOMNode node, DOMAttr attributeAt) { Optional foundProject = this.projectFinder.find(doc.getId()); String propertyName = attributeAt.getValue(); + if (foundProject.isPresent() && propertyName != null && !propertyName.isEmpty()) { IJavaProject project = foundProject.get(); String beanClass = PropertyNameCompletionProposalProvider.identifyBeanClass(node); + if (beanClass != null && beanClass.length() > 0) { return PropertyNameCompletionProposalProvider.propertyNameCandidateMethods(project, beanClass) .filter(method -> propertyName.equals(PropertyNameCompletionProposalProvider.getPropertyName(method))) .map(method -> locationProvider.findLocation(project, method)) - .findFirst() - .orElse(null); + .toList(); } } return null; diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/xml/hyperlinks/XMLHyperlinkProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/xml/hyperlinks/XMLHyperlinkProvider.java index 3e117e20ed..3f41a0ed4e 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/xml/hyperlinks/XMLHyperlinkProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/xml/hyperlinks/XMLHyperlinkProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019, 2020 Pivotal, Inc. + * Copyright (c) 2019, 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 @@ -10,6 +10,8 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.xml.hyperlinks; +import java.util.List; + import org.eclipse.lemminx.dom.DOMAttr; import org.eclipse.lemminx.dom.DOMNode; import org.eclipse.lsp4j.Location; @@ -20,6 +22,6 @@ */ public interface XMLHyperlinkProvider { - Location getDefinition(TextDocument doc, String namespace, DOMNode node, DOMAttr attributeAt); + List getDefinition(TextDocument doc, String namespace, DOMNode node, DOMAttr attributeAt); } diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/xml/test/XMLBeansHyperlinkTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/xml/test/XMLBeansHyperlinkTest.java index 3b83192b4e..458e71a817 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/xml/test/XMLBeansHyperlinkTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/xml/test/XMLBeansHyperlinkTest.java @@ -24,7 +24,6 @@ import org.eclipse.lsp4j.Range; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -172,7 +171,7 @@ void testBeanPropertyNameFromSuperClassHyperlink() throws Exception { } @Test - @Disabled +// @Disabled void testBeanRefHyperlink() throws Exception { log.debug("------------------ testBeanRefHyperlink ----------------------"); Path xmlFilePath = Paths.get(project.getLocationUri()).resolve("beans.xml");