Project build data via classpath listener from JDT

This commit is contained in:
aboyko
2022-11-15 18:52:32 -05:00
parent 6bcaef95eb
commit ed4eef0e0a
24 changed files with 242 additions and 101 deletions

View File

@@ -29,9 +29,10 @@ import org.springframework.stereotype.Component;
public class BootVersionValidator {
private static final Logger log = LoggerFactory.getLogger(BootVersionValidator.class);
private SimpleLanguageServer server;
public BootVersionValidator(SimpleLanguageServer server, ProjectObserver observer) {
this.server = server;
observer.addListener(new ProjectObserver.Listener() {
@Override
@@ -40,28 +41,7 @@ public class BootVersionValidator {
@Override
public void created(IJavaProject project) {
VersionValidationPreferences preferences = new VersionValidationPreferences();
String url = getSpringProjectsUrl(preferences);
SpringProjectsClient client = new SpringProjectsClient(url);
SpringProjectsProvider provider = new SpringIoProjectsProvider(client);
VersionValidators validators = new VersionValidators(server.getDiagnosticSeverityProvider());
ProjectVersionDiagnosticProvider diagnosticProvider = new ProjectVersionDiagnosticProvider(provider,
validators);
try {
DiagnosticResult result = diagnosticProvider.getDiagnostics(project);
if (result != null && !result.getDiagnostics().isEmpty()) {
server.getTextDocumentService().publishDiagnostics(
new TextDocumentIdentifier(result.getDocumentUri().toString()),
result.getDiagnostics());
}
} catch (Exception e) {
log.error("Failed validating Spring Project version", e);
}
validate(project);
}
@Override
@@ -70,6 +50,30 @@ public class BootVersionValidator {
}
});
}
public void validate(IJavaProject project) {
VersionValidationPreferences preferences = new VersionValidationPreferences();
String url = getSpringProjectsUrl(preferences);
SpringProjectsClient client = new SpringProjectsClient(url);
SpringProjectsProvider provider = new SpringIoProjectsProvider(client);
VersionValidators validators = new VersionValidators(server.getDiagnosticSeverityProvider());
ProjectVersionDiagnosticProvider diagnosticProvider = new ProjectVersionDiagnosticProvider(provider,
validators);
try {
DiagnosticResult result = diagnosticProvider.getDiagnostics(project);
if (result != null && !result.getDiagnostics().isEmpty()) {
server.getTextDocumentService().publishDiagnostics(
new TextDocumentIdentifier(result.getDocumentUri().toString()),
result.getDiagnostics());
}
} catch (Exception e) {
log.error("Failed validating Spring Project version", e);
}
}
private String getSpringProjectsUrl(VersionValidationPreferences preferences) {
return preferences.getSpringProjectsUrl();

View File

@@ -23,6 +23,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.ide.vscode.boot.app.BootJavaConfig;
import org.springframework.ide.vscode.boot.app.BootLanguageServerParams;
import org.springframework.ide.vscode.boot.app.BootVersionValidator;
import org.springframework.ide.vscode.boot.app.SpringSymbolIndex;
import org.springframework.ide.vscode.boot.java.annotations.AnnotationHierarchyAwareLookup;
import org.springframework.ide.vscode.boot.java.autowired.AutowiredHoverProvider;
@@ -201,7 +202,7 @@ public class BootJavaLanguageServerComponents implements LanguageServerComponent
reconcileEngine = new BootJavaReconcileEngine(projectFinder, new JavaReconciler[] {
jdtReconciler,
rewriteJavaReconciler
}, documents);
}, documents, appContext.getBean(BootVersionValidator.class));
codeActionProvider = new BootJavaCodeActionProvider(
projectFinder,

View File

@@ -24,6 +24,7 @@ import java.util.stream.Stream;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.app.BootVersionValidator;
import org.springframework.ide.vscode.boot.common.IJavaProjectReconcileEngine;
import org.springframework.ide.vscode.boot.java.reconcilers.JavaReconciler;
import org.springframework.ide.vscode.commons.java.IClasspathUtil;
@@ -48,11 +49,14 @@ public class BootJavaReconcileEngine implements IReconcileEngine, IJavaProjectRe
private final SimpleTextDocumentService documents;
private final JavaProjectFinder projectFinder;
private JavaReconciler[] javaReconcilers;
private BootVersionValidator bootVersionValidator;
public BootJavaReconcileEngine(JavaProjectFinder projectFinder, JavaReconciler[] javaReconcilers, SimpleTextDocumentService documents) {
public BootJavaReconcileEngine(JavaProjectFinder projectFinder, JavaReconciler[] javaReconcilers, SimpleTextDocumentService documents, BootVersionValidator bootVersionValidator) {
this.documents = documents;
this.projectFinder = projectFinder;
this.javaReconcilers = javaReconcilers;
this.bootVersionValidator = bootVersionValidator;
}
@Override
@@ -113,6 +117,9 @@ public class BootJavaReconcileEngine implements IReconcileEngine, IJavaProjectRe
@Override
public void reconcile(IJavaProject project, Function<TextDocument, IProblemCollector> problemCollectorFactory) {
if (bootVersionValidator != null) {
bootVersionValidator.validate(project);
}
Stream<Path> files = IClasspathUtil.getProjectJavaSourceFolders(project.getClasspath()).flatMap(folder -> {
try {
return Files.walk(folder.toPath());

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2018, 2020 Pivotal, Inc.
* Copyright (c) 2018, 2022 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
@@ -34,6 +34,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.commons.java.ClasspathData;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.java.IJavadocProvider;
import org.springframework.ide.vscode.commons.java.IProjectBuild;
import org.springframework.ide.vscode.commons.java.JavaProject;
import org.springframework.ide.vscode.commons.java.JdtLsJavaProject;
import org.springframework.ide.vscode.commons.javadoc.JdtLsJavadocProvider;
@@ -41,6 +42,7 @@ import org.springframework.ide.vscode.commons.languageserver.java.ls.ClasspathLi
import org.springframework.ide.vscode.commons.languageserver.util.ServerCapabilityInitializer;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.protocol.java.Classpath.CPE;
import org.springframework.ide.vscode.commons.protocol.java.ProjectBuild;
import org.springframework.ide.vscode.commons.util.FileObserver;
import org.springframework.ide.vscode.commons.util.UriUtil;
@@ -346,10 +348,11 @@ public class JdtLsProjectCache implements InitializableJavaProjectsService, Serv
log.debug("deleted = false");
URI projectUri = new URI(uri);
ClasspathData classpath = new ClasspathData(event.name, event.classpath.getEntries());
IProjectBuild projectBuild = from(event.projectBuild);
IJavaProject newProject = IS_JANDEX_INDEX
? new JavaProject(getFileObserver(), projectUri, classpath,
JdtLsProjectCache.this)
: new JdtLsJavaProject(server.getClient(), projectUri, classpath, JdtLsProjectCache.this);
JdtLsProjectCache.this, projectBuild)
: new JdtLsJavaProject(server.getClient(), projectUri, classpath, JdtLsProjectCache.this, projectBuild);
IJavaProject oldProject = table.put(uri, newProject);
if (oldProject != null) {
notifyDelete(oldProject);
@@ -365,5 +368,9 @@ public class JdtLsProjectCache implements InitializableJavaProjectsService, Serv
});
}
}
private static IProjectBuild from(ProjectBuild projectBuild) {
return projectBuild == null ? null : IProjectBuild.create(projectBuild.getType(), projectBuild.getBuildFile() == null ? null : URI.create(projectBuild.getBuildFile()));
}
}

View File

@@ -12,12 +12,8 @@ package org.springframework.ide.vscode.boot.validation.generations;
import java.io.File;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.eclipse.lsp4j.Diagnostic;
import org.springframework.ide.vscode.boot.validation.generations.json.Generation;
@@ -26,12 +22,8 @@ import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.java.SpringProjectUtil;
import org.springframework.ide.vscode.commons.java.Version;
import com.google.common.collect.ImmutableSet;
public class ProjectVersionDiagnosticProvider {
private static final String[] BUILD_FILES = new String[] { "pom.xml", "build.gradle", "build.gradle.kts" };
private final SpringProjectsProvider provider;
private final VersionValidators validators;
@@ -43,7 +35,7 @@ public class ProjectVersionDiagnosticProvider {
public DiagnosticResult getDiagnostics(IJavaProject javaProject) throws Exception {
URI buildFileUri = getBuildFileUri(javaProject);
URI buildFileUri = javaProject.getProjectBuild() == null ? null : javaProject.getProjectBuild().getBuildFile();
if (buildFileUri == null) {
throw new Exception("Unable to find build file in project while computing version validation for: ");
}
@@ -91,22 +83,6 @@ public class ProjectVersionDiagnosticProvider {
return null;
}
protected URI getBuildFileUri(IJavaProject javaProject) throws Exception {
File buildFile = null;
Path projectPath = new File(javaProject.getLocationUri()).toPath();
if (Files.isDirectory(projectPath, new LinkOption[] { LinkOption.NOFOLLOW_LINKS })) {
ImmutableSet<String> buildFileNames = ImmutableSet.copyOf(BUILD_FILES);
List<Path> results = Files.list(projectPath).filter(Files::isRegularFile)
.filter(file -> buildFileNames.contains(file.toFile().getName())).collect(Collectors.toList());
if (results != null && results.size() == 1) {
buildFile = results.get(0).toFile();
}
}
return buildFile != null ? buildFile.toURI() : null;
}
protected File getSpringBootDependency(IJavaProject project) {
List<File> libs = SpringProjectUtil.getLibrariesOnClasspath(project, "spring-boot");
return libs != null && libs.size() > 0 ? libs.get(0) : null;

View File

@@ -17,6 +17,7 @@ import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.CodeActionKind;
import org.eclipse.lsp4j.Command;
import org.eclipse.lsp4j.Diagnostic;
import org.springframework.ide.vscode.boot.java.rewrite.SpringBootUpgrade;
import org.springframework.ide.vscode.boot.validation.generations.json.Generation;
import org.springframework.ide.vscode.boot.validation.generations.json.ResolvedSpringProject;
import org.springframework.ide.vscode.boot.validation.generations.preferences.VersionValidationProblemType;
@@ -157,7 +158,7 @@ public class VersionValidators {
CodeAction ca = new CodeAction();
ca.setKind(CodeActionKind.QuickFix);
ca.setTitle("Upgrade To Target Version");
String commandId = "sts/upgrade/spring-boot";
String commandId = SpringBootUpgrade.CMD_UPGRADE_SPRING_BOOT;
ca.setCommand(new Command("Upgrade To Target Version", commandId,
ImmutableList.of(javaProject.getLocationUri().toString(), latest.toString())));

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2018, 2020 Pivotal, Inc.
* Copyright (c) 2018, 2022 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
@@ -31,6 +31,7 @@ import org.junit.Assert;
import org.springframework.ide.vscode.commons.java.ClasspathIndex;
import org.springframework.ide.vscode.commons.java.IClasspath;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.java.IProjectBuild;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver;
import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver.Listener;
@@ -185,6 +186,11 @@ public class MockProjects {
public String uri(String projectRelativePath) {
return new File(root, projectRelativePath).toURI().toString();
}
@Override
public IProjectBuild getProjectBuild() {
return null;
}
}
public class MockProjectObserver implements ProjectObserver {

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2020, 2021 Pivotal, Inc.
* Copyright (c) 2020, 2022 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
@@ -147,7 +147,7 @@ public class ValueSpelExpressionValidationTest {
problemCollector = new TestProblemCollector();
reconcileEngine = new BootJavaReconcileEngine(projectFinder, new JavaReconciler[] {
new JdtReconciler(compilationUnitCache)
}, server.getTextDocumentService());
}, server.getTextDocumentService(), null);
}
@After

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016, 2018 Pivotal, Inc.
* Copyright (c) 2016, 2022 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
@@ -91,7 +91,7 @@ public class ProjectsHarness {
public static final IJavaProject dummyProject() throws URISyntaxException {
return new LegacyJavaProject(new BasicFileObserver(), new URI("file:///someplace/nonexistent"), null,
new DelegatingCachedClasspath(() -> null, null), (uri, cpe) -> JavaDocProviders.createFor(cpe));
new DelegatingCachedClasspath(() -> null, null), (uri, cpe) -> JavaDocProviders.createFor(cpe), null);
}
private ProjectsHarness(FileObserver fileObserver) {