Skip to content

Commit 98a5992

Browse files
committed
GH-1530: requires complete index for validation and added more complicated test cases as a start for further testing
1 parent 13712bd commit 98a5992

File tree

9 files changed

+229
-2
lines changed

9 files changed

+229
-2
lines changed

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,12 @@ public boolean visit(TypeDeclaration node) {
8181

8282
ITypeBinding type = node.resolveBinding();
8383
if (type != null && ReconcileUtils.implementsAnyType(AOT_BEANS, type)) {
84-
String beanClassName = type.getQualifiedName();
8584

85+
if (!context.isIndexComplete()) {
86+
throw new RequiredCompleteIndexException();
87+
}
88+
89+
String beanClassName = type.getQualifiedName();
8690
Bean[] registeredBeans = springIndex.getBeansWithType(project.getElementName(), beanClassName);
8791

8892
if (registeredBeans == null || registeredBeans.length == 0) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
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.reconcilers.test;
12+
13+
import static org.junit.jupiter.api.Assertions.assertEquals;
14+
15+
import java.io.File;
16+
import java.util.List;
17+
import java.util.concurrent.CompletableFuture;
18+
import java.util.concurrent.TimeUnit;
19+
20+
import org.eclipse.lsp4j.Diagnostic;
21+
import org.eclipse.lsp4j.PublishDiagnosticsParams;
22+
import org.eclipse.lsp4j.TextDocumentIdentifier;
23+
import org.junit.jupiter.api.BeforeEach;
24+
import org.junit.jupiter.api.Disabled;
25+
import org.junit.jupiter.api.Test;
26+
import org.junit.jupiter.api.extension.ExtendWith;
27+
import org.springframework.beans.factory.annotation.Autowired;
28+
import org.springframework.context.annotation.Import;
29+
import org.springframework.ide.vscode.boot.app.BootJavaConfig;
30+
import org.springframework.ide.vscode.boot.app.SpringSymbolIndex;
31+
import org.springframework.ide.vscode.boot.bootiful.BootLanguageServerTest;
32+
import org.springframework.ide.vscode.boot.bootiful.SymbolProviderTestConf;
33+
import org.springframework.ide.vscode.boot.java.SpringAotJavaProblemType;
34+
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
35+
import org.springframework.ide.vscode.commons.languageserver.util.Settings;
36+
import org.springframework.ide.vscode.project.harness.BootLanguageServerHarness;
37+
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
38+
import org.springframework.test.context.junit.jupiter.SpringExtension;
39+
40+
import com.google.gson.Gson;
41+
import com.google.gson.JsonElement;
42+
43+
/**
44+
* @author Martin Lippert
45+
*/
46+
@ExtendWith(SpringExtension.class)
47+
@BootLanguageServerTest
48+
@Import(SymbolProviderTestConf.class)
49+
public class NotRegisteredBeansAdvancedReconcilingTest {
50+
51+
@Autowired private BootLanguageServerHarness harness;
52+
@Autowired private JavaProjectFinder projectFinder;
53+
@Autowired private SpringSymbolIndex indexer;
54+
@Autowired private BootJavaConfig config;
55+
56+
private File directory;
57+
58+
@BeforeEach
59+
public void setup() throws Exception {
60+
harness.intialize(null);
61+
62+
JsonElement json = new Gson().fromJson("""
63+
{
64+
"boot-java": {
65+
"validation": {
66+
"java": {
67+
"boot2": "AUTO",
68+
"boot3": "AUTO",
69+
"spring-aot": "ON",
70+
"version-validation": "ON"
71+
}
72+
}
73+
}
74+
}
75+
""", JsonElement.class);
76+
config.handleConfigurationChange(new Settings(json));
77+
78+
directory = new File(ProjectsHarness.class.getResource("/test-projects/test-spring-validations/").toURI());
79+
80+
String projectDir = directory.toURI().toString();
81+
82+
// trigger project creation
83+
projectFinder.find(new TextDocumentIdentifier(projectDir)).get();
84+
85+
CompletableFuture<Void> initProject = indexer.waitOperation();
86+
initProject.get(5, TimeUnit.SECONDS);
87+
}
88+
89+
@Test
90+
void testBasicValidationOfAotProcessorNotRegistered() throws Exception {
91+
String docUri = directory.toPath().resolve("src/main/java/org/test/aot/NotRegisteredBeanRegistrationAotProcessor.java").toUri().toString();
92+
93+
PublishDiagnosticsParams diagnosticsResult = harness.getDiagnostics(docUri);
94+
List<Diagnostic> diagnostics = diagnosticsResult.getDiagnostics();
95+
96+
assertEquals(1, diagnostics.size());
97+
assertEquals(SpringAotJavaProblemType.JAVA_BEAN_NOT_REGISTERED_IN_AOT.getCode(), diagnostics.get(0).getCode().getLeft());
98+
}
99+
100+
@Test
101+
void testBasicValidationOfAotProcessorRegisteredAsComponent() throws Exception {
102+
String docUri = directory.toPath().resolve("src/main/java/org/test/aot/RegisteredAsComponentBeanRegistrationAotProcessor.java").toUri().toString();
103+
104+
PublishDiagnosticsParams diagnosticsResult = harness.getDiagnostics(docUri);
105+
List<Diagnostic> diagnostics = diagnosticsResult.getDiagnostics();
106+
107+
assertEquals(0, diagnostics.size());
108+
}
109+
110+
@Test
111+
void testBasicValidationOfAotProcessorRegisteredViaConfig() throws Exception {
112+
String docUri = directory.toPath().resolve("src/main/java/org/test/aot/RegistetedViaConfigBeanRegistrationAotProcessor.java").toUri().toString();
113+
114+
PublishDiagnosticsParams diagnosticsResult = harness.getDiagnostics(docUri);
115+
List<Diagnostic> diagnostics = diagnosticsResult.getDiagnostics();
116+
117+
assertEquals(0, diagnostics.size());
118+
}
119+
120+
@Test
121+
@Disabled // this case needs work - (1) factories not taken into account at all, (2) requires complete index doesn't take other indexers into account yet
122+
void testBasicValidationOfAotProcessorRegisteredViaFactoriesFile() throws Exception {
123+
String docUri = directory.toPath().resolve("src/main/java/org/test/aot/RegisteredViaFactoriesBeanRegistrationAotProcessor.java").toUri().toString();
124+
125+
PublishDiagnosticsParams diagnosticsResult = harness.getDiagnostics(docUri);
126+
List<Diagnostic> diagnostics = diagnosticsResult.getDiagnostics();
127+
128+
assertEquals(0, diagnostics.size());
129+
}
130+
131+
@Test
132+
void testValidationDisappearsWhenComponentAnnotationIsAdded() throws Exception {
133+
// TODO
134+
}
135+
136+
@Test
137+
void testValidationAppearsWhenComponentAnnotationIsRemoved() throws Exception {
138+
// TODO
139+
}
140+
141+
@Test
142+
void testValidationDisappearsWhenBeanMethodIsAddedToConfig() throws Exception {
143+
// TODO
144+
}
145+
146+
@Test
147+
void testValidationAppearsWhenBeanMethodIsRemovedFromConfig() throws Exception {
148+
// TODO
149+
}
150+
151+
}

headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-validations/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<parent>
1212
<groupId>org.springframework.boot</groupId>
1313
<artifactId>spring-boot-starter-parent</artifactId>
14-
<version>3.1.2</version>
14+
<version>3.4.4</version>
1515
<relativePath/> <!-- lookup parent from repository -->
1616
</parent>
1717

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.test.aot;
2+
3+
import org.springframework.context.annotation.Bean;
4+
import org.springframework.context.annotation.Configuration;
5+
6+
@Configuration
7+
public class Config {
8+
9+
@Bean
10+
RegistetedViaConfigBeanRegistrationAotProcessor registeredViaConfigAotProcessor() {
11+
return new RegistetedViaConfigBeanRegistrationAotProcessor();
12+
}
13+
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.test.aot;
2+
3+
import org.springframework.beans.factory.aot.BeanRegistrationAotContribution;
4+
import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor;
5+
import org.springframework.beans.factory.support.RegisteredBean;
6+
7+
public class NotRegisteredBeanRegistrationAotProcessor implements BeanRegistrationAotProcessor {
8+
9+
@Override
10+
public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
11+
return null;
12+
}
13+
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package org.test.aot;
2+
3+
import org.springframework.beans.factory.aot.BeanRegistrationAotContribution;
4+
import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor;
5+
import org.springframework.beans.factory.support.RegisteredBean;
6+
import org.springframework.stereotype.Component;
7+
8+
@Component
9+
public class RegisteredAsComponentBeanRegistrationAotProcessor implements BeanRegistrationAotProcessor {
10+
11+
@Override
12+
public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
13+
return null;
14+
}
15+
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.test.aot;
2+
3+
import org.springframework.beans.factory.aot.BeanRegistrationAotContribution;
4+
import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor;
5+
import org.springframework.beans.factory.support.RegisteredBean;
6+
7+
public class RegisteredViaFactoriesBeanRegistrationAotProcessor implements BeanRegistrationAotProcessor {
8+
9+
@Override
10+
public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
11+
return null;
12+
}
13+
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.test.aot;
2+
3+
import org.springframework.beans.factory.aot.BeanRegistrationAotContribution;
4+
import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor;
5+
import org.springframework.beans.factory.support.RegisteredBean;
6+
7+
public class RegistetedViaConfigBeanRegistrationAotProcessor implements BeanRegistrationAotProcessor {
8+
9+
@Override
10+
public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
11+
return null;
12+
}
13+
14+
}

headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-validations/src/main/resources/META-INF/spring/aot.factories

Whitespace-only changes.

0 commit comments

Comments
 (0)