Skip to content

Commit ab69e82

Browse files
committed
GH-1498: bean registrars are not bean index eleements anymore, but have a dedicated index element instead
1 parent 7ae1e52 commit ab69e82

File tree

6 files changed

+84
-39
lines changed

6 files changed

+84
-39
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.commons.protocol.spring;
12+
13+
import org.eclipse.lsp4j.DocumentSymbol;
14+
import org.eclipse.lsp4j.Location;
15+
import org.eclipse.lsp4j.SymbolKind;
16+
17+
public class BeanRegistrarElement extends AbstractSpringIndexElement implements SymbolElement {
18+
19+
private final String name;
20+
private final String type;
21+
private final Location location;
22+
23+
public BeanRegistrarElement(String name, String type, Location location) {
24+
this.name = name;
25+
this.type = type;
26+
this.location = location;
27+
}
28+
29+
public String getType() {
30+
return type;
31+
}
32+
33+
public Location getLocation() {
34+
return location;
35+
}
36+
37+
@Override
38+
public DocumentSymbol getDocumentSymbol() {
39+
return new DocumentSymbol(
40+
name + " (Bean Registrar)",
41+
SymbolKind.Class,
42+
location.getRange(), location.getRange());
43+
}
44+
45+
}

Diff for: headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/ComponentSymbolProvider.java

+21-25
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.eclipse.jdt.core.dom.MethodDeclaration;
3131
import org.eclipse.jdt.core.dom.MethodInvocation;
3232
import org.eclipse.jdt.core.dom.RecordDeclaration;
33+
import org.eclipse.jdt.core.dom.SimpleName;
3334
import org.eclipse.jdt.core.dom.TypeDeclaration;
3435
import org.eclipse.lsp4j.Location;
3536
import org.eclipse.lsp4j.SymbolKind;
@@ -51,9 +52,11 @@
5152
import org.springframework.ide.vscode.boot.java.utils.SpringIndexerJavaContext;
5253
import org.springframework.ide.vscode.commons.protocol.spring.AnnotationMetadata;
5354
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
55+
import org.springframework.ide.vscode.commons.protocol.spring.BeanRegistrarElement;
5456
import org.springframework.ide.vscode.commons.protocol.spring.DefaultValues;
5557
import org.springframework.ide.vscode.commons.protocol.spring.InjectionPoint;
5658
import org.springframework.ide.vscode.commons.protocol.spring.SimpleSymbolElement;
59+
import org.springframework.ide.vscode.commons.protocol.spring.SpringIndexElement;
5760
import org.springframework.ide.vscode.commons.util.BadLocationException;
5861
import org.springframework.ide.vscode.commons.util.text.DocumentRegion;
5962
import org.springframework.ide.vscode.commons.util.text.TextDocument;
@@ -401,7 +404,7 @@ private MethodDeclaration findRegisterMethod(TypeDeclaration type, ITypeBinding
401404
return null;
402405
}
403406

