From 8ef70e9e01433fb077518f03c72b8e7819a4b781 Mon Sep 17 00:00:00 2001 From: aboyko Date: Tue, 10 Oct 2023 16:14:23 -0400 Subject: [PATCH] Boot version validation progress and error reporting --- .../languageserver/MessageService.java | 23 ++++++++ .../languageserver/Sts4LanguageServer.java | 8 ++- .../util/SimpleLanguageServer.java | 33 +++++++++++ .../boot/app/BootVersionValidationConfig.java | 4 +- .../AbstractDiagnosticValidator.java | 11 ++++ .../generations/GenerationsValidator.java | 34 +++++++++--- .../ProjectVersionDiagnosticProvider.java | 55 ++++++++++++++----- .../generations/UpdateBootVersion.java | 10 ++++ .../generations/VersionValidationUtils.java | 20 ++++--- .../generations/VersionValidator.java | 4 +- 10 files changed, 168 insertions(+), 34 deletions(-) create mode 100644 headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/MessageService.java diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/MessageService.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/MessageService.java new file mode 100644 index 000000000..06772f643 --- /dev/null +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/MessageService.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2023 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.commons.languageserver; + +public interface MessageService { + + void error(String message); + + void warning(String message); + + void info(String message); + + void log(String message); + +} diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/Sts4LanguageServer.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/Sts4LanguageServer.java index c2dfab573..e21190327 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/Sts4LanguageServer.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/Sts4LanguageServer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017 Pivotal, Inc. + * Copyright (c) 2017, 2023 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 @@ -39,5 +39,11 @@ public interface Sts4LanguageServer extends LanguageServer { * @return */ DiagnosticService getDiagnosticService(); + + /** + * Message Service to show various string messages in the IDE client UI + * @return message service instance + */ + MessageService getMessageService(); } diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java index 1b1fc2682..4745b7c5d 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java @@ -79,6 +79,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContext; import org.springframework.ide.vscode.commons.languageserver.DiagnosticService; +import org.springframework.ide.vscode.commons.languageserver.MessageService; import org.springframework.ide.vscode.commons.languageserver.ProgressService; import org.springframework.ide.vscode.commons.languageserver.Sts4LanguageServer; import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionEngine; @@ -201,6 +202,33 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, SpringInd } } }; + + private MessageService messageService = new MessageService() { + + @Override + public void warning(String message) { + message(MessageType.Warning, message); + } + + @Override + public void log(String message) { + message(MessageType.Log, message); + } + + @Override + public void info(String message) { + message(MessageType.Info, message); + } + + @Override + public void error(String message) { + message(MessageType.Error, message); + } + + private void message(MessageType messageType, String message) { + getClient().showMessage(new MessageParams(messageType, message)); + } + }; private DiagnosticService diagnosticService = message -> onError(null, message); @@ -858,6 +886,11 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, SpringInd public ProgressService getProgressService() { return progressService; } + + @Override + public MessageService getMessageService() { + return messageService; + } public void setTestListener(LanguageServerTestListener languageServerTestListener) { Assert.isLegal(this.testListener==null); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootVersionValidationConfig.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootVersionValidationConfig.java index ba6eb7c21..7f6add42b 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootVersionValidationConfig.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootVersionValidationConfig.java @@ -50,8 +50,8 @@ public class BootVersionValidationConfig { return new GenerationsValidator(server.getDiagnosticSeverityProvider(), projectsProvider); } - @Bean ProjectVersionDiagnosticProvider projectVersionDiagnosticProvider(List validators) { - return new ProjectVersionDiagnosticProvider(validators); + @Bean ProjectVersionDiagnosticProvider projectVersionDiagnosticProvider(SimpleLanguageServer server, List validators) { + return new ProjectVersionDiagnosticProvider(server.getProgressService(), server.getMessageService(), validators); } @ConditionalOnMissingClass("org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness") diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/AbstractDiagnosticValidator.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/AbstractDiagnosticValidator.java index 407f7893a..5cdd4a434 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/AbstractDiagnosticValidator.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/AbstractDiagnosticValidator.java @@ -19,6 +19,7 @@ import org.eclipse.lsp4j.Position; import org.eclipse.lsp4j.Range; import org.springframework.ide.vscode.boot.validation.generations.preferences.VersionValidationProblemType; import org.springframework.ide.vscode.commons.languageserver.reconcile.DiagnosticSeverityProvider; +import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType; abstract public class AbstractDiagnosticValidator implements VersionValidator { @@ -69,4 +70,14 @@ abstract public class AbstractDiagnosticValidator implements VersionValidator { protected Diagnostic createDiagnostic(VersionValidationProblemType problemType, String diagnosticMessage) { return createDiagnostic(null, problemType, diagnosticMessage); } + + protected boolean isEnabled(ProblemType... problemTypes) { + for (ProblemType problemType : problemTypes) { + DiagnosticSeverity severity = diagnosticSeverityProvider.getDiagnosticSeverity(problemType); + if (severity != null) { + return true; + } + } + return false; + } } \ No newline at end of file diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/GenerationsValidator.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/GenerationsValidator.java index fdfcd2c4d..e2b291940 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/GenerationsValidator.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/GenerationsValidator.java @@ -21,7 +21,6 @@ import org.springframework.ide.vscode.commons.Version; import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.java.SpringProjectUtil; import org.springframework.ide.vscode.commons.languageserver.reconcile.DiagnosticSeverityProvider; -import org.springframework.ide.vscode.commons.util.Assert; import com.google.common.collect.ImmutableList; @@ -54,7 +53,6 @@ public class GenerationsValidator extends AbstractDiagnosticValidator { public Collection validate(IJavaProject javaProject, Version javaProjectVersion) throws Exception { ResolvedSpringProject springProject = provider.getProject(SpringProjectUtil.SPRING_BOOT); Generation javaProjectGen = getGenerationForJavaProject(javaProject, springProject); - Assert.isLegal(javaProjectGen != null, "Unable to find Spring Project Generation for project: " + javaProjectVersion.toString()); ImmutableList.Builder b = ImmutableList.builder(); if (VersionValidationUtils.isOssValid(javaProjectGen)) { @@ -70,9 +68,14 @@ public class GenerationsValidator extends AbstractDiagnosticValidator { } else { StringBuilder message = new StringBuilder(); message.append("OSS support for Spring Boot "); - message.append(javaProjectGen.getName()); - message.append(" no longer available, ended on: "); - message.append(javaProjectGen.getOssSupportEndDate()); + if (javaProjectGen == null) { + message.append(javaProjectVersion); + message.append(" not available!"); + } else { + message.append(javaProjectGen.getName()); + message.append(" no longer available, ended on: "); + message.append(javaProjectGen.getOssSupportEndDate()); + } Diagnostic d = createDiagnostic(VersionValidationProblemType.UNSUPPORTED_OSS_VERSION, message.toString()); if (d != null) { b.add(d); @@ -92,9 +95,14 @@ public class GenerationsValidator extends AbstractDiagnosticValidator { } else { StringBuilder message = new StringBuilder(); message.append("Commercial support for Spring Boot "); - message.append(javaProjectGen.getName()); - message.append(" no longer available, ended on: "); - message.append(javaProjectGen.getCommercialSupportEndDate()); + if (javaProjectGen == null) { + message.append(javaProjectVersion); + message.append(" not available!"); + } else { + message.append(javaProjectGen.getName()); + message.append(" no longer available, ended on: "); + message.append(javaProjectGen.getCommercialSupportEndDate()); + } Diagnostic d = createDiagnostic(VersionValidationProblemType.UNSUPPORTED_COMMERCIAL_VERSION, message.toString()); if (d != null) { b.add(d); @@ -104,4 +112,14 @@ public class GenerationsValidator extends AbstractDiagnosticValidator { return b.build(); } + @Override + public boolean isEnabled() { + return isEnabled( + VersionValidationProblemType.SUPPORTED_OSS_VERSION, + VersionValidationProblemType.UNSUPPORTED_OSS_VERSION, + VersionValidationProblemType.SUPPORTED_COMMERCIAL_VERSION, + VersionValidationProblemType.UNSUPPORTED_COMMERCIAL_VERSION + ); + } + } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/ProjectVersionDiagnosticProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/ProjectVersionDiagnosticProvider.java index 9842c545a..e4fc3e281 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/ProjectVersionDiagnosticProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/ProjectVersionDiagnosticProvider.java @@ -16,6 +16,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; import org.eclipse.lsp4j.Diagnostic; import org.slf4j.Logger; @@ -23,6 +24,9 @@ import org.slf4j.LoggerFactory; import org.springframework.ide.vscode.commons.Version; import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.java.SpringProjectUtil; +import org.springframework.ide.vscode.commons.languageserver.MessageService; +import org.springframework.ide.vscode.commons.languageserver.PercentageProgressTask; +import org.springframework.ide.vscode.commons.languageserver.ProgressService; public class ProjectVersionDiagnosticProvider { @@ -30,7 +34,13 @@ public class ProjectVersionDiagnosticProvider { private final List validators; - public ProjectVersionDiagnosticProvider(List validators) { + private ProgressService progressService; + + private MessageService messageService; + + public ProjectVersionDiagnosticProvider(ProgressService progressService, MessageService messageService, List validators) { + this.progressService = progressService; + this.messageService = messageService; this.validators = validators; } @@ -42,26 +52,41 @@ public class ProjectVersionDiagnosticProvider { throw new Exception("Unable to find build file in project while computing version validation for: " + javaProject.getElementName()); } - Version javaProjectVersion = SpringProjectUtil.getSpringBootVersion(javaProject); - - if (javaProjectVersion == null) { - log.warn("Unable to resolve version for project: " + javaProject.getLocationUri().toASCIIString()); - return new DiagnosticResult(buildFileUri, Collections.emptyList()); - } - + List applicableValidators = validators.stream().filter(v -> v.isEnabled()).collect(Collectors.toList()); List diagnostics = new ArrayList(); - for (VersionValidator validator : validators) { + + if (!applicableValidators.isEmpty()) { + PercentageProgressTask progress = progressService.createPercentageProgressTask( + "validate-" + javaProject.getElementName(), + applicableValidators.size(), + "Validating Spring Boot Version of project '%s'".formatted(javaProject.getElementName())); + try { - Collection batch = validator.validate(javaProject, javaProjectVersion); - if (batch != null) { - diagnostics.addAll(batch); + Version javaProjectVersion = SpringProjectUtil.getSpringBootVersion(javaProject); + + if (javaProjectVersion == null) { + log.warn("Unable to resolve version for project: " + javaProject.getLocationUri().toASCIIString()); + return new DiagnosticResult(buildFileUri, Collections.emptyList()); } - } catch (Exception e) { - log.error("", e); + + for (VersionValidator validator : applicableValidators) { + try { + Collection batch = validator.validate(javaProject, javaProjectVersion); + if (batch != null) { + diagnostics.addAll(batch); + } + } catch (Exception e) { + messageService.error("Failed Spring Boot version validation for project '%s': %s".formatted(javaProject.getElementName(), e.getMessage())); + log.error("", e); + } + progress.increment(); + } + } finally { + progress.done(); } } - + return new DiagnosticResult(buildFileUri, diagnostics); } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/UpdateBootVersion.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/UpdateBootVersion.java index 3a908ef8a..c4f14048c 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/UpdateBootVersion.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/UpdateBootVersion.java @@ -161,4 +161,14 @@ public class UpdateBootVersion extends AbstractDiagnosticValidator { ImmutableList.of(showDocumentParams))); return releaseNoteLink; } + + @Override + public boolean isEnabled() { + return isEnabled( + VersionValidationProblemType.UPDATE_LATEST_PATCH_VERSION, + VersionValidationProblemType.UPDATE_LATEST_MINOR_VERSION, + VersionValidationProblemType.UPDATE_LATEST_MAJOR_VERSION + ); + } + } \ No newline at end of file diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/VersionValidationUtils.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/VersionValidationUtils.java index f8597af51..2251c2fe1 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/VersionValidationUtils.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/VersionValidationUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2022 VMware, Inc. + * Copyright (c) 2022, 2023 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 @@ -20,15 +20,21 @@ import org.springframework.ide.vscode.commons.Version; public class VersionValidationUtils { public static boolean isOssValid(Generation gen) { - Date currentDate = new Date(System.currentTimeMillis()); - Date ossEndDate = Date.valueOf(gen.getOssSupportEndDate()); - return currentDate.before(ossEndDate); + if (gen != null) { + Date currentDate = new Date(System.currentTimeMillis()); + Date ossEndDate = Date.valueOf(gen.getOssSupportEndDate()); + return currentDate.before(ossEndDate); + } + return false; } public static boolean isCommercialValid(Generation gen) { - Date currentDate = new Date(System.currentTimeMillis()); - Date commercialEndDate = Date.valueOf(gen.getCommercialSupportEndDate()); - return currentDate.before(commercialEndDate); + if (gen != null) { + Date currentDate = new Date(System.currentTimeMillis()); + Date commercialEndDate = Date.valueOf(gen.getCommercialSupportEndDate()); + return currentDate.before(commercialEndDate); + } + return false; } public static Version getLatestSupportedRelease(ResolvedSpringProject springProject) diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/VersionValidator.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/VersionValidator.java index 22bf16bb0..ee7316700 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/VersionValidator.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/VersionValidator.java @@ -19,5 +19,7 @@ import org.springframework.ide.vscode.commons.java.IJavaProject; public interface VersionValidator { Collection validate(IJavaProject javaProject, Version javaProjectVersion) throws Exception; - + + boolean isEnabled(); + }