From 6bcaef95eb1aedea5f23ce1d2b7f454d4ff44cea Mon Sep 17 00:00:00 2001 From: Nieraj Singh Date: Tue, 15 Nov 2022 07:54:27 -0800 Subject: [PATCH] GH-884: Added preferences for version validation Adopted existing preferences used for Boot 2, Boot 3, etc.. --- .../vscode/boot/app/BootVersionValidator.java | 43 ++- .../boot/common/SpringProblemCategories.java | 3 +- .../AbstractDiagnosticValidator.java | 64 +++++ .../ProjectVersionDiagnosticProvider.java | 121 +++----- .../generations/VersionValidation.java | 40 --- .../VersionValidationPreferences.java | 39 --- .../generations/VersionValidationUtils.java | 2 +- .../generations/VersionValidator.java | 15 +- .../generations/VersionValidators.java | 259 +++++++++--------- .../VersionValidationPreferences.java} | 25 +- .../VersionValidationProblemType.java | 75 +++++ .../src/main/resources/problem-types.json | 46 ++++ .../boot/test/ProblemTypesMetadataTest.java | 2 + .../vscode/boot/test/ProblemTypesToJson.java | 4 +- .../vscode-spring-boot/package.json | 76 +++++ 15 files changed, 463 insertions(+), 351 deletions(-) create mode 100644 headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/AbstractDiagnosticValidator.java delete mode 100644 headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/VersionValidation.java delete mode 100644 headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/VersionValidationPreferences.java rename headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/{SpringProjectDiagnostic.java => preferences/VersionValidationPreferences.java} (60%) create mode 100644 headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/preferences/VersionValidationProblemType.java diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootVersionValidator.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootVersionValidator.java index 96527bf54..2c235d095 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootVersionValidator.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootVersionValidator.java @@ -10,18 +10,16 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.app; -import java.util.List; - import org.eclipse.lsp4j.TextDocumentIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ide.vscode.boot.validation.generations.ProjectVersionDiagnosticProvider; +import org.springframework.ide.vscode.boot.validation.generations.ProjectVersionDiagnosticProvider.DiagnosticResult; import org.springframework.ide.vscode.boot.validation.generations.SpringIoProjectsProvider; -import org.springframework.ide.vscode.boot.validation.generations.SpringProjectDiagnostic; import org.springframework.ide.vscode.boot.validation.generations.SpringProjectsClient; import org.springframework.ide.vscode.boot.validation.generations.SpringProjectsProvider; -import org.springframework.ide.vscode.boot.validation.generations.VersionValidationPreferences; import org.springframework.ide.vscode.boot.validation.generations.VersionValidators; +import org.springframework.ide.vscode.boot.validation.generations.preferences.VersionValidationPreferences; import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver; import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer; @@ -29,18 +27,17 @@ import org.springframework.stereotype.Component; @Component public class BootVersionValidator { - + private static final Logger log = LoggerFactory.getLogger(BootVersionValidator.class); - public BootVersionValidator(SimpleLanguageServer server, ProjectObserver observer) { - + observer.addListener(new ProjectObserver.Listener() { - + @Override public void deleted(IJavaProject project) { } - + @Override public void created(IJavaProject project) { VersionValidationPreferences preferences = new VersionValidationPreferences(); @@ -48,30 +45,32 @@ public class BootVersionValidator { String url = getSpringProjectsUrl(preferences); SpringProjectsClient client = new SpringProjectsClient(url); SpringProjectsProvider provider = new SpringIoProjectsProvider(client); - VersionValidators validators = new VersionValidators(preferences); - - ProjectVersionDiagnosticProvider diagnosticProvider = new ProjectVersionDiagnosticProvider(provider, validators); - + VersionValidators validators = new VersionValidators(server.getDiagnosticSeverityProvider()); + + ProjectVersionDiagnosticProvider diagnosticProvider = new ProjectVersionDiagnosticProvider(provider, + validators); + try { - List diagnostics = diagnosticProvider.getDiagnostics(project); - if (diagnostics != null) { - for (SpringProjectDiagnostic springProjectDiagnostic : diagnostics) { - server.getTextDocumentService().publishDiagnostics(new TextDocumentIdentifier(springProjectDiagnostic.getUri().toString()), List.of(springProjectDiagnostic.getDiagnostic())); - } + 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); } - + } - + @Override public void changed(IJavaProject project) { - + } }); } - + private String getSpringProjectsUrl(VersionValidationPreferences preferences) { return preferences.getSpringProjectsUrl(); } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/common/SpringProblemCategories.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/common/SpringProblemCategories.java index ab6664dd6..824b1daaa 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/common/SpringProblemCategories.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/common/SpringProblemCategories.java @@ -35,6 +35,7 @@ public class SpringProblemCategories { public static final ProblemCategory SPEL = new ProblemCategory("spel", "SPEL Validation", new Toggle("Enablement", EnumSet.of(OFF, ON), ON, "boot-java.validation.spel.on")); - + public static final ProblemCategory VERSION_VALIDATION = new ProblemCategory("version-validation", "Spring Boot Version Validation", + new Toggle("Enablement", EnumSet.of(OFF, ON), ON, "boot-java.validation.java.version-validation")); } 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 new file mode 100644 index 000000000..754ec57f8 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/AbstractDiagnosticValidator.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * 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.validation.generations; + +import java.util.List; + +import org.eclipse.lsp4j.CodeAction; +import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.DiagnosticSeverity; +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; + + +abstract public class AbstractDiagnosticValidator implements VersionValidator { + + + private final DiagnosticSeverityProvider diagnosticSeverityProvider; + + public AbstractDiagnosticValidator(DiagnosticSeverityProvider diagnosticSeverityProvider) { + this.diagnosticSeverityProvider = diagnosticSeverityProvider; + } + + protected Diagnostic createDiagnostic(CodeAction action, VersionValidationProblemType problemType, String diagnosticMessage) { + DiagnosticSeverity severity = diagnosticSeverityProvider.getDiagnosticSeverity(problemType); + + Diagnostic diagnostic = new Diagnostic(); + diagnostic.setCode(VersionValidators.BOOT_VERSION_VALIDATION_CODE); + diagnostic.setMessage(diagnosticMessage.toString()); + + Range range = new Range(); + Position start = new Position(); + start.setLine(0); + start.setCharacter(0); + range.setStart(start); + Position end = new Position(); + end.setLine(0); + end.setCharacter(1); + range.setEnd(end); + diagnostic.setRange(range); + diagnostic.setSeverity(severity); + + if (action != null) { + Diagnostic refDiagnostic = new Diagnostic(diagnostic.getRange(), diagnostic.getMessage(), + diagnostic.getSeverity(), diagnostic.getSource()); + action.setDiagnostics(List.of(refDiagnostic)); + diagnostic.setData(action); + } + return diagnostic; + } + + protected Diagnostic createDiagnostic(VersionValidationProblemType problemType, String diagnosticMessage) { + return createDiagnostic(null, problemType, diagnosticMessage); + } +} \ 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/ProjectVersionDiagnosticProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/ProjectVersionDiagnosticProvider.java index da881bf54..9bc5ebc78 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 @@ -15,51 +15,37 @@ 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.CodeAction; -import org.eclipse.lsp4j.CodeActionKind; -import org.eclipse.lsp4j.Command; import org.eclipse.lsp4j.Diagnostic; -import org.eclipse.lsp4j.DiagnosticSeverity; -import org.eclipse.lsp4j.Position; -import org.eclipse.lsp4j.Range; -import org.openrewrite.java.tree.J.If; 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.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.java.SpringProjectUtil; import org.springframework.ide.vscode.commons.java.Version; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; - public class ProjectVersionDiagnosticProvider { - public static final String BOOT_VERSION_VALIDATION_CODE = "BOOT_VERSION_VALIDATION_CODE"; private static final String[] BUILD_FILES = new String[] { "pom.xml", "build.gradle", "build.gradle.kts" }; private final SpringProjectsProvider provider; private final VersionValidators validators; - public ProjectVersionDiagnosticProvider(SpringProjectsProvider provider, VersionValidators validationConditions) { + public ProjectVersionDiagnosticProvider(SpringProjectsProvider provider, VersionValidators validators) { + this.validators = validators; this.provider = provider; - this.validators = validationConditions; } - /** - * - * @return Non-null list of Diagnostics for the given Java project. Can be empty if no diagnostics are - * applicable. - * @throws If error encountered while getting diagnostics - */ - public List getDiagnostics(IJavaProject javaProject) throws Exception { - URI uri = getBuildFileUri(javaProject); - if (uri == null) { - return ImmutableList.of(); + public DiagnosticResult getDiagnostics(IJavaProject javaProject) throws Exception { + + URI buildFileUri = getBuildFileUri(javaProject); + if (buildFileUri == null) { + throw new Exception("Unable to find build file in project while computing version validation for: "); } ResolvedSpringProject springProject = provider.getProject(SpringProjectUtil.SPRING_BOOT); @@ -72,57 +58,21 @@ public class ProjectVersionDiagnosticProvider { Generation javaProjectGeneration = getGenerationForJavaProject(javaProject, springProject); if (javaProjectGeneration == null) { - throw new Exception("Unable to find Spring Project Generation for project: " + javaProjectVersion.toString()); + throw new Exception( + "Unable to find Spring Project Generation for project: " + javaProjectVersion.toString()); } - VersionValidation validation = null; + List diagnostics = new ArrayList(); for (VersionValidator validator : validators.getValidators()) { - if (validator.isEnabled()) { - validation = validator.getValidation(springProject, javaProjectGeneration, javaProjectVersion); - if (validation != null) { - break; - } + Diagnostic diagnostic = validator.validate(springProject, javaProject, javaProjectGeneration, + javaProjectVersion); + if (diagnostic != null) { + diagnostics.add(diagnostic); } } - if (validation != null) { - - DiagnosticSeverity severity = validation.getSeverity(); - Version toUpgrade = validation.getVersionToUprade(); - - StringBuffer msg = new StringBuffer(); - msg.append(validation.getMessage()); - - if (toUpgrade != null) { - msg.append('\n'); - msg.append("Consider upgrading to a newer supported version: "); - msg.append(toUpgrade.toString()); - } - - Diagnostic diagnostic = new Diagnostic(); - diagnostic.setCode(BOOT_VERSION_VALIDATION_CODE); - diagnostic.setMessage(msg.toString()); - - Range range = new Range(); - Position start = new Position(); - start.setLine(0); - start.setCharacter(0); - range.setStart(start); - Position end = new Position(); - end.setLine(0); - end.setCharacter(1); - range.setEnd(end); - diagnostic.setRange(range); - diagnostic.setSeverity(severity); - - setQuickfix(diagnostic, toUpgrade, javaProject.getLocationUri().toString()); - - return ImmutableList.of(new SpringProjectDiagnostic(diagnostic, uri)); - - } - - return ImmutableList.of(); + return new DiagnosticResult(buildFileUri, diagnostics); } private Generation getGenerationForJavaProject(IJavaProject javaProject, ResolvedSpringProject springProject) @@ -141,18 +91,6 @@ public class ProjectVersionDiagnosticProvider { return null; } - private void setQuickfix(Diagnostic diagnostic, Version toUpgrade, String projectUri) { - Diagnostic refDiagnostic = new Diagnostic(diagnostic.getRange(), diagnostic.getMessage(), - diagnostic.getSeverity(), diagnostic.getSource()); - CodeAction ca = new CodeAction(); - ca.setKind(CodeActionKind.QuickFix); - ca.setTitle("Upgrade To Target Version"); - ca.setDiagnostics(List.of(refDiagnostic)); - String commandId = "sts/upgrade/spring-boot"; - ca.setCommand(new Command("Upgrade To Target Version", commandId, ImmutableList.of(projectUri, toUpgrade.toString()))); - diagnostic.setData(ca); - } - protected URI getBuildFileUri(IJavaProject javaProject) throws Exception { File buildFile = null; Path projectPath = new File(javaProject.getLocationUri()).toPath(); @@ -160,8 +98,7 @@ public class ProjectVersionDiagnosticProvider { ImmutableSet buildFileNames = ImmutableSet.copyOf(BUILD_FILES); List results = Files.list(projectPath).filter(Files::isRegularFile) - .filter(file -> buildFileNames.contains(file.toFile().getName())) - .collect(Collectors.toList()); + .filter(file -> buildFileNames.contains(file.toFile().getName())).collect(Collectors.toList()); if (results != null && results.size() == 1) { buildFile = results.get(0).toFile(); @@ -178,4 +115,28 @@ public class ProjectVersionDiagnosticProvider { protected Version getVersion(Generation generation) throws Exception { return SpringProjectUtil.getVersionFromGeneration(generation.getName()); } + + public static class DiagnosticResult { + + private final URI documentUri; + private final List diagnostics; + + + public DiagnosticResult(URI documentUri, List diagnostics) { + super(); + this.documentUri = documentUri; + this.diagnostics = diagnostics; + } + + + public URI getDocumentUri() { + return documentUri; + } + + + public List getDiagnostics() { + return diagnostics; + } + + } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/VersionValidation.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/VersionValidation.java deleted file mode 100644 index 8547892a3..000000000 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/VersionValidation.java +++ /dev/null @@ -1,40 +0,0 @@ -/******************************************************************************* - * 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.validation.generations; - -import org.eclipse.lsp4j.DiagnosticSeverity; -import org.springframework.ide.vscode.commons.java.Version; - -public class VersionValidation { - - private final Version versionToUpgrade; - private final DiagnosticSeverity severity; - private final String message; - - public VersionValidation(Version versionToUpgrade, DiagnosticSeverity severity, String message) { - this.versionToUpgrade = versionToUpgrade; - this.severity = severity; - this.message = message; - } - - public DiagnosticSeverity getSeverity() { - return this.severity; - } - - public Version getVersionToUprade() { - return this.versionToUpgrade; - } - - public String getMessage() { - return this.message; - } - -} diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/VersionValidationPreferences.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/VersionValidationPreferences.java deleted file mode 100644 index ca9123d72..000000000 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/VersionValidationPreferences.java +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************************* - * 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.validation.generations; - -import org.eclipse.lsp4j.DiagnosticSeverity; - -// TODO: integrate with actual LS preferences -public class VersionValidationPreferences { - - private static final String DEFAULT_SPRING_PROJECT_URL = "https://spring.io/api/projects"; - - public ValidationPreference getSupportedPreference() { - return new ValidationPreference(true, DiagnosticSeverity.Hint); - } - - public ValidationPreference getUnsupportedOssPreference() { - return new ValidationPreference(true, DiagnosticSeverity.Warning); - } - - public ValidationPreference getUnsupportedCommercialPreference() { - return new ValidationPreference(true, DiagnosticSeverity.Warning); - } - - public ValidationPreference getUnsupportedPreference() { - return new ValidationPreference(true, DiagnosticSeverity.Error); - } - - public String getSpringProjectsUrl() { - return DEFAULT_SPRING_PROJECT_URL; - } -} 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 6edb99a9d..e191fa3a0 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 @@ -47,7 +47,7 @@ public class VersionValidationUtils { return null; } - public static Version getLatestSupportedRelease(ResolvedSpringProject springProject, Version version) + public static Version getLatestSupportedRelease(ResolvedSpringProject springProject) throws Exception { List rls = springProject.getReleases(); for (Release release : rls) { 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 71536f959..d8a565588 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 @@ -10,24 +10,15 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.validation.generations; +import org.eclipse.lsp4j.Diagnostic; 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.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.java.Version; public interface VersionValidator { - /** - * - * @param springProject contains information about the spring project associated - * with the generation and version to validate - * @param generation to validate - * @param version to validate - * @return validation if application. Null otherwise - * @throws Exception - */ - VersionValidation getValidation(ResolvedSpringProject springProject, Generation generation, Version version) + Diagnostic validate(ResolvedSpringProject springProject, IJavaProject javaProject, Generation javaProjectGen, Version javaProjectVersion) throws Exception; - boolean isEnabled(); - } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/VersionValidators.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/VersionValidators.java index 5cadb8523..59fbb5b14 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/VersionValidators.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/VersionValidators.java @@ -13,171 +13,158 @@ package org.springframework.ide.vscode.boot.validation.generations; import java.util.Arrays; import java.util.List; -import org.eclipse.lsp4j.DiagnosticSeverity; +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.validation.generations.json.Generation; import org.springframework.ide.vscode.boot.validation.generations.json.ResolvedSpringProject; +import org.springframework.ide.vscode.boot.validation.generations.preferences.VersionValidationProblemType; +import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.java.Version; +import org.springframework.ide.vscode.commons.languageserver.reconcile.DiagnosticSeverityProvider; + +import com.google.common.collect.ImmutableList; public class VersionValidators { - + + public static final String BOOT_VERSION_VALIDATION_CODE = "BOOT_VERSION_VALIDATION_CODE"; + private final VersionValidator[] validators; - public VersionValidators(VersionValidationPreferences preferences) { - this.validators = new VersionValidator[] { - new SupportedValidator(preferences), new UnsupportedCommercialValidator(preferences), - new UnsupportedOssValidator(preferences), new UnsupportedValidator(preferences) - }; + public VersionValidators(DiagnosticSeverityProvider diagnosticSeverityProvider) { + this.validators = new VersionValidator[] { new SupportedOssValidator(diagnosticSeverityProvider), + new UnsupportedCommercialValidator(diagnosticSeverityProvider), + new UnsupportedOssValidator(diagnosticSeverityProvider), + new SupportedCommercialValidator(diagnosticSeverityProvider), + new UpdateLatestMajorVersion(diagnosticSeverityProvider) }; } public List getValidators() { return Arrays.asList(this.validators); } - private static class SupportedValidator implements VersionValidator { + private static class SupportedOssValidator extends AbstractDiagnosticValidator { - private final VersionValidationPreferences preferences; - - public SupportedValidator(VersionValidationPreferences preferences) { - this.preferences = preferences; + public SupportedOssValidator(DiagnosticSeverityProvider diagnosticSeverityProvider) { + super(diagnosticSeverityProvider); } @Override - public VersionValidation getValidation(ResolvedSpringProject springProject, Generation generation, - Version version) throws Exception { + public Diagnostic validate(ResolvedSpringProject springProject, IJavaProject javaProject, + Generation javaProjectGen, Version javaProjectVersion) throws Exception { - if (VersionValidationUtils.isCommercialValid(generation) && VersionValidationUtils.isOssValid(generation)) { - DiagnosticSeverity severity = preferences.getSupportedPreference().getSeverity(); - - StringBuffer message = new StringBuffer(); - - message.append("OSS support ends on: "); - message.append(generation.getOssSupportEndDate()); - message.append('\n'); - message.append("Commercial supports ends on: "); - message.append(generation.getCommercialSupportEndDate()); - - Version toUpdate = VersionValidationUtils.getLatestSupportedRelease(springProject, version); - return new VersionValidation(toUpdate, severity, message.toString()); - } - return null; - } - - @Override - public boolean isEnabled() { - return preferences.getSupportedPreference().isEnabled(); - } - } - - private static class UnsupportedValidator implements VersionValidator { - - private final VersionValidationPreferences preferences; - - public UnsupportedValidator(VersionValidationPreferences preferences) { - this.preferences = preferences; - } - - @Override - public VersionValidation getValidation(ResolvedSpringProject springProject, Generation generation, - Version version) throws Exception { - - if (!VersionValidationUtils.isCommercialValid(generation) - && !VersionValidationUtils.isOssValid(generation)) { - DiagnosticSeverity severity = preferences.getUnsupportedPreference().getSeverity(); - StringBuffer message = new StringBuffer(); - - message.append("Unsupported OSS. Support ended on: "); - message.append(generation.getOssSupportEndDate()); - message.append('\n'); - message.append("Unsupported Commercial. Support ended on: "); - message.append(generation.getCommercialSupportEndDate()); - - return new VersionValidation( - toUpdateForUnsupported(springProject, version), severity, message.toString()); - } - return null; - } - - @Override - public boolean isEnabled() { - return preferences.getUnsupportedPreference().isEnabled(); - } - } - - private static class UnsupportedOssValidator implements VersionValidator { - - private final VersionValidationPreferences preferences; - - public UnsupportedOssValidator(VersionValidationPreferences preferences) { - this.preferences = preferences; - } - - @Override - public VersionValidation getValidation(ResolvedSpringProject springProject, Generation generation, - Version version) throws Exception { - if (!VersionValidationUtils.isOssValid(generation) - && VersionValidationUtils.isCommercialValid(generation)) { - - DiagnosticSeverity severity = preferences.getUnsupportedOssPreference().getSeverity(); - - StringBuffer message = new StringBuffer(); - message.append("Unsupported OSS. Support ended on: "); - message.append(generation.getOssSupportEndDate()); - message.append('\n'); - message.append("Commercial supports ends on: "); - message.append(generation.getCommercialSupportEndDate()); - return new VersionValidation(toUpdateForUnsupported(springProject, version), severity, message.toString()); - - } - return null; - } - - @Override - public boolean isEnabled() { - return preferences.getUnsupportedOssPreference().isEnabled(); - } - } - - private static class UnsupportedCommercialValidator implements VersionValidator { - - private final VersionValidationPreferences preferences; - - public UnsupportedCommercialValidator(VersionValidationPreferences preferences) { - this.preferences = preferences; - } - - @Override - public VersionValidation getValidation(ResolvedSpringProject springProject, Generation generation, - Version version) throws Exception { - if (!VersionValidationUtils.isCommercialValid(generation) - && VersionValidationUtils.isOssValid(generation)) { - - DiagnosticSeverity severity = preferences.getUnsupportedCommercialPreference().getSeverity(); + if (VersionValidationUtils.isOssValid(javaProjectGen)) { + VersionValidationProblemType problemType = VersionValidationProblemType.SUPPORTED_OSS_VERSION; StringBuffer message = new StringBuffer(); message.append("OSS support ends on: "); - message.append(generation.getOssSupportEndDate()); - message.append('\n'); - message.append("Unsupported Commercial. Support ended on: "); - message.append(generation.getCommercialSupportEndDate()); - - return new VersionValidation(toUpdateForUnsupported(springProject, version), severity, message.toString()); + message.append(javaProjectGen.getOssSupportEndDate()); + + return createDiagnostic(problemType, message.toString()); } return null; } + } + + private static class SupportedCommercialValidator extends AbstractDiagnosticValidator { + + public SupportedCommercialValidator(DiagnosticSeverityProvider diagnosticSeverityProvider) { + super(diagnosticSeverityProvider); + } @Override - public boolean isEnabled() { - return preferences.getUnsupportedCommercialPreference().isEnabled(); + public Diagnostic validate(ResolvedSpringProject springProject, IJavaProject javaProject, + Generation javaProjectGen, Version javaProjectVersion) throws Exception { + + if (VersionValidationUtils.isCommercialValid(javaProjectGen)) { + + VersionValidationProblemType problemType = VersionValidationProblemType.SUPPORTED_COMMERCIAL_VERSION; + + StringBuffer message = new StringBuffer(); + message.append("Commercial support ends on: "); + message.append(javaProjectGen.getCommercialSupportEndDate()); + + return createDiagnostic(problemType, message.toString()); + } + return null; } } - private static Version toUpdateForUnsupported(ResolvedSpringProject springProject, Version version) - throws Exception { - Version toUpdate = VersionValidationUtils.getLatestSupportedInSameMajor(springProject, version); - if (toUpdate == null) { - toUpdate = VersionValidationUtils.getLatestSupportedRelease(springProject, version); + private static class UnsupportedOssValidator extends AbstractDiagnosticValidator { + + public UnsupportedOssValidator(DiagnosticSeverityProvider diagnosticSeverityProvider) { + super(diagnosticSeverityProvider); + } + + @Override + public Diagnostic validate(ResolvedSpringProject springProject, IJavaProject javaProject, + Generation javaProjectGen, Version javaProjectVersion) throws Exception { + if (!VersionValidationUtils.isOssValid(javaProjectGen)) { + + VersionValidationProblemType problemType = VersionValidationProblemType.UNSUPPORTED_OSS_VERSION; + + StringBuffer message = new StringBuffer(); + message.append("Unsupported OSS. Support ended on: "); + message.append(javaProjectGen.getOssSupportEndDate()); + + return createDiagnostic(problemType, message.toString()); + } + return null; + } + } + + private static class UnsupportedCommercialValidator extends AbstractDiagnosticValidator { + + public UnsupportedCommercialValidator(DiagnosticSeverityProvider diagnosticSeverityProvider) { + super(diagnosticSeverityProvider); + } + + @Override + public Diagnostic validate(ResolvedSpringProject springProject, IJavaProject javaProject, + Generation javaProjectGen, Version javaProjectVersion) throws Exception { + if (!VersionValidationUtils.isCommercialValid(javaProjectGen)) { + + VersionValidationProblemType problemType = VersionValidationProblemType.UNSUPPORTED_COMMERCIAL_VERSION; + + StringBuffer message = new StringBuffer(); + message.append("Unsupported Commercial. Support ended on: "); + message.append(javaProjectGen.getCommercialSupportEndDate()); + + return createDiagnostic(problemType, message.toString()); + } + return null; + } + } + + private static class UpdateLatestMajorVersion extends AbstractDiagnosticValidator { + + public UpdateLatestMajorVersion(DiagnosticSeverityProvider diagnosticSeverityProvider) { + super(diagnosticSeverityProvider); + } + + @Override + public Diagnostic validate(ResolvedSpringProject springProject, IJavaProject javaProject, + Generation javaProjectGen, Version javaProjectVersion) throws Exception { + Version latest = VersionValidationUtils.getLatestSupportedInSameMajor(springProject, javaProjectVersion); + if (latest != null) { + VersionValidationProblemType problemType = VersionValidationProblemType.UPDATE_LATEST_MAJOR_VERSION; + + StringBuffer message = new StringBuffer(); + message.append("Newer Major Boot Version Available: "); + message.append(latest.toString()); + + CodeAction ca = new CodeAction(); + ca.setKind(CodeActionKind.QuickFix); + ca.setTitle("Upgrade To Target Version"); + String commandId = "sts/upgrade/spring-boot"; + ca.setCommand(new Command("Upgrade To Target Version", commandId, + ImmutableList.of(javaProject.getLocationUri().toString(), latest.toString()))); + + + return createDiagnostic(ca, problemType, message.toString()); + } + return null; } - return toUpdate; } - } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/SpringProjectDiagnostic.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/preferences/VersionValidationPreferences.java similarity index 60% rename from headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/SpringProjectDiagnostic.java rename to headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/preferences/VersionValidationPreferences.java index 64ca3e908..ef6f26af8 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/SpringProjectDiagnostic.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/preferences/VersionValidationPreferences.java @@ -8,27 +8,14 @@ * Contributors: * VMware, Inc. - initial API and implementation *******************************************************************************/ -package org.springframework.ide.vscode.boot.validation.generations; +package org.springframework.ide.vscode.boot.validation.generations.preferences; -import java.net.URI; +// TODO: integrate with actual LS preferences +public class VersionValidationPreferences { -import org.eclipse.lsp4j.Diagnostic; + private static final String DEFAULT_SPRING_PROJECT_URL = "https://spring.io/api/projects"; -public class SpringProjectDiagnostic { - - private final Diagnostic diagnostic; - private final URI uri; - - public SpringProjectDiagnostic(Diagnostic diagnostic, URI uri) { - this.diagnostic = diagnostic; - this.uri = uri; - } - - public Diagnostic getDiagnostic() { - return diagnostic; - } - - public URI getUri() { - return uri; + public String getSpringProjectsUrl() { + return DEFAULT_SPRING_PROJECT_URL; } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/preferences/VersionValidationProblemType.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/preferences/VersionValidationProblemType.java new file mode 100644 index 000000000..2b15ceebe --- /dev/null +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/preferences/VersionValidationProblemType.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * 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.validation.generations.preferences; + +import static org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity.HINT; +import static org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity.ERROR; + +import org.springframework.ide.vscode.boot.common.SpringProblemCategories; +import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemCategory; +import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity; +import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType; + +public enum VersionValidationProblemType implements ProblemType { + + SUPPORTED_OSS_VERSION(HINT, "Supported OSS Boot Version", "Supported OSS Boot Version"), + + UNSUPPORTED_OSS_VERSION(ERROR, "Unsupported OSS Version", "Unsupported OSS Version"), + + UNSUPPORTED_COMMERCIAL_VERSION(ERROR, "Unsupported Commercial Version", "Unsupported Commercial Version"), + + SUPPORTED_COMMERCIAL_VERSION(HINT, "Supported Commercial Version", "Supported Commercial Version"), + + UPDATE_LATEST_MAJOR_VERSION(HINT, "Update to Latest Boot Version", "Update to Latest Boot Version"); + + private final ProblemSeverity defaultSeverity; + private String description; + private String label; + + private VersionValidationProblemType(ProblemSeverity defaultSeverity, String description, String label) { + this.description = description; + this.defaultSeverity = defaultSeverity; + this.label = label; + } + + @Override + public ProblemSeverity getDefaultSeverity() { + return defaultSeverity; + } + + public String getLabel() { + if (label==null) { + label = createDefaultLabel(); + } + return label; + } + + @Override + public String getDescription() { + return description; + } + + private String createDefaultLabel() { + String label = this.toString().substring(5).toLowerCase().replace('_', ' '); + return Character.toUpperCase(label.charAt(0)) + label.substring(1); + } + + @Override + public String getCode() { + return name(); + } + + @Override + public ProblemCategory getCategory() { + return SpringProblemCategories.VERSION_VALIDATION; + } + +} diff --git a/headless-services/spring-boot-language-server/src/main/resources/problem-types.json b/headless-services/spring-boot-language-server/src/main/resources/problem-types.json index 8a95f1c89..c28f5da61 100644 --- a/headless-services/spring-boot-language-server/src/main/resources/problem-types.json +++ b/headless-services/spring-boot-language-server/src/main/resources/problem-types.json @@ -288,5 +288,51 @@ "defaultSeverity": "ERROR" } ] + }, + { + "id": "version-validation", + "label": "Spring Boot Version Validation", + "toggle": { + "label": "Enablement", + "values": [ + "OFF", + "ON" + ], + "preferenceKey": "boot-java.validation.java.version-validation", + "defaultValue": "ON" + }, + "order": 7, + "problemTypes": [ + { + "code": "SUPPORTED_OSS_VERSION", + "label": "Supported OSS Boot Version", + "description": "Supported OSS Boot Version", + "defaultSeverity": "HINT" + }, + { + "code": "UNSUPPORTED_OSS_VERSION", + "label": "Unsupported OSS Version", + "description": "Unsupported OSS Version", + "defaultSeverity": "ERROR" + }, + { + "code": "UNSUPPORTED_COMMERCIAL_VERSION", + "label": "Unsupported Commercial Version", + "description": "Unsupported Commercial Version", + "defaultSeverity": "ERROR" + }, + { + "code": "SUPPORTED_COMMERCIAL_VERSION", + "label": "Supported Commercial Version", + "description": "Supported Commercial Version", + "defaultSeverity": "HINT" + }, + { + "code": "UPDATE_LATEST_MAJOR_VERSION", + "label": "Update to Latest Boot Version", + "description": "Update to Latest Boot Version", + "defaultSeverity": "HINT" + } + ] } ] \ No newline at end of file diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/test/ProblemTypesMetadataTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/test/ProblemTypesMetadataTest.java index 9afa2fb76..e1e0a27ad 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/test/ProblemTypesMetadataTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/test/ProblemTypesMetadataTest.java @@ -16,6 +16,7 @@ import org.springframework.ide.vscode.boot.java.SpringAotJavaProblemType; import org.springframework.ide.vscode.boot.java.Boot3JavaProblemType; import org.springframework.ide.vscode.boot.java.SpelProblemType; import org.springframework.ide.vscode.boot.properties.reconcile.ApplicationPropertiesProblemType; +import org.springframework.ide.vscode.boot.validation.generations.preferences.VersionValidationProblemType; import org.springframework.ide.vscode.boot.yaml.reconcile.ApplicationYamlProblemType; public class ProblemTypesMetadataTest { @@ -32,6 +33,7 @@ public class ProblemTypesMetadataTest { reader.validate("boot3", Boot3JavaProblemType.values()); reader.validate("spring-aot", SpringAotJavaProblemType.values()); reader.validate("spel", SpelProblemType.values()); + reader.validate("version-validation", VersionValidationProblemType.values()); } } diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/test/ProblemTypesToJson.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/test/ProblemTypesToJson.java index 012638594..4827a1b43 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/test/ProblemTypesToJson.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/test/ProblemTypesToJson.java @@ -27,10 +27,11 @@ import java.util.stream.Stream; import org.apache.commons.io.FileUtils; import org.springframework.ide.vscode.boot.java.Boot2JavaProblemType; -import org.springframework.ide.vscode.boot.java.SpringAotJavaProblemType; import org.springframework.ide.vscode.boot.java.Boot3JavaProblemType; import org.springframework.ide.vscode.boot.java.SpelProblemType; +import org.springframework.ide.vscode.boot.java.SpringAotJavaProblemType; import org.springframework.ide.vscode.boot.properties.reconcile.ApplicationPropertiesProblemType; +import org.springframework.ide.vscode.boot.validation.generations.preferences.VersionValidationProblemType; import org.springframework.ide.vscode.boot.yaml.reconcile.ApplicationYamlProblemType; import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemCategory; import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemCategory.Toggle; @@ -175,6 +176,7 @@ public class ProblemTypesToJson { writer.collectProblemTypeData(ApplicationPropertiesProblemType.values()); writer.collectProblemTypeData(Boot3JavaProblemType.values()); writer.collectProblemTypeData(SpringAotJavaProblemType.values()); + writer.collectProblemTypeData(VersionValidationProblemType.values()); Collections.sort(writer.problemCategories); diff --git a/vscode-extensions/vscode-spring-boot/package.json b/vscode-extensions/vscode-spring-boot/package.json index 74d273193..d06eb6e95 100644 --- a/vscode-extensions/vscode-spring-boot/package.json +++ b/vscode-extensions/vscode-spring-boot/package.json @@ -785,6 +785,82 @@ ] } } + }, + { + "id": "version-validation", + "title": "Spring Boot Version Validation", + "order": 407, + "properties": { + "boot-java.validation.java.version-validation": { + "type": "string", + "default": "ON", + "description": "Enablement", + "enum": [ + "OFF", + "ON" + ] + }, + "spring-boot.ls.problem.version-validation.SUPPORTED_OSS_VERSION": { + "type": "string", + "default": "HINT", + "description": "Supported OSS Boot Version", + "enum": [ + "IGNORE", + "INFO", + "WARNING", + "HINT", + "ERROR" + ] + }, + "spring-boot.ls.problem.version-validation.UNSUPPORTED_OSS_VERSION": { + "type": "string", + "default": "ERROR", + "description": "Unsupported OSS Version", + "enum": [ + "IGNORE", + "INFO", + "WARNING", + "HINT", + "ERROR" + ] + }, + "spring-boot.ls.problem.version-validation.UNSUPPORTED_COMMERCIAL_VERSION": { + "type": "string", + "default": "ERROR", + "description": "Unsupported Commercial Version", + "enum": [ + "IGNORE", + "INFO", + "WARNING", + "HINT", + "ERROR" + ] + }, + "spring-boot.ls.problem.version-validation.SUPPORTED_COMMERCIAL_VERSION": { + "type": "string", + "default": "HINT", + "description": "Supported Commercial Version", + "enum": [ + "IGNORE", + "INFO", + "WARNING", + "HINT", + "ERROR" + ] + }, + "spring-boot.ls.problem.version-validation.UPDATE_LATEST_MAJOR_VERSION": { + "type": "string", + "default": "HINT", + "description": "Update to Latest Boot Version", + "enum": [ + "IGNORE", + "INFO", + "WARNING", + "HINT", + "ERROR" + ] + } + } } ], "grammars": [