404-
private void indexBeanRegistrarImplementation(Bean bean, TypeDeclaration typeDeclaration, SpringIndexerJavaContext context, TextDocument doc) {
407+
private void indexBeanRegistrarImplementation(SpringIndexElement parentNode, TypeDeclaration typeDeclaration, SpringIndexerJavaContext context, TextDocument doc) {
405408
try {
406409
ITypeBinding typeBinding = typeDeclaration.resolveBinding();
407410
if (typeBinding == null) return;
@@ -416,39 +419,32 @@ private void indexBeanRegistrarImplementation(Bean bean, TypeDeclaration typeDec
416419
throw new RequiredCompleteAstException();
417420
}
418421

419-
if (bean == null) { // need to create and register bean element
420-
String beanType = typeBinding.getQualifiedName();
421-
String beanName = BeanUtils.getBeanNameFromType(typeBinding.getName());
422+
if (parentNode == null) { // need to create and register bean element
423+
String name = typeBinding.getName();
424+
String type = typeBinding.getQualifiedName();
422425

423-
Location location = new Location(doc.getUri(), doc.toRange(typeDeclaration.getStartPosition(), typeDeclaration.getLength()));
426+
SimpleName typeNameNode = typeDeclaration.getName();
427+
Location location = new Location(doc.getUri(), doc.toRange(typeNameNode.getStartPosition(), typeNameNode.getLength()));
424428

425429
WorkspaceSymbol symbol = new WorkspaceSymbol(
426-
beanLabel("+", null, null, beanName, beanType),
427-
SymbolKind.Class,
430+
name + " (Bean Registrar)",
431+
SymbolKind.Interface,
428432
Either.forLeft(location));
429433

430-
InjectionPoint[] injectionPoints = ASTUtils.findInjectionPoints(typeDeclaration, doc);
431-
432-
Set<String> supertypes = new HashSet<>();
433-
ASTUtils.findSupertypes(typeBinding, supertypes);
434-
435-
Collection<Annotation> annotationsOnMethod = ASTUtils.getAnnotations(typeDeclaration);
436-
AnnotationMetadata[] annotations = ASTUtils.getAnnotationsMetadata(annotationsOnMethod, doc);
437-
438-
bean = new Bean(beanName, beanType, location, injectionPoints, supertypes, annotations, false, symbol.getName());
434+
parentNode = new BeanRegistrarElement(name, type, location);
439435

440436
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), symbol));
441-
context.getBeans().add(new CachedBean(context.getDocURI(), bean));
437+
context.getBeans().add(new CachedBean(context.getDocURI(), parentNode));
442438
}
443439

444-
scanBeanRegistryInvocations(bean, registerMethod.getBody(), context, doc);
440+
scanBeanRegistryInvocations(parentNode, registerMethod.getBody(), context, doc);
445441

446442
} catch (BadLocationException e) {
447443
log.error("", e);
448444
}
449445
}
450446

