From a1e98d7026ef5af2cb834b8e60ce5546e5080f51 Mon Sep 17 00:00:00 2001 From: aboyko Date: Thu, 23 Feb 2023 17:50:42 -0500 Subject: [PATCH] Missing @Configuration --- .../boot/java/Boot2JavaProblemType.java | 4 +- .../rewrite/BootCodeActionRepository.java | 4 +- ...ConfigurationIfBeansPresentCodeAction.java | 95 +++++++++++++++++++ .../HttpSecurityLamdaDslCodeAction.java | 6 +- ...ServerHttpSecurityLambdaDslCodeAction.java | 6 +- .../src/main/resources/problem-types.json | 6 ++ .../vscode-spring-boot/package.json | 12 +++ 7 files changed, 123 insertions(+), 10 deletions(-) create mode 100644 headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/reconcile/AddConfigurationIfBeansPresentCodeAction.java diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/Boot2JavaProblemType.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/Boot2JavaProblemType.java index da650557f..ea7771c49 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/Boot2JavaProblemType.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/Boot2JavaProblemType.java @@ -34,7 +34,9 @@ public enum Boot2JavaProblemType implements ProblemType { JAVA_REPOSITORY(WARNING, "Unnecessary `@Repository`", "Unnecessary `@Repository`"), - JAVA_LAMBDA_DSL(INFO, "Consider switching to Lambda DSL syntax", "Switch to Lambda DSL syntax"); + JAVA_LAMBDA_DSL(INFO, "Consider switching to Lambda DSL syntax", "Switch to Lambda DSL syntax"), + + MISSING_CONFIGURATION_ANNOTATION(WARNING, "Class likely missing '@Configuration' annotation, i.e. has Bean methods but no '@Configuration' annotation", "Missing '@Configuration'"); private final ProblemSeverity defaultSeverity; private String description; diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/BootCodeActionRepository.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/BootCodeActionRepository.java index 506564f0a..30e449b78 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/BootCodeActionRepository.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/BootCodeActionRepository.java @@ -12,6 +12,7 @@ package org.springframework.ide.vscode.boot.java.rewrite; import java.util.List; +import org.springframework.ide.vscode.boot.java.rewrite.reconcile.AddConfigurationIfBeansPresentCodeAction; import org.springframework.ide.vscode.boot.java.rewrite.reconcile.AutowiredFieldIntoConstructorParameterCodeAction; import org.springframework.ide.vscode.boot.java.rewrite.reconcile.BeanMethodNotPublicProblem; import org.springframework.ide.vscode.boot.java.rewrite.reconcile.BeanPostProcessingIgnoreInAotProblem; @@ -43,7 +44,8 @@ public class BootCodeActionRepository extends CodeActionRepository { new AutowiredFieldIntoConstructorParameterCodeAction(), new NoRepoAnnotationProblem(), new HttpSecurityLamdaDslCodeAction(), - new ServerHttpSecurityLambdaDslCodeAction() + new ServerHttpSecurityLambdaDslCodeAction(), + new AddConfigurationIfBeansPresentCodeAction() ); } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/reconcile/AddConfigurationIfBeansPresentCodeAction.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/reconcile/AddConfigurationIfBeansPresentCodeAction.java new file mode 100644 index 000000000..5254e0816 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/reconcile/AddConfigurationIfBeansPresentCodeAction.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * 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.boot.java.rewrite.reconcile; + +import java.util.List; + +import org.openrewrite.ExecutionContext; +import org.openrewrite.SourceFile; +import org.openrewrite.Tree; +import org.openrewrite.java.JavaVisitor; +import org.openrewrite.java.spring.boot2.AddConfigurationAnnotationIfBeansPresent; +import org.openrewrite.java.tree.J.ClassDeclaration; +import org.openrewrite.java.tree.J.MethodDeclaration; +import org.openrewrite.java.tree.J.VariableDeclarations; +import org.springframework.context.ApplicationContext; +import org.springframework.ide.vscode.boot.java.Boot2JavaProblemType; +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 org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType; +import org.springframework.ide.vscode.commons.rewrite.config.RecipeCodeActionDescriptor; +import org.springframework.ide.vscode.commons.rewrite.config.RecipeScope; +import org.springframework.ide.vscode.commons.rewrite.java.FixAssistMarker; +import org.springframework.ide.vscode.commons.rewrite.java.FixDescriptor; +import org.springframework.ide.vscode.commons.rewrite.java.JavaMarkerVisitor; + +public class AddConfigurationIfBeansPresentCodeAction implements RecipeCodeActionDescriptor { + + private static final String ID = "org.openrewrite.java.spring.boot2.AddConfigurationAnnotationIfBeansPresent"; + + private static final String PROBLEM_LABEL = "'@Configuration' is missing on a class defining Spring Beans"; + + private static final String FIX_LABEL = "Add missing '@Configuration' annotations over classes"; + + @Override + public JavaVisitor getMarkerVisitor(ApplicationContext applicationContext) { + return new JavaMarkerVisitor() { + + @Override + public MethodDeclaration visitMethodDeclaration(MethodDeclaration method, ExecutionContext p) { + return method; + } + + @Override + public VariableDeclarations visitVariableDeclarations(VariableDeclarations multiVariable, + ExecutionContext p) { + return multiVariable; + } + + @Override + public ClassDeclaration visitClassDeclaration(ClassDeclaration classDecl, ExecutionContext p) { + ClassDeclaration c = super.visitClassDeclaration(classDecl, p); + if (AddConfigurationAnnotationIfBeansPresent.isApplicableClass(classDecl, getCursor())) { + String uri = getCursor().firstEnclosing(SourceFile.class).getSourcePath().toUri().toASCIIString(); + FixAssistMarker marker = new FixAssistMarker(Tree.randomId(), ID).withLabel(PROBLEM_LABEL) + .withFixes( + new FixDescriptor(ID, List.of(uri), + RecipeCodeActionDescriptor.buildLabel(FIX_LABEL, RecipeScope.FILE)) + .withRecipeScope(RecipeScope.FILE), + new FixDescriptor(ID, List.of(uri), + RecipeCodeActionDescriptor.buildLabel(FIX_LABEL, RecipeScope.PROJECT)) + .withRecipeScope(RecipeScope.PROJECT)); + c = c.withName(c.getName().withMarkers(c.getName().getMarkers().add(marker))); + } + return c; + } + + }; + } + + @Override + public String getId() { + return ID; + } + + @Override + public ProblemType getProblemType() { + return Boot2JavaProblemType.MISSING_CONFIGURATION_ANNOTATION; + } + + @Override + public boolean isApplicable(IJavaProject project) { + Version version = SpringProjectUtil.getDependencyVersion(project, "spring-context"); + return version != null && version.compareTo(new Version(3, 0, 0, null)) >= 0; + } + +} diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/reconcile/HttpSecurityLamdaDslCodeAction.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/reconcile/HttpSecurityLamdaDslCodeAction.java index a9923966e..c1ffd619e 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/reconcile/HttpSecurityLamdaDslCodeAction.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/reconcile/HttpSecurityLamdaDslCodeAction.java @@ -33,11 +33,9 @@ import org.springframework.ide.vscode.commons.rewrite.java.JavaMarkerVisitor; public class HttpSecurityLamdaDslCodeAction implements RecipeCodeActionDescriptor { - private static final Version SECURITY_VERSION = new Version(5, 2, 0, null); - private static final String PROBLEM_LABEL = "Consider switching to 'HttpSecurity' Lambda DSL syntax"; - private static final String FIX_LABEL = "SWitch to 'HttpSecurity` Lambda DSL syntax"; + private static final String FIX_LABEL = "Switch to 'HttpSecurity` Lambda DSL syntax"; private HttpSecurityLambdaDsl recipe = new HttpSecurityLambdaDsl(); @@ -74,7 +72,7 @@ public class HttpSecurityLamdaDslCodeAction implements RecipeCodeActionDescripto @Override public boolean isApplicable(IJavaProject project) { Version version = SpringProjectUtil.getDependencyVersion(project, "spring-security-config"); - return version != null && version.compareTo(SECURITY_VERSION) >= 0; + return version != null && version.compareTo(new Version(5, 2, 0, null)) >= 0; } @Override diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/reconcile/ServerHttpSecurityLambdaDslCodeAction.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/reconcile/ServerHttpSecurityLambdaDslCodeAction.java index f9e2bf387..6bd6a92d0 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/reconcile/ServerHttpSecurityLambdaDslCodeAction.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/reconcile/ServerHttpSecurityLambdaDslCodeAction.java @@ -33,11 +33,9 @@ import org.springframework.ide.vscode.commons.rewrite.java.JavaMarkerVisitor; public class ServerHttpSecurityLambdaDslCodeAction implements RecipeCodeActionDescriptor { - private static final Version SECURITY_VERSION = new Version(5, 2, 0, null); - private static final String PROBLEM_LABEL = "Consider switching to 'ServerHttpSecurity' Lambda DSL syntax"; - private static final String FIX_LABEL = "SWitch to 'ServerHttpSecurity` Lambda DSL syntax"; + private static final String FIX_LABEL = "Switch to 'ServerHttpSecurity` Lambda DSL syntax"; private ServerHttpSecurityLambdaDsl recipe = new ServerHttpSecurityLambdaDsl(); @@ -73,7 +71,7 @@ public class ServerHttpSecurityLambdaDslCodeAction implements RecipeCodeActionDe @Override public boolean isApplicable(IJavaProject project) { Version version = SpringProjectUtil.getDependencyVersion(project, "spring-security-config"); - return version != null && version.compareTo(SECURITY_VERSION) >= 0; + return version != null && version.compareTo(new Version(5, 2, 0, null)) >= 0; } @Override 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 4876aa21f..2b4d99cb9 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 @@ -55,6 +55,12 @@ "label": "Switch to Lambda DSL syntax", "description": "Consider switching to Lambda DSL syntax", "defaultSeverity": "INFO" + }, + { + "code": "MISSING_CONFIGURATION_ANNOTATION", + "label": "Missing '@Configuration'", + "description": "Class likely missing '@Configuration' annotation, i.e. has Bean methods but no '@Configuration' annotation", + "defaultSeverity": "WARNING" } ] }, diff --git a/vscode-extensions/vscode-spring-boot/package.json b/vscode-extensions/vscode-spring-boot/package.json index c9a0e59b5..da5c458ee 100644 --- a/vscode-extensions/vscode-spring-boot/package.json +++ b/vscode-extensions/vscode-spring-boot/package.json @@ -414,6 +414,18 @@ "HINT", "ERROR" ] + }, + "spring-boot.ls.problem.boot2.MISSING_CONFIGURATION_ANNOTATION": { + "type": "string", + "default": "WARNING", + "description": "Class likely missing '@Configuration' annotation, i.e. has Bean methods but no '@Configuration' annotation", + "enum": [ + "IGNORE", + "INFO", + "WARNING", + "HINT", + "ERROR" + ] } } },