From 0130203c8feb483e1f5aedd9e538d6fde43f8bc6 Mon Sep 17 00:00:00 2001 From: aboyko Date: Fri, 7 Oct 2022 13:38:44 -0400 Subject: [PATCH] Mark types not supported as of Boot 3 --- .../commons/rewrite/java/FixAssistMarker.java | 13 +- .../boot/java/Boot3JavaProblemType.java | 5 +- .../rewrite/BootCodeActionRepository.java | 4 +- .../boot/java/rewrite/RewriteReconciler.java | 2 +- .../Boot3NotSupportedTypeProblem.java | 129 ++++++++++++++++++ .../src/main/resources/problem-types.json | 6 + .../vscode-spring-boot/package.json | 12 ++ 7 files changed, 167 insertions(+), 4 deletions(-) create mode 100644 headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/reconcile/Boot3NotSupportedTypeProblem.java diff --git a/headless-services/commons/commons-rewrite/src/main/java/org/springframework/ide/vscode/commons/rewrite/java/FixAssistMarker.java b/headless-services/commons/commons-rewrite/src/main/java/org/springframework/ide/vscode/commons/rewrite/java/FixAssistMarker.java index cab32e755..2f6212b43 100644 --- a/headless-services/commons/commons-rewrite/src/main/java/org/springframework/ide/vscode/commons/rewrite/java/FixAssistMarker.java +++ b/headless-services/commons/commons-rewrite/src/main/java/org/springframework/ide/vscode/commons/rewrite/java/FixAssistMarker.java @@ -24,7 +24,9 @@ public class FixAssistMarker implements Marker { private String descriptorId; - private List fixes = new ArrayList<>();; + private List fixes = new ArrayList<>(); + + private String label; public FixAssistMarker(UUID id, String descriptorId) { super(); @@ -61,6 +63,15 @@ public class FixAssistMarker implements Marker { public List getFixes() { return fixes; } + + public FixAssistMarker withLabel(String label) { + this.label = label; + return this; + } + + public String getLabel() { + return label; + } @Override public int hashCode() { diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/Boot3JavaProblemType.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/Boot3JavaProblemType.java index 4a992e46f..df35790d6 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/Boot3JavaProblemType.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/Boot3JavaProblemType.java @@ -10,6 +10,7 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.java; +import static org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity.ERROR; import static org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity.WARNING; import org.springframework.ide.vscode.boot.common.SpringProblemCategories; @@ -27,7 +28,9 @@ public enum Boot3JavaProblemType implements ProblemType { JAVA_BEAN_POST_PROCESSOR_IGNORED_IN_AOT(WARNING, "'BeanPostProcessor' behaviour is ignored in Spring 6 AOT", "'BeanPostProcessor' behaviour is ignored in AOT"), - JAVA_BEAN_NOT_REGISTERED_IN_AOT(WARNING, "Not registered as Bean", "Not registered as a Bean"); + JAVA_BEAN_NOT_REGISTERED_IN_AOT(WARNING, "Not registered as Bean", "Not registered as a Bean"), + + JAVA_TYPE_NOT_SUPPORTED(ERROR, "Type no supported as of Spring Boot 3", "Type not supported as of Spring Boot 3"); 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 828ba25b6..397f90f2a 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 @@ -16,6 +16,7 @@ import org.springframework.ide.vscode.boot.java.rewrite.codeaction.AutowiredFiel import org.springframework.ide.vscode.boot.java.rewrite.codeaction.NoRequestMappingAnnotationCodeAction; import org.springframework.ide.vscode.boot.java.rewrite.reconcile.BeanMethodNotPublicProblem; import org.springframework.ide.vscode.boot.java.rewrite.reconcile.BeanPostProcessingIgnoreInAotProblem; +import org.springframework.ide.vscode.boot.java.rewrite.reconcile.Boot3NotSupportedTypeProblem; import org.springframework.ide.vscode.boot.java.rewrite.reconcile.NoAutowiredOnConstructorProblem; import org.springframework.ide.vscode.boot.java.rewrite.reconcile.NotRegisteredBeansProblem; import org.springframework.ide.vscode.boot.java.rewrite.reconcile.PreciseBeanTypeProblem; @@ -42,7 +43,8 @@ public class BootCodeActionRepository extends CodeActionRepository { new UnnecessarySpringExtensionProblem(), new PreciseBeanTypeProblem(), new BeanPostProcessingIgnoreInAotProblem(), - new NotRegisteredBeansProblem() + new NotRegisteredBeansProblem(), + new Boot3NotSupportedTypeProblem() ); } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/RewriteReconciler.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/RewriteReconciler.java index a7a5d5949..4c25c3f03 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/RewriteReconciler.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/RewriteReconciler.java @@ -112,7 +112,7 @@ public class RewriteReconciler implements JavaReconciler { private ReconcileProblemImpl createProblem(IDocument doc, RecipeSpringJavaProblemDescriptor recipeFixDescriptor, FixAssistMarker m, Range range) { ProblemType problemType = recipeFixDescriptor.getProblemType(); - ReconcileProblemImpl problem = new ReconcileProblemImpl(problemType, problemType.getLabel(), range.getStart().getOffset(), range.getEnd().getOffset() - range.getStart().getOffset()); + ReconcileProblemImpl problem = new ReconcileProblemImpl(problemType, m.getLabel() == null ? problemType.getLabel() : m.getLabel(), range.getStart().getOffset(), range.getEnd().getOffset() - range.getStart().getOffset()); QuickfixType quickfixType = quickfixRegistry.getQuickfixType(RewriteRefactorings.REWRITE_RECIPE_QUICKFIX); if (quickfixType != null) { for (FixDescriptor f : m.getFixes()) { diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/reconcile/Boot3NotSupportedTypeProblem.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/reconcile/Boot3NotSupportedTypeProblem.java new file mode 100644 index 000000000..17673ed9e --- /dev/null +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/reconcile/Boot3NotSupportedTypeProblem.java @@ -0,0 +1,129 @@ +/******************************************************************************* + * 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.java.rewrite.reconcile; + +import static org.springframework.ide.vscode.commons.java.SpringProjectUtil.springBootVersionGreaterOrEqual; + +import java.util.List; + +import org.openrewrite.ExecutionContext; +import org.openrewrite.Tree; +import org.openrewrite.java.JavaIsoVisitor; +import org.openrewrite.java.JavaVisitor; +import org.openrewrite.java.tree.J; +import org.openrewrite.java.tree.J.MethodInvocation; +import org.openrewrite.java.tree.JavaType; +import org.openrewrite.java.tree.JavaType.FullyQualified; +import org.openrewrite.java.tree.JavaType.Method; +import org.openrewrite.java.tree.NameTree; +import org.openrewrite.java.tree.TypeUtils; +import org.springframework.context.ApplicationContext; +import org.springframework.ide.vscode.boot.java.Boot3JavaProblemType; +import org.springframework.ide.vscode.commons.java.IJavaProject; +import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType; +import org.springframework.ide.vscode.commons.rewrite.config.RecipeSpringJavaProblemDescriptor; +import org.springframework.ide.vscode.commons.rewrite.java.FixAssistMarker; + +public class Boot3NotSupportedTypeProblem implements RecipeSpringJavaProblemDescriptor { + + private static final List TYPE_FQNAMES = List.of( + "org.springframework.web.multipart.commons.CommonsMultipartResolver", + "java.lang.SecurityManager", + "java.security.AccessControlException" + ); + + @Override + public JavaVisitor getMarkerVisitor(ApplicationContext applicationContext) { + return new JavaIsoVisitor<>() { + @Override + public J.Identifier visitIdentifier(J.Identifier ident, ExecutionContext executionContext) { + if (ident.getType() != null && + getCursor().firstEnclosing(J.Import.class) == null && + getCursor().firstEnclosing(J.FieldAccess.class) == null && + !(getCursor().getParentOrThrow().getValue() instanceof J.ParameterizedType)) { + JavaType.FullyQualified type = TypeUtils.asFullyQualified(ident.getType()); + for (String fqName : TYPE_FQNAMES) { + if (typeMatches(true, fqName, type) && + ident.getSimpleName().equals(type.getClassName())) { + return ident.withMarkers(ident.getMarkers().add(new FixAssistMarker(Tree.randomId(), getId()).withLabel(createLabel(fqName)))); + } + } + } + return super.visitIdentifier(ident, executionContext); + } + + @Override + public N visitTypeName(N name, ExecutionContext ctx) { + N n = super.visitTypeName(name, ctx); + JavaType.FullyQualified type = TypeUtils.asFullyQualified(n.getType()); + for (String fqName : TYPE_FQNAMES) { + if (typeMatches(true, fqName, type) && + getCursor().firstEnclosing(J.Import.class) == null) { + return n.withMarkers(n.getMarkers().add(new FixAssistMarker(Tree.randomId(), getId()).withLabel(createLabel(fqName)))); + } + } + return n; + } + + @Override + public J.FieldAccess visitFieldAccess(J.FieldAccess fieldAccess, ExecutionContext ctx) { + J.FieldAccess fa = (J.FieldAccess) super.visitFieldAccess(fieldAccess, ctx); + JavaType.FullyQualified type = TypeUtils.asFullyQualified(fa.getTarget().getType()); + for (String fqName : TYPE_FQNAMES) { + if (typeMatches(true, fqName, type) && + fa.getName().getSimpleName().equals("class")) { + return fa.withMarkers(fa.getMarkers().add(new FixAssistMarker(Tree.randomId(), getId()).withLabel(createLabel(fqName)))); + } + } + return fa; + } + + public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) { + MethodInvocation m = super.visitMethodInvocation(method, ctx); + Method methodType = m.getMethodType(); + if (methodType != null) { + FullyQualified fqType = TypeUtils.asFullyQualified(methodType.getReturnType()); + if (fqType != null) { + for (String fqName : TYPE_FQNAMES) { + if (typeMatches(true, fqName, fqType)) { + return m.withMarkers(m.getMarkers().add(new FixAssistMarker(Tree.randomId(), getId()).withLabel(createLabel(fqName)))); + } + } + } + } + return m; + } + }; + } + + private static String createLabel(String type) { + StringBuilder sb = new StringBuilder(); + sb.append("'"); + sb.append(type); + sb.append("' not supported as of Spring Boot 3"); + return sb.toString(); + } + + private static boolean typeMatches(boolean checkAssignability, String fqName, JavaType.FullyQualified test) { + return test != null && (checkAssignability ? test.isAssignableTo(fqName) : fqName.equals(test.getFullyQualifiedName())); + } + + @Override + public boolean isApplicable(IJavaProject project) { + return springBootVersionGreaterOrEqual(3, 0, 0).test(project); + } + + @Override + public ProblemType getProblemType() { + return Boot3JavaProblemType.JAVA_TYPE_NOT_SUPPORTED; + } + +} 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 b065a99a6..00c2091a6 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 @@ -66,6 +66,12 @@ "label": "Not registered as a Bean", "description": "Not registered as Bean", "defaultSeverity": "WARNING" + }, + { + "code": "JAVA_TYPE_NOT_SUPPORTED", + "label": "Type not supported as of Spring Boot 3", + "description": "Type no supported as of Spring Boot 3", + "defaultSeverity": "ERROR" } ] }, diff --git a/vscode-extensions/vscode-spring-boot/package.json b/vscode-extensions/vscode-spring-boot/package.json index 221702b69..e0cb25dd1 100644 --- a/vscode-extensions/vscode-spring-boot/package.json +++ b/vscode-extensions/vscode-spring-boot/package.json @@ -359,6 +359,18 @@ "HINT", "ERROR" ] + }, + "spring-boot.ls.problem.boot3.JAVA_TYPE_NOT_SUPPORTED": { + "type": "string", + "default": "ERROR", + "description": "Type no supported as of Spring Boot 3", + "enum": [ + "IGNORE", + "INFO", + "WARNING", + "HINT", + "ERROR" + ] } } },