451-
private void scanBeanRegistryInvocations(Bean component, Block body, SpringIndexerJavaContext context, TextDocument doc) {
447+
private void scanBeanRegistryInvocations(SpringIndexElement parent, Block body, SpringIndexerJavaContext context, TextDocument doc) {
452448
if (body == null) {
453449
return;
454450
}
@@ -491,7 +487,7 @@ public boolean visit(MethodInvocation methodInvocation) {
491487
String beanName = BeanUtils.getBeanNameFromType(typeParameters[0].getName());
492488
String beanType = typeParamName;
493489

494-
createBean(component, beanName, beanType, typeParameters[0], methodInvocation, context, doc);
490+
createBean(parent, beanName, beanType, typeParameters[0], methodInvocation, context, doc);
495491
}
496492
}
497493
else if (arguments.size() == 2 && "java.lang.String".equals(types.get(0).getQualifiedName()) && "java.lang.Class".equals(types.get(1).getBinaryName())) {
@@ -505,7 +501,7 @@ else if (arguments.size() == 2 && "java.lang.String".equals(types.get(0).getQual
505501
String typeParamName = typeParameters[0].getBinaryName();
506502
String beanType = typeParamName;
507503

508-
createBean(component, beanName, beanType, typeParameters[0], methodInvocation, context, doc);
504+
createBean(parent, beanName, beanType, typeParameters[0], methodInvocation, context, doc);
509505
}
510506
}
511507
else if (arguments.size() == 2 && "java.lang.Class".equals(types.get(0).getBinaryName()) && "java.util.function.Consumer".equals(types.get(1).getBinaryName())) {
@@ -519,7 +515,7 @@ else if (arguments.size() == 2 && "java.lang.Class".equals(types.get(0).getBinar
519515
String beanName = BeanUtils.getBeanNameFromType(typeParameters[0].getName());
520516
String beanType = typeParamName;
521517

522-
createBean(component, beanName, beanType, typeParameters[0], methodInvocation, context, doc);
518+
createBean(parent, beanName, beanType, typeParameters[0], methodInvocation, context, doc);
523519
}
524520
}
525521
else if (arguments.size() == 3 && "java.lang.String".equals(types.get(0).getQualifiedName())
@@ -534,7 +530,7 @@ else if (arguments.size() == 3 && "java.lang.String".equals(types.get(0).getQual
534530
String typeParamName = typeParameters[0].getBinaryName();
535531
String beanType = typeParamName;
536532

537-
createBean(component, beanName, beanType, typeParameters[0], methodInvocation, context, doc);
533+
createBean(parent, beanName, beanType, typeParameters[0], methodInvocation, context, doc);
538534
}
539535
}
540536
}
@@ -548,7 +544,7 @@ else if (arguments.size() == 3 && "java.lang.String".equals(types.get(0).getQual
548544
});
549545
}
550546

551-
public void createBean(Bean parentBean, String beanName, String beanType, ITypeBinding beanTypeBinding, ASTNode node, SpringIndexerJavaContext context, TextDocument doc) throws BadLocationException {
547+
public void createBean(SpringIndexElement parentNode, String beanName, String beanType, ITypeBinding beanTypeBinding, ASTNode node, SpringIndexerJavaContext context, TextDocument doc) throws BadLocationException {
552548
Location location = new Location(doc.getUri(), doc.toRange(node.getStartPosition(), node.getLength()));
553549

554550
WorkspaceSymbol symbol = new WorkspaceSymbol(
@@ -564,7 +560,7 @@ public void createBean(Bean parentBean, String beanName, String beanType, ITypeB
564560
AnnotationMetadata[] annotations = DefaultValues.EMPTY_ANNOTATIONS;
565561

566562
Bean bean = new Bean(beanName, beanType, location, injectionPoints, supertypes, annotations, false, symbol.getName());
567-
parentBean.addChild(bean);
563+
parentNode.addChild(bean);
568564
}
569565

570566
public static String beanLabel(String searchPrefix, String annotationTypeName, Collection<String> metaAnnotationNames, String beanName, String beanType) {

Diff for: headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/reconcilers/BeanRegistrarDeclarationReconciler.java

+6-4
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
3838
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblemImpl;
3939
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
40+
import org.springframework.ide.vscode.commons.protocol.spring.BeanRegistrarElement;
4041
import org.springframework.ide.vscode.commons.protocol.spring.SpringIndexElement;
4142
import org.springframework.ide.vscode.commons.rewrite.config.RecipeScope;
4243
import org.springframework.ide.vscode.commons.rewrite.java.FixDescriptor;
@@ -168,10 +169,11 @@ protected void identifyPossibleRegistrarsForReconciling(ReconcilingContext conte
168169

169170
Set<String> importedTypesDelta = getImportAnnotationTypesDelta(createdIndexElements, previuosIndexElements);
170171

171-
Arrays.stream(springIndex.getBeans())
172-
.filter(bean -> bean.isTypeCompatibleWith(Annotations.BEAN_REGISTRAR_INTERFACE))
173-
.filter(bean -> importedTypesDelta.contains(bean.getType()))
174-
.map(bean -> bean.getLocation().getUri())
172+
List<BeanRegistrarElement> registrarElements = springIndex.getNodesOfType(BeanRegistrarElement.class);
173+
174+
registrarElements.stream()
175+
.filter(registrar -> importedTypesDelta.contains(registrar.getType()))
176+
.map(registrar -> registrar.getLocation().getUri())
175177
.map(docURI -> UriUtil.toFileString(docURI))
176178
.forEach(file -> context.markForAffetcedFilesIndexing(file));
177179
}

Diff for: headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerJava.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public class SpringIndexerJava implements SpringIndexer {
9292

9393
// whenever the implementation of the indexer changes in a way that the stored data in the cache is no longer valid,
9494
// we need to change the generation - this will result in a re-indexing due to no up-to-date cache data being found
95-
private static final String GENERATION = "GEN-17";
95+
private static final String GENERATION = "GEN-18";
9696
private static final String INDEX_FILES_TASK_ID = "index-java-source-files-task-";
9797

9898
private static final String SYMBOL_KEY = "symbols";

Diff for: headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/index/test/SpringIndexerBeanRegistrarTest.java

+11-7
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*******************************************************************************/
1111
package org.springframework.ide.vscode.boot.index.test;
1212

13+
import static org.junit.Assert.assertFalse;
1314
import static org.junit.Assert.assertTrue;
1415
import static org.junit.jupiter.api.Assertions.assertEquals;
1516

@@ -31,8 +32,9 @@
3132
import org.springframework.ide.vscode.boot.index.SpringMetamodelIndex;
3233
import org.springframework.ide.vscode.boot.java.Annotations;
3334
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
34-
import org.springframework.ide.vscode.commons.protocol.spring.AnnotationMetadata;
3535
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
36+
import org.springframework.ide.vscode.commons.protocol.spring.BeanRegistrarElement;
37+
import org.springframework.ide.vscode.commons.protocol.spring.DocumentElement;
3638
import org.springframework.ide.vscode.commons.protocol.spring.SpringIndexElement;
3739
import org.springframework.ide.vscode.project.harness.BootLanguageServerHarness;
3840
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
@@ -72,15 +74,17 @@ public void setup() throws Exception {
7274
void testSimpleBeanRegistration() throws Exception {
7375
String docUri = directory.toPath().resolve("src/main/java/com/example/MyBeanRegistrar.java").toUri().toString();
7476

75-
Bean[] beans = springIndex.getBeansOfDocument(docUri);
76-
assertEquals(5, beans.length);
77+
Bean[] beansOfDoc = springIndex.getBeansOfDocument(docUri);
78+
assertFalse(Arrays.stream(beansOfDoc).anyMatch(bean -> bean.getName().equals("myBeanRegistrar")));
7779

78-
Bean beanRegistrarBean = Arrays.stream(beans).filter(bean -> bean.getName().equals("myBeanRegistrar")).findFirst().get();
79-
assertEquals("com.example.MyBeanRegistrar", beanRegistrarBean.getType());
80+
DocumentElement document = springIndex.getDocument(docUri);
81+
List<SpringIndexElement> docChildren = document.getChildren();
82+
assertEquals(1, docChildren.size());
83+
assertTrue(docChildren.get(0) instanceof BeanRegistrarElement);
8084

81-
List<SpringIndexElement> children = beanRegistrarBean.getChildren();
85+
List<SpringIndexElement> children = docChildren.get(0).getChildren();
8286
assertEquals(4, children.size());
83-
87+
8488
Bean fooFoo = (Bean) children.get(0);
8589
assertEquals("fooFoo", fooFoo.getName());
8690
assertEquals("com.example.FooFoo", fooFoo.getType());

Diff for: headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/reconcilers/test/BeanRegistrarAdvancedReconcilingTest.java

-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import org.springframework.ide.vscode.boot.app.SpringSymbolIndex;
3232
import org.springframework.ide.vscode.boot.bootiful.BootLanguageServerTest;
3333
import org.springframework.ide.vscode.boot.bootiful.SymbolProviderTestConf;
34-
import org.springframework.ide.vscode.boot.index.SpringMetamodelIndex;
3534
import org.springframework.ide.vscode.boot.java.Boot4JavaProblemType;
3635
import org.springframework.ide.vscode.boot.java.utils.test.TestFileScanListener;
3736
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
@@ -51,7 +50,6 @@ public class BeanRegistrarAdvancedReconcilingTest {
5150
@Autowired private BootLanguageServerHarness harness;
5251
@Autowired private JavaProjectFinder projectFinder;
5352
@Autowired private SpringSymbolIndex indexer;
54-
@Autowired private SpringMetamodelIndex springIndex;
5553

5654
private File directory;
5755

0 commit comments

Comments
 (0)