Minimal Spring Factories support in Boot LS

This commit is contained in:
aboyko
2022-10-20 10:15:29 -04:00
parent 4618a07968
commit 0fb7e7daca
10 changed files with 243 additions and 3 deletions

View File

@@ -11,7 +11,6 @@
package org.springframework.ide.vscode.boot.app;
import java.net.URI;
import java.nio.file.Path;
import java.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
@@ -28,6 +27,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.ide.vscode.boot.common.IJavaProjectReconcileEngine;
import org.springframework.ide.vscode.boot.factories.SpringFactoriesLanguageServerComponents;
import org.springframework.ide.vscode.boot.java.BootJavaLanguageServerComponents;
import org.springframework.ide.vscode.boot.java.links.JavaElementLocationProvider;
import org.springframework.ide.vscode.boot.java.links.SourceLinks;
@@ -143,6 +143,7 @@ public class BootLanguageServerInitializer implements InitializingBean {
BootJavaLanguageServerComponents bootJavaLanguageServerComponent = new BootJavaLanguageServerComponents(appContext);
builder.add(bootJavaLanguageServerComponent);
builder.add(new SpringXMLLanguageServerComponents(server, springIndexer, params, config));
builder.add(new SpringFactoriesLanguageServerComponents(projectFinder, springIndexer));
components = builder.build(server);
projectReconciler = (IJavaProjectReconcileEngine) bootJavaLanguageServerComponent.getReconcileEngine().get();

View File

@@ -0,0 +1,54 @@
/*******************************************************************************
* Copyright (c) 2022 VMware, 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
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.factories;
import java.util.Optional;
import java.util.Set;
import org.springframework.ide.vscode.boot.app.SpringSymbolIndex;
import org.springframework.ide.vscode.commons.languageserver.composable.LanguageServerComponents;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IReconcileEngine;
import org.springframework.ide.vscode.commons.languageserver.util.DocumentSymbolHandler;
import org.springframework.ide.vscode.commons.languageserver.util.HoverHandler;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
public class SpringFactoriesLanguageServerComponents implements LanguageServerComponents {
private SpringFactoriesReconcileEngine reconciler;
private SpringSymbolIndex springIndex;
public SpringFactoriesLanguageServerComponents(JavaProjectFinder projectFinder, SpringSymbolIndex springIndex) {
this.springIndex = springIndex;
reconciler = new SpringFactoriesReconcileEngine(projectFinder);
}
@Override
public Set<LanguageId> getInterestingLanguages() {
return Set.of(LanguageId.SPRING_FACTORIES);
}
@Override
public HoverHandler getHoverProvider() {
return null;
}
@Override
public Optional<IReconcileEngine> getReconcileEngine() {
return Optional.of(reconciler);
}
@Override
public Optional<DocumentSymbolHandler> getDocumentSymbolProvider() {
return Optional.of(params -> springIndex.getSymbols(params.getTextDocument().getUri()));
}
}

View File

@@ -0,0 +1,76 @@
package org.springframework.ide.vscode.boot.factories;
/*******************************************************************************
* Copyright (c) 2022 VMware, 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
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
import java.util.Map;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.springframework.ide.vscode.boot.java.Boot3JavaProblemType;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.java.SpringProjectUtil;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IReconcileEngine;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblemImpl;
import org.springframework.ide.vscode.commons.util.text.IDocument;
import org.springframework.ide.vscode.java.properties.antlr.parser.AntlrParser;
import org.springframework.ide.vscode.java.properties.parser.PropertiesAst;
import org.springframework.ide.vscode.java.properties.parser.PropertiesAst.KeyValuePair;
public class SpringFactoriesReconcileEngine implements IReconcileEngine {
@FunctionalInterface
interface KeyValuePairReconciler {
void reconcile(IJavaProject project, KeyValuePair pair, IProblemCollector problemCollector);
}
private final JavaProjectFinder projectFinder;
private AntlrParser parser = new AntlrParser();
private final Map<String, KeyValuePairReconciler> keyValuePairReconcilers = Map.of(
"org.springframework.boot.autoconfigure.EnableAutoConfiguration", (project, pair, problemCollector) -> {
if (SpringProjectUtil.springBootVersionGreaterOrEqual(3, 0, 0).test(project)) {
ReconcileProblemImpl problem = new ReconcileProblemImpl(
Boot3JavaProblemType.FACTORIES_KEY_NOT_SUPPORTED,
"Key is not supported as of Spring Boot 3. See Boot 3 documentation topic \"Locating Auto-configuration Candidates\"",
pair.getOffset(),
pair.getLength());
problemCollector.accept(problem);
}
}
);
public SpringFactoriesReconcileEngine(JavaProjectFinder projectFinder) {
this.projectFinder = projectFinder;
}
@Override
public void reconcile(IDocument doc, IProblemCollector problemCollector) {
projectFinder.find(new TextDocumentIdentifier(doc.getUri())).ifPresent(project -> {
problemCollector.beginCollecting();
try {
PropertiesAst ast = parser.parse(doc.get()).ast;
if (ast != null) {
for (KeyValuePair pair : ast.getNodes(KeyValuePair.class)) {
String key = pair.getKey().decode().trim();
KeyValuePairReconciler r = keyValuePairReconcilers.get(key);
if (r != null) {
r.reconcile(project, pair, problemCollector);
}
}
}
} finally {
problemCollector.endCollecting();
}
});
}
}

View File

@@ -30,7 +30,9 @@ public enum Boot3JavaProblemType implements ProblemType {
JAVA_BEAN_NOT_REGISTERED_IN_AOT(WARNING, "Not registered as Bean", "Not registered as a Bean"),
JAVA_TYPE_NOT_SUPPORTED(ERROR, "Type no supported as of Spring Boot 3", "Type not supported as of Spring Boot 3");
JAVA_TYPE_NOT_SUPPORTED(ERROR, "Type no supported as of Spring Boot 3", "Type not supported as of Spring Boot 3"),
FACTORIES_KEY_NOT_SUPPORTED(ERROR, "Spring factories key not supported", "Spring factories key not supported");
private final ProblemSeverity defaultSeverity;
private String description;

View File

@@ -72,6 +72,12 @@
"label": "Type not supported as of Spring Boot 3",
"description": "Type no supported as of Spring Boot 3",
"defaultSeverity": "ERROR"
},
{
"code": "FACTORIES_KEY_NOT_SUPPORTED",
"label": "Spring factories key not supported",
"description": "Spring factories key not supported",
"defaultSeverity": "ERROR"
}
]
},