added bean method container to index for bean methods without a configuration class around
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
/*******************************************************************************
|
||||
* 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.commons.protocol.spring;
|
||||
|
||||
import org.eclipse.lsp4j.Location;
|
||||
|
||||
/**
|
||||
* This index element is meant to capture bean elements from @Bean annotated
|
||||
* methods where the containing class is not a configuration class (e.g. Feign config
|
||||
* classes)
|
||||
*
|
||||
* This container element is meant for internal use and not to be displayed
|
||||
* on the UI, therefore this is not a symbol element.
|
||||
*
|
||||
* @author Martin Lippert
|
||||
*/
|
||||
public class BeanMethodContainerElement extends AbstractSpringIndexElement {
|
||||
|
||||
private final Location location;
|
||||
private final String type;
|
||||
|
||||
public BeanMethodContainerElement(Location location, String type) {
|
||||
super();
|
||||
this.location = location;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -35,6 +35,7 @@ import org.springframework.ide.vscode.boot.java.utils.SpringIndexerJavaContext;
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.AnnotationMetadata;
|
||||
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.commons.util.BadLocationException;
|
||||
import org.springframework.ide.vscode.commons.util.text.DocumentRegion;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
@@ -49,7 +50,7 @@ public class BeansIndexer {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(BeansIndexer.class);
|
||||
|
||||
public static void indexBeanMethod(Bean configBean, Annotation node, SpringIndexerJavaContext context, TextDocument doc) {
|
||||
public static void indexBeanMethod(SpringIndexElement parentNode, Annotation node, SpringIndexerJavaContext context, TextDocument doc) {
|
||||
if (node == null) return;
|
||||
|
||||
ASTNode parent = node.getParent();
|
||||
@@ -89,7 +90,7 @@ public class BeansIndexer {
|
||||
WebfluxRouterSymbolProvider.createWebfluxElements(beanDefinition, method, context, doc);
|
||||
}
|
||||
|
||||
configBean.addChild(beanDefinition);
|
||||
parentNode.addChild(beanDefinition);
|
||||
|
||||
} catch (BadLocationException e) {
|
||||
log.error("", e);
|
||||
|
||||
@@ -52,6 +52,7 @@ import org.springframework.ide.vscode.boot.java.utils.DefaultSymbolProvider;
|
||||
import org.springframework.ide.vscode.boot.java.utils.SpringIndexerJavaContext;
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.AnnotationMetadata;
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.BeanMethodContainerElement;
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.BeanRegistrarElement;
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.DefaultValues;
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.InjectionPoint;
|
||||
@@ -201,28 +202,49 @@ public class ComponentSymbolProvider implements SymbolProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private void indexBeanMethods(Bean bean, TypeDeclaration type, ITypeBinding annotationType, Collection<ITypeBinding> metaAnnotations, SpringIndexerJavaContext context, TextDocument doc) {
|
||||
private void indexBeanMethods(final Bean bean, TypeDeclaration type, ITypeBinding annotationType, Collection<ITypeBinding> metaAnnotations, SpringIndexerJavaContext context, TextDocument doc) {
|
||||
AnnotationHierarchies annotationHierarchies = AnnotationHierarchies.get(type);
|
||||
if (bean.isConfiguration()) {
|
||||
MethodDeclaration[] methods = type.getMethods();
|
||||
if (methods == null) {
|
||||
|
||||
SpringIndexElement parent = bean;
|
||||
|
||||
if (bean == null) {
|
||||
try {
|
||||
|
||||
Location location = new Location(doc.getUri(), doc.toRange(type.getName().getStartPosition(), type.getName().getLength()));
|
||||
String typeName = type.resolveBinding().getQualifiedName();
|
||||
parent = new BeanMethodContainerElement(location, typeName);
|
||||
|
||||
} catch (BadLocationException e) {
|
||||
log.error("error while looking up position for type: " + type.toString(), e);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
MethodDeclaration methodDecl = methods[i];
|
||||
Collection<Annotation> annotations = ASTUtils.getAnnotations(methodDecl);
|
||||
|
||||
for (Annotation annotation : annotations) {
|
||||
ITypeBinding typeBinding = annotation.resolveTypeBinding();
|
||||
|
||||
boolean isBeanMethod = annotationHierarchies.isAnnotatedWith(typeBinding, Annotations.BEAN);
|
||||
if (isBeanMethod) {
|
||||
BeansIndexer.indexBeanMethod(bean, annotation, context, doc);
|
||||
}
|
||||
}
|
||||
else if (!bean.isConfiguration()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MethodDeclaration[] methods = type.getMethods();
|
||||
if (methods == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
MethodDeclaration methodDecl = methods[i];
|
||||
Collection<Annotation> annotations = ASTUtils.getAnnotations(methodDecl);
|
||||
|
||||
for (Annotation annotation : annotations) {
|
||||
ITypeBinding typeBinding = annotation.resolveTypeBinding();
|
||||
|
||||
boolean isBeanMethod = annotationHierarchies.isAnnotatedWith(typeBinding, Annotations.BEAN);
|
||||
if (isBeanMethod) {
|
||||
BeansIndexer.indexBeanMethod(parent, annotation, context, doc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bean == null && parent.getChildren().size() > 0) {
|
||||
context.getBeans().add(new CachedBean(context.getDocURI(), parent));
|
||||
}
|
||||
}
|
||||
|
||||
private void indexEventListeners(Bean bean, TypeDeclaration type, ITypeBinding annotationType, Collection<ITypeBinding> metaAnnotations, SpringIndexerJavaContext context, TextDocument doc) {
|
||||
@@ -329,6 +351,7 @@ public class ComponentSymbolProvider implements SymbolProvider {
|
||||
if (!isComponment) {
|
||||
indexEventListenerInterfaceImplementation(null, typeDeclaration, context, doc);
|
||||
indexBeanRegistrarImplementation(null, typeDeclaration, context, doc);
|
||||
indexBeanMethods(null, typeDeclaration, null, null, context, doc);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ public class SpringIndexViaLSPMethodTest {
|
||||
List<Bean> beans = result.get(5, TimeUnit.SECONDS);
|
||||
|
||||
assertNotNull(beans);
|
||||
assertEquals(26, beans.size());
|
||||
assertEquals(SpringMetamodelIndexingTest.NO_OF_EXPECTED_BEANS, beans.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -98,7 +98,7 @@ public class SpringIndexViaLSPMethodTest {
|
||||
List<Bean> beans = result.get(5, TimeUnit.SECONDS);
|
||||
|
||||
assertNotNull(beans);
|
||||
assertEquals(25, beans.size());
|
||||
assertEquals(SpringMetamodelIndexingTest.NO_OF_EXPECTED_BEANS - 1, beans.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -40,9 +40,12 @@ import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFin
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.AnnotationAttributeValue;
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.AnnotationMetadata;
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.BeanMethodContainerElement;
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.DefaultValues;
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.DocumentElement;
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.InjectionPoint;
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.SpringIndexElement;
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.SymbolElement;
|
||||
import org.springframework.ide.vscode.project.harness.BootLanguageServerHarness;
|
||||
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
@@ -544,6 +547,34 @@ public class SpringMetamodelIndexerBeansTest {
|
||||
assertEquals("prof2", profileAttributeValues[1].getName());
|
||||
assertEquals(new Location(beans[0].getLocation().getUri(), new Range(new Position(9, 19), new Position(9, 26))), profileAttributeValues[1].getLocation());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBeanMethodsWithoutConfiguration() {
|
||||
String docUri = directory.toPath().resolve("src/main/java/org/test/BeanMethodsWithoutConfiguration.java").toUri().toString();
|
||||
|
||||
DocumentElement document = springIndex.getDocument(docUri);
|
||||
List<SpringIndexElement> docChildren = document.getChildren();
|
||||
assertEquals(1, docChildren.size());
|
||||
assertTrue(docChildren.get(0) instanceof BeanMethodContainerElement);
|
||||
|
||||
BeanMethodContainerElement container = (BeanMethodContainerElement) docChildren.get(0);
|
||||
assertEquals(docUri, container.getLocation().getUri());
|
||||
assertEquals("org.test.BeanMethodsWithoutConfiguration", container.getType());
|
||||
assertFalse(container instanceof SymbolElement);
|
||||
|
||||
List<SpringIndexElement> beans = container.getChildren();
|
||||
assertEquals(2, beans.size());
|
||||
|
||||
Bean bean1 = (Bean) beans.get(0);
|
||||
Bean bean2 = (Bean) beans.get(1);
|
||||
|
||||
assertEquals("beanWithoutConfig", bean1.getName());
|
||||
assertEquals("beanWithoutConfig2", bean2.getName());
|
||||
|
||||
Bean[] beansFound = springIndex.getBeansWithName("test-spring-indexing", "beanWithoutConfig");
|
||||
assertEquals(1, beansFound.length);
|
||||
assertSame(bean1, beansFound[0]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
@Import(SymbolProviderTestConf.class)
|
||||
public class SpringMetamodelIndexingTest {
|
||||
|
||||
private static final int NO_OF_EXPECTED_BEANS = 26;
|
||||
public static final int NO_OF_EXPECTED_BEANS = 28;
|
||||
|
||||
@Autowired private BootLanguageServerHarness harness;
|
||||
@Autowired private JavaProjectFinder projectFinder;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.test;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
public class BeanMethodsWithoutConfiguration {
|
||||
|
||||
@Bean
|
||||
public BeanClass1 beanWithoutConfig() {
|
||||
return new BeanClass1();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public BeanClass2 beanWithoutConfig2() {
|
||||
return new BeanClass2();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user