refactoring of reconciler design to avoid running through all the ast visitor mechanics for each validation

This commit is contained in:
Martin Lippert
2024-04-26 18:49:33 +02:00
parent b706849f42
commit fc7cbf60fb
22 changed files with 731 additions and 454 deletions

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023 VMware, Inc.
* Copyright (c) 2023, 2024 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
@@ -29,15 +29,23 @@ public abstract class AbstractSecurityLamdaDslReconciler implements JdtAstReconc
private QuickfixRegistry registry;
AbstractSecurityLamdaDslReconciler(QuickfixRegistry registry) {
public AbstractSecurityLamdaDslReconciler(QuickfixRegistry registry) {
this.registry = registry;
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector,
boolean isCompleteAst) throws RequiredCompleteAstException {
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) throws RequiredCompleteAstException {
ASTVisitor visitor = createVisitor(project, docUri, cu, problemCollector, isCompleteAst);
if (visitor != null) {
cu.accept(visitor);
}
}
@Override
public ASTVisitor createVisitor(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) {
if (isCompleteAst) {
cu.accept(new ASTVisitor() {
return new ASTVisitor() {
@Override
public boolean visit(MethodInvocation node) {
@@ -66,28 +74,27 @@ public abstract class AbstractSecurityLamdaDslReconciler implements JdtAstReconc
return true;
}
});
};
} else {
if (ReconcileUtils.isAnyTypeUsed(cu, List.of(getTargetTypeFqName()))) {
throw new RequiredCompleteAstException();
}
else {
return null;
}
}
}
protected abstract String getFixLabel();
protected abstract String getRecipeId();
protected abstract String getProblemLabel();
abstract protected String getTargetTypeFqName();
abstract protected Collection<String> getApplicableMethodNames();
private static MethodInvocation findTopLevelMethodInvocation(MethodInvocation m) {
for (; m.getParent() instanceof MethodInvocation; m = (MethodInvocation) m.getParent()) {}
return m;
}
protected abstract String getFixLabel();
protected abstract String getRecipeId();
protected abstract String getProblemLabel();
abstract protected String getTargetTypeFqName();
abstract protected Collection<String> getApplicableMethodNames();
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023 VMware, Inc.
* Copyright (c) 2023, 2024 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
@@ -48,21 +48,40 @@ import org.springframework.ide.vscode.commons.rewrite.java.FixDescriptor;
public class AddConfigurationIfBeansPresentReconciler implements JdtAstReconciler, ApplicationContextAware {
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";
private QuickfixRegistry quickfixRegistry;
private ApplicationContext applicationContext;
public AddConfigurationIfBeansPresentReconciler(QuickfixRegistry quickfixRegistry) {
this.quickfixRegistry = quickfixRegistry;
}
@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;
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector,
boolean isCompleteAst) {
cu.accept(new ASTVisitor() {
public ProblemType getProblemType() {
return Boot2JavaProblemType.MISSING_CONFIGURATION_ANNOTATION;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) {
ASTVisitor visitor = createVisitor(project, docUri, cu, problemCollector, isCompleteAst);
cu.accept(visitor);
}
@Override
public ASTVisitor createVisitor(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) {
return new ASTVisitor() {
@Override
public boolean visit(TypeDeclaration classDecl) {
@@ -86,7 +105,7 @@ public class AddConfigurationIfBeansPresentReconciler implements JdtAstReconcile
return true;
}
});
};
}
private boolean isApplicableClass(IJavaProject project, CompilationUnit cu, TypeDeclaration classDecl) {
@@ -179,20 +198,4 @@ public class AddConfigurationIfBeansPresentReconciler implements JdtAstReconcile
return false;
}
@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;
}
@Override
public ProblemType getProblemType() {
return Boot2JavaProblemType.MISSING_CONFIGURATION_ANNOTATION;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023 VMware, Inc.
* Copyright (c) 2023, 2024 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
@@ -75,11 +75,27 @@ public class AnnotationNodeReconciler implements JdtAstReconciler {
};
config.addListener(evt -> this.spelExpressionReconciler.setEnabled(config.isSpelExpressionValidationEnabled()));
}
@Override
public boolean isApplicable(IJavaProject project) {
return true;
}
@Override
public ProblemType getProblemType() {
return SpelProblemType.JAVA_SPEL_EXPRESSION_SYNTAX;
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) {
cu.accept(new ASTVisitor() {
ASTVisitor visitor = createVisitor(project, docUri, cu, problemCollector, isCompleteAst);
cu.accept(visitor);
}
@Override
public ASTVisitor createVisitor(IJavaProject project, URI docUri, CompilationUnit cu,
IProblemCollector problemCollector, boolean isCompleteAst) {
return new ASTVisitor() {
@Override
public boolean visit(SingleMemberAnnotation node) {
@@ -111,7 +127,7 @@ public class AnnotationNodeReconciler implements JdtAstReconciler {
return super.visit(node);
}
});
};
}
private void visitAnnotation(IJavaProject project, URI docUri, Annotation node, IProblemCollector problemCollector) {
@@ -123,16 +139,4 @@ public class AnnotationNodeReconciler implements JdtAstReconciler {
}
}
@Override
public boolean isApplicable(IJavaProject project) {
return true;
}
@Override
public ProblemType getProblemType() {
return SpelProblemType.JAVA_SPEL_EXPRESSION_SYNTAX;
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023 VMware, Inc.
* Copyright (c) 2023, 2024 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
@@ -32,17 +32,11 @@ import org.springframework.ide.vscode.commons.rewrite.java.FixDescriptor;
public class AuthorizeHttpRequestsReconciler implements JdtAstReconciler {
private static final String FQN_HTTP_SECURITY = "org.springframework.security.config.annotation.web.builders.HttpSecurity";
private static final String AUTHORIZE_REQUESTS = "authorizeRequests";
private static final String AUTHORIZE_REQUESTS_PROBLEM_LABEL = "HttpSecurity API 'authorizeRequests(...)' is outdated";
private static final String AUTHORIZE_REQUESTS_FIX_LABEL = "Replace with 'authorizeHttpRequests(...)' and related types";
private static final String FQN_INTERCEPTOR_URL_CONFIG = "org.springframework.security.config.annotation.web.configurers.AbstractInterceptUrlConfigurer";
private static final String FQN_EXPR_AUTH_CONFIG = "org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer";
private static final String FQN_EXPR_INTERCEPT_REG = "org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry";
private QuickfixRegistry registry;
@@ -52,10 +46,29 @@ public class AuthorizeHttpRequestsReconciler implements JdtAstReconciler {
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector,
boolean isCompleteAst) throws RequiredCompleteAstException {
public boolean isApplicable(IJavaProject project) {
Version version = SpringProjectUtil.getDependencyVersion(project, "spring-security-config");
return version != null && version.compareTo(new Version(5, 6, 0, null)) >= 0;
}
@Override
public ProblemType getProblemType() {
return Boot2JavaProblemType.HTTP_SECURITY_AUTHORIZE_HTTP_REQUESTS;
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) throws RequiredCompleteAstException {
ASTVisitor visitor = createVisitor(project, docUri, cu, problemCollector, isCompleteAst);
if (visitor != null) {
cu.accept(visitor);
}
}
@Override
public ASTVisitor createVisitor(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) {
if (isCompleteAst) {
cu.accept(new ASTVisitor() {
return new ASTVisitor() {
@Override
public boolean visit(MethodInvocation node) {
@@ -84,7 +97,7 @@ public class AuthorizeHttpRequestsReconciler implements JdtAstReconciler {
return true;
}
});
};
} else {
boolean needsFullAst = ReconcileUtils.isAnyTypeUsed(cu, List.of(
FQN_HTTP_SECURITY,
@@ -92,21 +105,13 @@ public class AuthorizeHttpRequestsReconciler implements JdtAstReconciler {
FQN_EXPR_AUTH_CONFIG,
FQN_EXPR_INTERCEPT_REG
));
if (needsFullAst) {
throw new RequiredCompleteAstException();
}
return null;
}
}
@Override
public boolean isApplicable(IJavaProject project) {
Version version = SpringProjectUtil.getDependencyVersion(project, "spring-security-config");
return version != null && version.compareTo(new Version(5, 6, 0, null)) >= 0;
}
@Override
public ProblemType getProblemType() {
return Boot2JavaProblemType.HTTP_SECURITY_AUTHORIZE_HTTP_REQUESTS;
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023 VMware, Inc.
* Copyright (c) 2023, 2024 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
@@ -18,7 +18,6 @@ import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import org.eclipse.jdt.core.dom.ASTVisitor;
@@ -57,14 +56,32 @@ public class AutowiredFieldIntoConstructorParameterReconciler implements JdtAstR
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector,
boolean isCompleteAst) throws RequiredCompleteAstException {
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(2, 0, 0).test(project);
}
@Override
public ProblemType getProblemType() {
return Boot2JavaProblemType.JAVA_CONSTRUCTOR_PARAMETER_INJECTION;
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) throws RequiredCompleteAstException {
ASTVisitor visitor = createVisitor(project, docUri, cu, problemCollector, isCompleteAst);
if (visitor != null) {
cu.accept(visitor);
}
}
@Override
public ASTVisitor createVisitor(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) {
Path sourceFile = Paths.get(docUri);
// Check if source file belongs to non-test java sources folder
if (IClasspathUtil.getProjectJavaSourceFoldersWithoutTests(project.getClasspath())
.anyMatch(f -> sourceFile.startsWith(f.toPath()))) {
AtomicBoolean completeAstRequired = new AtomicBoolean(false);
cu.accept(new ASTVisitor() {
return new ASTVisitor() {
@Override
public boolean visit(FieldDeclaration field) {
@@ -84,8 +101,7 @@ public class AutowiredFieldIntoConstructorParameterReconciler implements JdtAstR
problemCollector.accept(createProblem(cu, field, fieldName, docUri));
} else if (constructors.size() == 1) {
if (!isCompleteAst) {
completeAstRequired.set(true);
return false;
throw new RequiredCompleteAstException();
}
if (!isAssigningField(constructors.get(0), variableDeclarationFragment.resolveBinding(),
fieldName)) {
@@ -98,8 +114,7 @@ public class AutowiredFieldIntoConstructorParameterReconciler implements JdtAstR
.limit(2).collect(Collectors.toList());
if (autowiredConstructors.size() == 1) {
if (!isCompleteAst) {
completeAstRequired.set(true);
return false;
throw new RequiredCompleteAstException();
} else if (!isAssigningField(autowiredConstructors.get(0),
variableDeclarationFragment.resolveBinding(), fieldName)) {
problemCollector.accept(createProblem(cu, field, fieldName, docUri));
@@ -112,12 +127,11 @@ public class AutowiredFieldIntoConstructorParameterReconciler implements JdtAstR
return true;
}
});
if (completeAstRequired.get()) {
throw new RequiredCompleteAstException();
}
};
}
else {
return null;
}
}
private ReconcileProblemImpl createProblem(CompilationUnit cu, FieldDeclaration field, String fieldName,
@@ -157,14 +171,4 @@ public class AutowiredFieldIntoConstructorParameterReconciler implements JdtAstR
return false;
}
@Override
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(2, 0, 0).test(project);
}
@Override
public ProblemType getProblemType() {
return Boot2JavaProblemType.JAVA_CONSTRUCTOR_PARAMETER_INJECTION;
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2022, 2023 VMware, Inc.
* Copyright (c) 2022, 2024 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
@@ -46,8 +46,7 @@ import org.springframework.ide.vscode.commons.rewrite.java.FixDescriptor;
public class BeanMethodNotPublicReconciler implements JdtAstReconciler {
private static final Logger log = LoggerFactory.getLogger(BeanMethodNotPublicReconciler.class);
private static final String LABEL = "Remove 'public' from @Bean method";
private static final String LABEL = "Remove 'public' from @Bean method";
private final QuickfixRegistry quickfixRegistry;
@@ -55,6 +54,62 @@ public class BeanMethodNotPublicReconciler implements JdtAstReconciler {
this.quickfixRegistry = quickfixRegistry;
}
@Override
public boolean isApplicable(IJavaProject project) {
Version version = SpringProjectUtil.getDependencyVersion(project, SpringProjectUtil.SPRING_BOOT);
return version != null && version.getMajor() >= 2;
}
@Override
public ProblemType getProblemType() {
return Boot2JavaProblemType.JAVA_PUBLIC_BEAN_METHOD;
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) {
ASTVisitor visitor = createVisitor(project, docUri, cu, problemCollector, isCompleteAst);
cu.accept(visitor);
}
@Override
public ASTVisitor createVisitor(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) {
return new ASTVisitor() {
@Override
public boolean visit(SingleMemberAnnotation node) {
try {
visitAnnotation(project, cu, docUri, node, problemCollector);
} catch (Exception e) {
}
return super.visit(node);
}
@Override
public boolean visit(NormalAnnotation node) {
try {
visitAnnotation(project, cu, docUri, node, problemCollector);
} catch (Exception e) {
}
return super.visit(node);
}
@Override
public boolean visit(MarkerAnnotation node) {
try {
visitAnnotation(project, cu, docUri, node, problemCollector);
} catch (Exception e) {
}
return super.visit(node);
}
};
}
public static final boolean isNotOverridingPublicMethod(IMethodBinding methodBinding) {
return !isOverriding(methodBinding) && (methodBinding.getModifiers() & Modifier.PUBLIC) != 0;
}
private void visitAnnotation(IJavaProject project, CompilationUnit cu, URI docUri, Annotation node, IProblemCollector problemCollector) {
ITypeBinding typeBinding = node.resolveTypeBinding();
if (typeBinding != null && Annotations.BEAN.equals(typeBinding.getQualifiedName()) && node.getParent() instanceof MethodDeclaration) {
@@ -95,10 +150,6 @@ public class BeanMethodNotPublicReconciler implements JdtAstReconciler {
return false;
}
public static final boolean isNotOverridingPublicMethod(IMethodBinding methodBinding) {
return !isOverriding(methodBinding) && (methodBinding.getModifiers() & Modifier.PUBLIC) != 0;
}
private void addQuickFixes(CompilationUnit cu, URI docUri, ReconcileProblemImpl problem, MethodDeclaration method) {
if (quickfixRegistry != null) {
@@ -130,49 +181,4 @@ public class BeanMethodNotPublicReconciler implements JdtAstReconciler {
}
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) {
cu.accept(new ASTVisitor() {
@Override
public boolean visit(SingleMemberAnnotation node) {
try {
visitAnnotation(project, cu, docUri, node, problemCollector);
} catch (Exception e) {
}
return super.visit(node);
}
@Override
public boolean visit(NormalAnnotation node) {
try {
visitAnnotation(project, cu, docUri, node, problemCollector);
} catch (Exception e) {
}
return super.visit(node);
}
@Override
public boolean visit(MarkerAnnotation node) {
try {
visitAnnotation(project, cu, docUri, node, problemCollector);
} catch (Exception e) {
}
return super.visit(node);
}
});
}
@Override
public boolean isApplicable(IJavaProject project) {
Version version = SpringProjectUtil.getDependencyVersion(project, SpringProjectUtil.SPRING_BOOT);
return version != null && version.getMajor() >= 2;
}
@Override
public ProblemType getProblemType() {
return Boot2JavaProblemType.JAVA_PUBLIC_BEAN_METHOD;
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023 VMware, Inc.
* Copyright (c) 2023, 2024 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
@@ -44,12 +44,27 @@ public class BeanPostProcessingIgnoreInAotReconciler implements JdtAstReconciler
public BeanPostProcessingIgnoreInAotReconciler(QuickfixRegistry registry) {
this.registry = registry;
}
@Override
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(3, 0, 0).test(project);
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector,
boolean isCompleteAst) throws RequiredCompleteAstException {
AtomicBoolean requiresFullAst = new AtomicBoolean(false);
cu.accept(new ASTVisitor() {
public ProblemType getProblemType() {
return SpringAotJavaProblemType.JAVA_BEAN_POST_PROCESSOR_IGNORED_IN_AOT;
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) throws RequiredCompleteAstException {
ASTVisitor visitor = createVisitor(project, docUri, cu, problemCollector, isCompleteAst);
cu.accept(visitor);
}
@Override
public ASTVisitor createVisitor(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) {
return new ASTVisitor() {
@Override
public boolean visit(TypeDeclaration typeDecl) {
@@ -77,7 +92,7 @@ public class BeanPostProcessingIgnoreInAotReconciler implements JdtAstReconciler
});
markProblem = returnsTrue.get();
} else {
requiresFullAst.set(true);
throw new RequiredCompleteAstException();
}
} else {
markProblem = true;
@@ -93,27 +108,14 @@ public class BeanPostProcessingIgnoreInAotReconciler implements JdtAstReconciler
problemCollector.accept(problem);
}
}
return !requiresFullAst.get();
return true;
}
private boolean isApplicable(ITypeBinding type) {
return ReconcileUtils.implementsType(RUNTIME_BEAN_POST_PROCESSOR, type) && ReconcileUtils.implementsType(COMPILE_BEAN_POST_PROCESSOR, type);
}
});
if (requiresFullAst.get()) {
throw new RequiredCompleteAstException();
}
};
}
@Override
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(3, 0, 0).test(project);
}
@Override
public ProblemType getProblemType() {
return SpringAotJavaProblemType.JAVA_BEAN_POST_PROCESSOR_IGNORED_IN_AOT;
private static boolean isApplicable(ITypeBinding type) {
return ReconcileUtils.implementsType(RUNTIME_BEAN_POST_PROCESSOR, type) && ReconcileUtils.implementsType(COMPILE_BEAN_POST_PROCESSOR, type);
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023 VMware, Inc.
* Copyright (c) 2023, 2024 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
@@ -33,11 +33,26 @@ public class Boot3NotSupportedTypeReconciler implements JdtAstReconciler {
"java.lang.SecurityManager",
"java.security.AccessControlException"
);
@Override
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(3, 0, 0).test(project);
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector,
boolean isCompleteAst) throws RequiredCompleteAstException {
cu.accept(new ASTVisitor() {
public ProblemType getProblemType() {
return Boot3JavaProblemType.JAVA_TYPE_NOT_SUPPORTED;
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) throws RequiredCompleteAstException {
ASTVisitor visitor = createVisitor(project, docUri, cu, problemCollector, isCompleteAst);
cu.accept(visitor);
}
@Override
public ASTVisitor createVisitor(IJavaProject project, URI docURI, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) {
return new ASTVisitor() {
@Override
public boolean visit(ImportDeclaration node) {
@@ -57,10 +72,10 @@ public class Boot3NotSupportedTypeReconciler implements JdtAstReconciler {
return super.visit(node);
}
});
};
}
private String processType(CompilationUnit cu, String name) {
private static String processType(CompilationUnit cu, String name) {
if (TYPE_FQNAMES.contains(name)) {
return name;
} else {
@@ -73,7 +88,7 @@ public class Boot3NotSupportedTypeReconciler implements JdtAstReconciler {
return null;
}
private List<String> createFqNamesFromWildcardImports(CompilationUnit cu, String name) {
private static List<String> createFqNamesFromWildcardImports(CompilationUnit cu, String name) {
List<String> fqNames = new ArrayList<>();
for (Object im : cu.imports()) {
ImportDeclaration importDecl = (ImportDeclaration) im;
@@ -84,16 +99,6 @@ public class Boot3NotSupportedTypeReconciler implements JdtAstReconciler {
return fqNames;
}
@Override
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(3, 0, 0).test(project);
}
@Override
public ProblemType getProblemType() {
return Boot3JavaProblemType.JAVA_TYPE_NOT_SUPPORTED;
}
private static String createLabel(String type) {
StringBuilder sb = new StringBuilder();
sb.append("'");

View File

@@ -0,0 +1,143 @@
/*******************************************************************************
* Copyright (c) 2024 Broadcom
* 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:
* Broadcom - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.reconcilers;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.ImportDeclaration;
import org.eclipse.jdt.core.dom.MarkerAnnotation;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.NormalAnnotation;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.SimpleType;
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
import org.eclipse.jdt.core.dom.TypeDeclaration;
public class CompositeASTVisitor extends ASTVisitor {
List<ASTVisitor> visitors = new ArrayList<>();
public void add(ASTVisitor visitor) {
visitors.add(visitor);
}
@Override
public boolean visit(TypeDeclaration node) {
boolean result = true;
for (ASTVisitor astVisitor : visitors) {
result &= astVisitor.visit(node);
}
return result;
}
@Override
public boolean visit(MethodInvocation node) {
boolean result = true;
for (ASTVisitor astVisitor : visitors) {
result &= astVisitor.visit(node);
}
return result;
}
@Override
public boolean visit(MethodDeclaration node) {
boolean result = true;
for (ASTVisitor astVisitor : visitors) {
result &= astVisitor.visit(node);
}
return result;
}
@Override
public void endVisit(MethodDeclaration node) {
for (ASTVisitor astVisitor : visitors) {
astVisitor.endVisit(node);
}
}
@Override
public boolean visit(FieldDeclaration node) {
boolean result = true;
for (ASTVisitor astVisitor : visitors) {
result &= astVisitor.visit(node);
}
return result;
}
@Override
public boolean visit(SingleMemberAnnotation node) {
boolean result = true;
for (ASTVisitor astVisitor : visitors) {
result &= astVisitor.visit(node);
}
return result;
}
@Override
public boolean visit(NormalAnnotation node) {
boolean result = true;
for (ASTVisitor astVisitor : visitors) {
result &= astVisitor.visit(node);
}
return result;
}
@Override
public boolean visit(MarkerAnnotation node) {
boolean result = true;
for (ASTVisitor astVisitor : visitors) {
result &= astVisitor.visit(node);
}
return result;
}
@Override
public boolean visit(ImportDeclaration node) {
boolean result = true;
for (ASTVisitor astVisitor : visitors) {
result &= astVisitor.visit(node);
}
return result;
}
@Override
public boolean visit(SimpleType node) {
boolean result = true;
for (ASTVisitor astVisitor : visitors) {
result &= astVisitor.visit(node);
}
return result;
}
@Override
public boolean visit(QualifiedName node) {
boolean result = true;
for (ASTVisitor astVisitor : visitors) {
result &= astVisitor.visit(node);
}
return result;
}
@Override
public boolean visit(ReturnStatement node) {
boolean result = true;
for (ASTVisitor astVisitor : visitors) {
result &= astVisitor.visit(node);
}
return result;
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023 VMware, Inc.
* Copyright (c) 2023, 2024 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
@@ -55,12 +55,31 @@ public class EntityIdForRepoReconciler implements JdtAstReconciler {
Double.class.getName(),
Byte.class.getName()
);
@Override
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(2, 0, 0).test(project);
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector,
boolean isCompleteAst) throws RequiredCompleteAstException {
final boolean considerIdField = project.getClasspath().findBinaryLibrary("spring-data-mongodb-").isPresent();
cu.accept(new ASTVisitor() {
public ProblemType getProblemType() {
return Boot2JavaProblemType.DOMAIN_ID_FOR_REPOSITORY;
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) throws RequiredCompleteAstException {
ASTVisitor visitor = createVisitor(project, docUri, cu, problemCollector, isCompleteAst);
if (visitor != null) {
cu.accept(visitor);
}
}
@Override
public ASTVisitor createVisitor(IJavaProject project, URI docURI, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) {
return new ASTVisitor() {
final boolean considerIdField = project.getClasspath().findBinaryLibrary("spring-data-mongodb-").isPresent();
@Override
public boolean visit(TypeDeclaration typeDecl) {
@@ -216,22 +235,6 @@ public class EntityIdForRepoReconciler implements JdtAstReconciler {
}
}
private ITypeBinding getTypeFromAnnotationParameter(IAnnotationBinding a, String param) {
for (IMemberValuePairBinding pair : a.getDeclaredMemberValuePairs()) {
if (pair.getName().equals(param)) {
if (pair.getValue() instanceof ITypeBinding) {
return (ITypeBinding) pair.getValue();
} else if (pair.getValue() instanceof Object[]) {
Object[] arr = (Object[]) pair.getValue();
if (arr.length > 0 && arr[0] instanceof ITypeBinding) {
return (ITypeBinding) arr[0];
}
}
}
}
return null;
}
private List<ITypeBinding> findIdType(ITypeBinding type) {
List<ITypeBinding> idTypes = findAnnotatedIdTypes(type, new HashSet<>());
if (idTypes.isEmpty() && considerIdField) {
@@ -243,40 +246,47 @@ public class EntityIdForRepoReconciler implements JdtAstReconciler {
return idTypes;
}
private boolean isValidRepoIdType(ITypeBinding repoIdType, ITypeBinding idType) {
if (NUMBER_CLASS_NAMES.contains(repoIdType.getQualifiedName()) && NUMBER_CLASS_NAMES.contains(idType.getQualifiedName())) {
return true;
};
}
private static boolean isValidRepoIdType(ITypeBinding repoIdType, ITypeBinding idType) {
if (NUMBER_CLASS_NAMES.contains(repoIdType.getQualifiedName()) && NUMBER_CLASS_NAMES.contains(idType.getQualifiedName())) {
return true;
}
return repoIdType.isCastCompatible(idType) || idType.isCastCompatible(repoIdType);
}
private static ITypeBinding getTypeFromAnnotationParameter(IAnnotationBinding a, String param) {
for (IMemberValuePairBinding pair : a.getDeclaredMemberValuePairs()) {
if (pair.getName().equals(param)) {
if (pair.getValue() instanceof ITypeBinding) {
return (ITypeBinding) pair.getValue();
} else if (pair.getValue() instanceof Object[]) {
Object[] arr = (Object[]) pair.getValue();
if (arr.length > 0 && arr[0] instanceof ITypeBinding) {
return (ITypeBinding) arr[0];
}
}
return repoIdType.isCastCompatible(idType) || idType.isCastCompatible(repoIdType);
}
});
}
@Override
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(2, 0, 0).test(project);
}
@Override
public ProblemType getProblemType() {
return Boot2JavaProblemType.DOMAIN_ID_FOR_REPOSITORY;
}
public static void findSuperTypeBindings(ITypeBinding binding, Set<ITypeBinding> superTypes) {
// superclasses
ITypeBinding superclass = binding.getSuperclass();
if (superclass != null) {
superTypes.add(superclass);
findSuperTypeBindings(superclass, superTypes);
}
// interfaces
for (ITypeBinding i : binding.getInterfaces()) {
superTypes.add(i);
findSuperTypeBindings(i, superTypes);
}
return null;
}
// public static void findSuperTypeBindings(ITypeBinding binding, Set<ITypeBinding> superTypes) {
// // superclasses
// ITypeBinding superclass = binding.getSuperclass();
// if (superclass != null) {
// superTypes.add(superclass);
// findSuperTypeBindings(superclass, superTypes);
// }
// // interfaces
// for (ITypeBinding i : binding.getInterfaces()) {
// superTypes.add(i);
// findSuperTypeBindings(i, superTypes);
// }
// }
//
private static @Nullable List<ITypeBinding> findRepoTypeChain(ITypeBinding type, List<ITypeBinding> visited) {
if (visited.stream().anyMatch(b -> b.isEqualTo(type))) {
return null;
@@ -404,7 +414,7 @@ public class EntityIdForRepoReconciler implements JdtAstReconciler {
return true;
}
private List<ASTNode> findParamTypes(List<?> typeParams, ITypeBinding idType) {
private static List<ASTNode> findParamTypes(List<?> typeParams, ITypeBinding idType) {
List<ASTNode> matchedParams = new ArrayList<>();
for (Object o : typeParams) {
if (o instanceof TypeParameter) {
@@ -424,4 +434,5 @@ public class EntityIdForRepoReconciler implements JdtAstReconciler {
return matchedParams;
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023 VMware, Inc.
* Copyright (c) 2023, 2024 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
@@ -12,6 +12,7 @@ package org.springframework.ide.vscode.boot.java.reconcilers;
import java.net.URI;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
@@ -25,4 +26,6 @@ public interface JdtAstReconciler {
ProblemType getProblemType();
ASTVisitor createVisitor(IJavaProject project, URI docURI, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst);
}

View File

@@ -17,6 +17,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -49,13 +50,19 @@ public class JdtReconciler implements JavaReconciler {
private final CompilationUnitCache compilationUnitCache;
private final JdtAstReconciler[] reconcilers;
private BootJavaConfig config;
private long stats_timer;
private long stats_counter;
public JdtReconciler(CompilationUnitCache compilationUnitCache, BootJavaConfig config, JdtAstReconciler[] reconcilers) {
this.compilationUnitCache = compilationUnitCache;
this.config = config;
this.reconcilers = reconcilers;
this.stats_timer = 0;
this.stats_counter = 0;
}
@Override
public void reconcile(IJavaProject project, final IDocument doc, final IProblemCollector problemCollector) {
if (!config.isJavaSourceReconcileEnabled()) {
@@ -76,20 +83,48 @@ public class JdtReconciler implements JavaReconciler {
return null;
});
}
public ASTVisitor createCompositeVisitor(IJavaProject project, URI docURI, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) throws RequiredCompleteAstException {
CompositeASTVisitor compositeVisitor = new CompositeASTVisitor();
for (JdtAstReconciler reconciler : getApplicableReconcilers(project)) {
ASTVisitor visitor = reconciler.createVisitor(project, docURI, cu, problemCollector, isCompleteAst);
if (visitor != null) {
compositeVisitor.add(visitor);
}
}
return compositeVisitor;
}
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) throws RequiredCompleteAstException {
long start = System.currentTimeMillis();
if (!config.isJavaSourceReconcileEnabled()) {
return;
}
for (JdtAstReconciler reconciler : getApplicableReconcilers(project)) {
try {
reconciler.reconcile(project, docUri, cu, problemCollector, isCompleteAst);
} catch (RequiredCompleteAstException e) {
throw e;
} catch (Exception e) {
log.error("", e);
}
try {
ASTVisitor compositeVisitor = createCompositeVisitor(project, docUri, cu, problemCollector, isCompleteAst);
cu.accept(compositeVisitor);
// for (JdtAstReconciler reconciler : getApplicableReconcilers(project)) {
// try {
// reconciler.reconcile(project, docUri, cu, problemCollector, isCompleteAst);
// } catch (RequiredCompleteAstException e) {
// throw e;
// } catch (Exception e) {
// log.error("", e);
// }
// }
}
finally {
long end = System.currentTimeMillis();
stats_counter++;
stats_timer += (end - start);
}
}
@@ -120,5 +155,13 @@ public class JdtReconciler implements JavaReconciler {
return Collections.emptyMap();
}
public long getStatsTimer() {
return stats_timer;
}
public long getStatsCounter() {
return stats_counter;
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023 VMware, Inc.
* Copyright (c) 2023, 2024 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
@@ -35,19 +35,44 @@ import org.springframework.ide.vscode.commons.languageserver.reconcile.Reconcile
public class ModulithTypeReferenceViolationReconciler implements JdtAstReconciler, ApplicationContextAware {
private ApplicationContext appContext;
@Override
public boolean isApplicable(IJavaProject project) {
return ModulithService.isModulithDependentProject(project);
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector,
boolean isCompleteAst) throws RequiredCompleteAstException {
public ProblemType getProblemType() {
return Boot3JavaProblemType.MODULITH_TYPE_REF_VIOLATION;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.appContext = applicationContext;
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) throws RequiredCompleteAstException {
ASTVisitor visitor = createVisitor(project, docUri, cu, problemCollector, isCompleteAst);
if (visitor != null) {
cu.accept(visitor);
}
}
@Override
public ASTVisitor createVisitor(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) {
Path sourceFile = Paths.get(docUri);
if (IClasspathUtil.getProjectJavaSourceFoldersWithoutTests(project.getClasspath())
.anyMatch(f -> sourceFile.startsWith(f.toPath()))) {
ModulithService modulithService = appContext.getBean(ModulithService.class);
AppModules appModules = modulithService.getModulesData(project);
if (appModules != null) {
final String packageName = cu.getPackage().getName().getFullyQualifiedName();
cu.accept(new ASTVisitor() {
return new ASTVisitor() {
@Override
public boolean visit(QualifiedName node) {
@@ -71,25 +96,11 @@ public class ModulithTypeReferenceViolationReconciler implements JdtAstReconcile
}
}
});
};
}
}
}
@Override
public boolean isApplicable(IJavaProject project) {
return ModulithService.isModulithDependentProject(project);
}
@Override
public ProblemType getProblemType() {
return Boot3JavaProblemType.MODULITH_TYPE_REF_VIOLATION;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.appContext = applicationContext;
return null;
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023 VMware, Inc.
* Copyright (c) 2023, 2024 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
@@ -45,9 +45,25 @@ public class NoAutowiredOnConstructorReconciler implements JdtAstReconciler {
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector,
boolean isCompleteAst) throws RequiredCompleteAstException {
cu.accept(new ASTVisitor() {
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(2, 0, 0).test(project);
}
@Override
public ProblemType getProblemType() {
return Boot2JavaProblemType.JAVA_AUTOWIRED_CONSTRUCTOR;
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) throws RequiredCompleteAstException {
ASTVisitor visitor = createVisitor(project, docUri, cu, problemCollector, isCompleteAst);
cu.accept(visitor);
}
@Override
public ASTVisitor createVisitor(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) {
return new ASTVisitor() {
@Override
public boolean visit(TypeDeclaration typeDecl) {
@@ -86,17 +102,7 @@ public class NoAutowiredOnConstructorReconciler implements JdtAstReconciler {
return super.visit(typeDecl);
}
});
}
@Override
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(2, 0, 0).test(project);
}
@Override
public ProblemType getProblemType() {
return Boot2JavaProblemType.JAVA_AUTOWIRED_CONSTRUCTOR;
};
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023 VMware, Inc.
* Copyright (c) 2023, 2024 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
@@ -44,10 +44,25 @@ public class NoRepoAnnotationReconciler implements JdtAstReconciler {
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector,
boolean isCompleteAst) throws RequiredCompleteAstException {
cu.accept(new ASTVisitor() {
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(2, 0, 0).test(project);
}
@Override
public Boot2JavaProblemType getProblemType() {
return Boot2JavaProblemType.JAVA_REPOSITORY;
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) throws RequiredCompleteAstException {
ASTVisitor visitor = createVisitor(project, docUri, cu, problemCollector, isCompleteAst);
cu.accept(visitor);
}
@Override
public ASTVisitor createVisitor(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) {
return new ASTVisitor() {
@Override
public boolean visit(TypeDeclaration typeDecl) {
@@ -80,46 +95,35 @@ public class NoRepoAnnotationReconciler implements JdtAstReconciler {
}
return super.visit(typeDecl);
}
private boolean isApplicableRepoAnnotation(Annotation a) {
if (a instanceof MarkerAnnotation || (a.isNormalAnnotation() && ((NormalAnnotation) a).properties().isEmpty())) {
String typeName = a.getTypeName().getFullyQualifiedName();
if (Annotations.REPOSITORY.equals(typeName)) {
return true;
} else if (typeName.endsWith("Repository")) {
ITypeBinding type = a.resolveTypeBinding();
if (type != null && Annotations.REPOSITORY.equals(type.getQualifiedName())) {
return true;
}
}
}
return false;
}
private boolean isRepo(ITypeBinding t) {
if (INTERFACE_REPOSITORY.equals(t.getQualifiedName())) {
};
}
private static boolean isApplicableRepoAnnotation(Annotation a) {
if (a instanceof MarkerAnnotation || (a.isNormalAnnotation() && ((NormalAnnotation) a).properties().isEmpty())) {
String typeName = a.getTypeName().getFullyQualifiedName();
if (Annotations.REPOSITORY.equals(typeName)) {
return true;
} else if (typeName.endsWith("Repository")) {
ITypeBinding type = a.resolveTypeBinding();
if (type != null && Annotations.REPOSITORY.equals(type.getQualifiedName())) {
return true;
} else {
for (ITypeBinding st : t.getInterfaces()) {
if (isRepo(st)) {
return true;
}
}
}
return false;
}
});
}
return false;
}
@Override
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(2, 0, 0).test(project);
}
@Override
public Boot2JavaProblemType getProblemType() {
return Boot2JavaProblemType.JAVA_REPOSITORY;
private static boolean isRepo(ITypeBinding t) {
if (INTERFACE_REPOSITORY.equals(t.getQualifiedName())) {
return true;
} else {
for (ITypeBinding st : t.getInterfaces()) {
if (isRepo(st)) {
return true;
}
}
}
return false;
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023 VMware, Inc.
* Copyright (c) 2023, 2024 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
@@ -57,11 +57,27 @@ public class NoRequestMappingAnnotationReconciler implements JdtAstReconciler {
public NoRequestMappingAnnotationReconciler(QuickfixRegistry registry) {
this.registry = registry;
}
@Override
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(2, 0, 0).test(project);
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector,
boolean isCompleteAst) throws RequiredCompleteAstException {
cu.accept(new ASTVisitor() {
public ProblemType getProblemType() {
return Boot2JavaProblemType.JAVA_PRECISE_REQUEST_MAPPING;
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) throws RequiredCompleteAstException {
ASTVisitor visitor = createVisitor(project, docUri, cu, problemCollector, isCompleteAst);
cu.accept(visitor);
}
@Override
public ASTVisitor createVisitor(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) {
return new ASTVisitor() {
@Override
public boolean visit(MarkerAnnotation node) {
@@ -109,7 +125,7 @@ public class NoRequestMappingAnnotationReconciler implements JdtAstReconciler {
}
}
});
};
}
private static FixDescriptor createFixDescriptor(String uri, Range range, String requestMethod) {
@@ -162,14 +178,4 @@ public class NoRequestMappingAnnotationReconciler implements JdtAstReconciler {
return SUPPORTED_REQUEST_METHODS.contains(requestMethod) ? requestMethod : UNSUPPORTED_REQUEST_METHOD;
}
@Override
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(2, 0, 0).test(project);
}
@Override
public ProblemType getProblemType() {
return Boot2JavaProblemType.JAVA_PRECISE_REQUEST_MAPPING;
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023 VMware, Inc.
* Copyright (c) 2023, 2204 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
@@ -64,14 +64,34 @@ public class NotRegisteredBeansReconciler implements JdtAstReconciler, Applicati
private QuickfixRegistry registry;
public NotRegisteredBeansReconciler(QuickfixRegistry registry) {
this.registry = registry;
this.registry = registry;
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector,
boolean isCompleteAst) throws RequiredCompleteAstException {
cu.accept(new ASTVisitor() {
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(3, 0, 0).test(project);
}
@Override
public ProblemType getProblemType() {
return SpringAotJavaProblemType.JAVA_BEAN_NOT_REGISTERED_IN_AOT;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) throws RequiredCompleteAstException {
ASTVisitor visitor = createVisitor(project, docUri, cu, problemCollector, isCompleteAst);
cu.accept(visitor);
}
@Override
public ASTVisitor createVisitor(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) {
return new ASTVisitor() {
@Override
public boolean visit(TypeDeclaration node) {
@@ -146,24 +166,9 @@ public class NotRegisteredBeansReconciler implements JdtAstReconciler, Applicati
return super.visit(node);
}
});
};
}
@Override
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(3, 0, 0).test(project);
}
@Override
public ProblemType getProblemType() {
return SpringAotJavaProblemType.JAVA_BEAN_NOT_REGISTERED_IN_AOT;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
private static Set<String> allFQTypes(IBinding binding) {
ImmutableSet.Builder<String> b = ImmutableSet.builder();
if (binding instanceof IMethodBinding) {

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023 VMware, Inc.
* Copyright (c) 2023, 2024 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
@@ -17,7 +17,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.CompilationUnit;
@@ -45,14 +44,28 @@ public class PreciseBeanTypeReconciler implements JdtAstReconciler {
public PreciseBeanTypeReconciler(QuickfixRegistry registry) {
this.registry = registry;
}
@Override
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(3, 0, 0).test(project);
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector,
boolean isCompleteAst) throws RequiredCompleteAstException {
AtomicBoolean requiresCompleteAst = new AtomicBoolean(false);
cu.accept(new ASTVisitor() {
public ProblemType getProblemType() {
return SpringAotJavaProblemType.JAVA_CONCRETE_BEAN_TYPE;
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) throws RequiredCompleteAstException {
ASTVisitor visitor = createVisitor(project, docUri, cu, problemCollector, isCompleteAst);
cu.accept(visitor);
}
@Override
public ASTVisitor createVisitor(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) {
return new ASTVisitor() {
private MethodDeclaration currentMethod;
@@ -72,7 +85,7 @@ public class PreciseBeanTypeReconciler implements JdtAstReconciler {
return true;
}
} else {
requiresCompleteAst.set(true);
throw new RequiredCompleteAstException();
}
}
}
@@ -124,21 +137,7 @@ public class PreciseBeanTypeReconciler implements JdtAstReconciler {
return super.visit(node);
}
});
if (requiresCompleteAst.get()) {
throw new RequiredCompleteAstException();
}
}
@Override
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(3, 0, 0).test(project);
}
@Override
public ProblemType getProblemType() {
return SpringAotJavaProblemType.JAVA_CONCRETE_BEAN_TYPE;
};
}
}

View File

@@ -10,7 +10,7 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.reconcilers;
public class RequiredCompleteAstException extends Exception {
public class RequiredCompleteAstException extends RuntimeException {
private static final long serialVersionUID = 1L;

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023 VMware, Inc.
* Copyright (c) 2023, 2024 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
@@ -61,13 +61,28 @@ public class UnnecessarySpringExtensionReconciler implements JdtAstReconciler {
public UnnecessarySpringExtensionReconciler(QuickfixRegistry registry) {
this.registry = registry;
}
@Override
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(2, 1, 0).test(project);
}
@Override
public Boot2JavaProblemType getProblemType() {
return Boot2JavaProblemType.JAVA_TEST_SPRING_EXTENSION;
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector,
boolean isCompleteAst) throws RequiredCompleteAstException {
cu.accept(new ASTVisitor() {
ASTVisitor visitor = createVisitor(project, docUri, cu, problemCollector, isCompleteAst);
cu.accept(visitor);
}
@Override
public ASTVisitor createVisitor(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) {
return new ASTVisitor() {
@Override
public boolean visit(TypeDeclaration typeDecl) {
@@ -94,50 +109,40 @@ public class UnnecessarySpringExtensionReconciler implements JdtAstReconciler {
}
return super.visit(typeDecl);
}
private boolean isApplicableExtendsWith(Annotation a) {
if (FQN_EXTEND_WITH.endsWith(a.getTypeName().getFullyQualifiedName())) {
IAnnotationBinding annotationBinding = a.resolveAnnotationBinding();
if (annotationBinding != null && FQN_EXTEND_WITH.equals(annotationBinding.getAnnotationType().getQualifiedName()) && annotationBinding.getDeclaredMemberValuePairs().length == 1) {
IMemberValuePairBinding pair = annotationBinding.getDeclaredMemberValuePairs()[0];
if ("value".equals(pair.getName())) {
ITypeBinding typeBinding = null;
if (pair.getValue() instanceof ITypeBinding) {
typeBinding = (ITypeBinding) pair.getValue();
} else if (pair.getValue() instanceof Object[]) {
Object[] arr = (Object[]) pair.getValue();
if (arr.length > 0 && arr[0] instanceof ITypeBinding) {
typeBinding = (ITypeBinding) arr[0];
}
}
return typeBinding != null && FQN_SPRING_EXT.equals(typeBinding.getQualifiedName());
};
}
private static boolean isApplicableExtendsWith(Annotation a) {
if (FQN_EXTEND_WITH.endsWith(a.getTypeName().getFullyQualifiedName())) {
IAnnotationBinding annotationBinding = a.resolveAnnotationBinding();
if (annotationBinding != null && FQN_EXTEND_WITH.equals(annotationBinding.getAnnotationType().getQualifiedName()) && annotationBinding.getDeclaredMemberValuePairs().length == 1) {
IMemberValuePairBinding pair = annotationBinding.getDeclaredMemberValuePairs()[0];
if ("value".equals(pair.getName())) {
ITypeBinding typeBinding = null;
if (pair.getValue() instanceof ITypeBinding) {
typeBinding = (ITypeBinding) pair.getValue();
} else if (pair.getValue() instanceof Object[]) {
Object[] arr = (Object[]) pair.getValue();
if (arr.length > 0 && arr[0] instanceof ITypeBinding) {
typeBinding = (ITypeBinding) arr[0];
}
}
return typeBinding != null && FQN_SPRING_EXT.equals(typeBinding.getQualifiedName());
}
return false;
}
private boolean isApplicableTestAnnotation(Annotation a) {
String annotationTypeFqn = a.getTypeName().getFullyQualifiedName();
if (SPRING_BOOT_TEST_ANNOTATIONS.stream().anyMatch(fqn -> fqn.endsWith(annotationTypeFqn))) {
IAnnotationBinding annotationBinding = a.resolveAnnotationBinding();
if (annotationBinding != null && SPRING_BOOT_TEST_ANNOTATIONS.contains(annotationBinding.getAnnotationType().getQualifiedName())) {
return true;
}
}
return false;
}
return false;
}
private static boolean isApplicableTestAnnotation(Annotation a) {
String annotationTypeFqn = a.getTypeName().getFullyQualifiedName();
if (SPRING_BOOT_TEST_ANNOTATIONS.stream().anyMatch(fqn -> fqn.endsWith(annotationTypeFqn))) {
IAnnotationBinding annotationBinding = a.resolveAnnotationBinding();
if (annotationBinding != null && SPRING_BOOT_TEST_ANNOTATIONS.contains(annotationBinding.getAnnotationType().getQualifiedName())) {
return true;
}
});
}
@Override
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(2, 1, 0).test(project);
}
@Override
public Boot2JavaProblemType getProblemType() {
return Boot2JavaProblemType.JAVA_TEST_SPRING_EXTENSION;
}
return false;
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023 VMware, Inc.
* Copyright (c) 2023, 2024 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
@@ -36,11 +36,8 @@ import org.springframework.ide.vscode.commons.rewrite.java.FixDescriptor;
public class WebSecurityConfigurerAdapterReconciler implements JdtAstReconciler {
private static final String WEB_SECURITY_CONFIGURER_ADAPTER = "WebSecurityConfigurerAdapter";
private static final String FQN_WEB_SECURITY_CONFIGURER_ADAPTER = "org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter";
private static final String PROBLEM_LABEL = "Class extends 'WebSecurityConfigurerAdapter' which is removed in Spring-Security 6.x";
private static final String FIX_LABEL = "Refactor class into a Configuration bean not extending 'WebSecurityConfigurerAdapter'";
private static final String STUB_WEB_SECURITY_CONFIG_ADAPTER = """
@@ -73,13 +70,28 @@ public class WebSecurityConfigurerAdapterReconciler implements JdtAstReconciler
public WebSecurityConfigurerAdapterReconciler(QuickfixRegistry registry) {
this.registry = registry;
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector,
boolean isCompleteAst) throws RequiredCompleteAstException {
cu.accept(new ASTVisitor() {
public boolean isApplicable(IJavaProject project) {
Version version = SpringProjectUtil.getDependencyVersion(project, "spring-security-config");
return version != null && version.compareTo(new Version(5, 7, 0, null)) >= 0 && version.compareTo(new Version(6, 1, 0, null)) < 0;
}
@Override
public ProblemType getProblemType() {
return Boot2JavaProblemType.WEB_SECURITY_CONFIGURER_ADAPTER;
}
@Override
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) throws RequiredCompleteAstException {
ASTVisitor visitor = createVisitor(project, docUri, cu, problemCollector, isCompleteAst);
cu.accept(visitor);
}
@Override
public ASTVisitor createVisitor(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) {
return new ASTVisitor() {
@Override
public boolean visit(TypeDeclaration typeDecl) {
@@ -108,7 +120,7 @@ public class WebSecurityConfigurerAdapterReconciler implements JdtAstReconciler
return super.visit(typeDecl);
}
});
};
}
private static boolean isWebSecurityConfigurerAdapter(CompilationUnit cu, Type type) {
@@ -133,15 +145,4 @@ public class WebSecurityConfigurerAdapterReconciler implements JdtAstReconciler
return false;
}
@Override
public boolean isApplicable(IJavaProject project) {
Version version = SpringProjectUtil.getDependencyVersion(project, "spring-security-config");
return version != null && version.compareTo(new Version(5, 7, 0, null)) >= 0 && version.compareTo(new Version(6, 1, 0, null)) < 0;
}
@Override
public ProblemType getProblemType() {
return Boot2JavaProblemType.WEB_SECURITY_CONFIGURER_ADAPTER;
}
}

View File

@@ -541,6 +541,9 @@ public class SpringIndexerJava implements SpringIndexer {
addEmptyDiagnostics(diagnosticsByDoc, javaFiles);
symbolHandler.addSymbols(project, enhancedSymbols, allBeans, diagnosticsByDoc);
}
System.out.println("reconciling stats - counter: " + reconciler.getStatsCounter());
System.out.println("reconciling stats - timer: " + reconciler.getStatsTimer());
}
private String[] scanFiles(IJavaProject project, String[] javaFiles, List<CachedSymbol> generatedSymbols, List<CachedBean> generatedBeans,
@@ -606,6 +609,7 @@ public class SpringIndexerJava implements SpringIndexer {
catch (Exception e) {
log.error("error extracting symbol information in project '" + context.getProject().getElementName() + "' - for docURI '" + context.getDocURI() + "' - on node: " + node.toString(), e);
}
return super.visit(node);
}