Remove rewrite reconcile related classes and cleanup

This commit is contained in:
aboyko
2023-08-31 18:16:44 -04:00
parent bf675bca7a
commit da89df6e60
45 changed files with 66 additions and 3081 deletions

View File

@@ -1,75 +0,0 @@
/*******************************************************************************
* Copyright (c) 2022, 2023 VMware, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.rewrite.test;
import java.util.List;
import org.openrewrite.ExecutionContext;
import org.openrewrite.SourceFile;
import org.openrewrite.Tree;
import org.openrewrite.java.JavaIsoVisitor;
import org.openrewrite.java.JavaVisitor;
import org.openrewrite.java.tree.J.MethodDeclaration;
import org.openrewrite.marker.Range;
import org.springframework.ide.vscode.commons.java.IJavaProject;
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;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemTypes;
import org.springframework.ide.vscode.commons.rewrite.config.MarkerVisitorContext;
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;
public class HelloMethodRenameProblemDescriptor implements RecipeCodeActionDescriptor {
private static final String LABEL = "Switch hello method into bye";
private static final String RECIPE_ID = "org.springframework.rewrite.test.HelloMethodRenameRecipe";
@Override
public JavaVisitor<ExecutionContext> getMarkerVisitor(MarkerVisitorContext context) {
return new JavaIsoVisitor<>() {
@Override
public MethodDeclaration visitMethodDeclaration(MethodDeclaration method, ExecutionContext p) {
MethodDeclaration m = super.visitMethodDeclaration(method, p);
if ("hello".equals(method.getSimpleName())) {
String uri = getCursor().firstEnclosing(SourceFile.class).getSourcePath().toUri().toASCIIString();
FixAssistMarker marker = new FixAssistMarker(Tree.randomId(), getId())
.withFixes(
new FixDescriptor(RECIPE_ID, List.of(uri), RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.NODE))
.withRecipeScope(RecipeScope.NODE)
.withRangeScope(m.getMarkers().findFirst(Range.class).get()),
new FixDescriptor(RECIPE_ID, List.of(uri), RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.FILE))
.withRecipeScope(RecipeScope.FILE),
new FixDescriptor(RECIPE_ID, List.of(uri), RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.PROJECT))
.withRecipeScope(RecipeScope.PROJECT)
);
m = m.withName(m.getName().withMarkers(m.getName().getMarkers().add(marker)));
}
return m;
}
};
}
@Override
public boolean isApplicable(IJavaProject project) {
return true;
}
@Override
public ProblemType getProblemType() {
return ProblemTypes.create("Hello Method!", ProblemSeverity.ERROR, ProblemCategory.NO_CATEGORY);
}
}

View File

@@ -1,25 +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.rewrite.test;
import java.util.List;
import org.springframework.ide.vscode.commons.rewrite.config.CodeActionRepository;
import org.springframework.ide.vscode.commons.rewrite.config.RecipeCodeActionDescriptor;
public class StsTestCodeActionRepo extends CodeActionRepository {
@Override
public List<RecipeCodeActionDescriptor> getCodeActionDescriptors() {
return List.of(new HelloMethodRenameProblemDescriptor());
}
}

View File

@@ -1,80 +0,0 @@
/*******************************************************************************
* Copyright (c) 2023 VMware, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.rewrite.config;
import java.lang.reflect.Constructor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import org.openrewrite.internal.RecipeIntrospectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.github.classgraph.ClassGraph;
import io.github.classgraph.ClassInfo;
import io.github.classgraph.ScanResult;
public class CodeActionRepoLoader {
final static Logger log = LoggerFactory.getLogger(CodeActionRepoLoader.class);
private final List<CodeActionRepository> codeActionRepos = new ArrayList<>();
public CodeActionRepoLoader(String... acceptPackages) {
scanClasses(new ClassGraph().acceptPackages(acceptPackages), getClass().getClassLoader());
}
public CodeActionRepoLoader(Path p, ClassLoader classLoader) {
if (Files.isDirectory(p)) {
String dir = p.toString();
scanClasses(new ClassGraph().acceptPaths(dir).ignoreParentClassLoaders().overrideClassLoaders(classLoader),
classLoader);
} else {
String jarName = p.toFile().getName();
scanClasses(
new ClassGraph().acceptJars(jarName).ignoreParentClassLoaders().overrideClassLoaders(classLoader),
classLoader);
}
}
private void scanClasses(ClassGraph classGraph, ClassLoader classLoader) {
try (ScanResult result = classGraph.ignoreClassVisibility().overrideClassLoaders(classLoader).scan()) {
for (ClassInfo classInfo : result.getSubclasses(CodeActionRepository.class.getName())) {
Class<?> codeActionRepoClass = classInfo.loadClass();
Constructor<?> primaryConstructor = RecipeIntrospectionUtils
.getZeroArgsConstructor(codeActionRepoClass);
if (primaryConstructor == null) {
// TODO: error!!!
} else {
try {
CodeActionRepository repo = (CodeActionRepository) primaryConstructor.newInstance();
codeActionRepos.add(repo);
} catch (Throwable t) {
log.warn("Unable to configure " + codeActionRepoClass.getName(), t);
}
}
}
}
}
public List<CodeActionRepository> listCodeActionDescriptorsRepositories() {
return codeActionRepos;
}
}

View File

@@ -1,19 +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.commons.rewrite.config;
import java.util.List;
public abstract class CodeActionRepository {
public abstract List<RecipeCodeActionDescriptor> getCodeActionDescriptors();
}

View File

@@ -1,18 +0,0 @@
/*******************************************************************************
* Copyright (c) 2023 VMware, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.rewrite.config;
import org.springframework.context.ApplicationContext;
import org.springframework.ide.vscode.commons.java.IJavaProject;
public record DefaultMarkerVisitorContext(ApplicationContext appContext, IJavaProject project) implements MarkerVisitorContext {
}

View File

@@ -1,22 +0,0 @@
/*******************************************************************************
* Copyright (c) 2023 VMware, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.rewrite.config;
import org.springframework.context.ApplicationContext;
import org.springframework.ide.vscode.commons.java.IJavaProject;
public interface MarkerVisitorContext {
IJavaProject project();
ApplicationContext appContext();
}

View File

@@ -1,43 +0,0 @@
/*******************************************************************************
* Copyright (c) 2022, 2023 VMware, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.rewrite.config;
import org.openrewrite.ExecutionContext;
import org.openrewrite.java.JavaVisitor;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
public interface RecipeCodeActionDescriptor {
default String getId() {
return getClass().getName();
}
JavaVisitor<ExecutionContext> getMarkerVisitor(MarkerVisitorContext context);
boolean isApplicable(IJavaProject project);
default ProblemType getProblemType() {
return null;
}
static String buildLabel(String label, RecipeScope s) {
switch (s) {
case FILE:
return label + " in file";
case PROJECT:
return label + " in project";
default:
return label;
}
}
}

View File

@@ -1,81 +0,0 @@
/*******************************************************************************
* Copyright (c) 2023 VMware, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.rewrite.config;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.openrewrite.Recipe;
import org.openrewrite.config.Environment;
import org.openrewrite.config.RecipeDescriptor;
import org.openrewrite.config.ResourceLoader;
public class StsEnvironment {
final private Supplier<Stream<CodeActionRepository>> codeActionRepos;
final private Environment env;
private StsEnvironment(Environment env, List<CodeActionRepoLoader> loaders) {
this.env = env;
codeActionRepos = () -> loaders.stream().flatMap(l -> l.listCodeActionDescriptorsRepositories().stream());
}
public static class Builder {
private List<CodeActionRepoLoader> loaders = new ArrayList<>();
private Environment.Builder envBuilder = new Environment.Builder(new Properties());;
public Builder scanRuntimeClasspath(String... acceptPackages) {
loaders.add(new CodeActionRepoLoader(acceptPackages));
envBuilder.scanRuntimeClasspath(acceptPackages);
return this;
}
public Builder scanJar(Path jar, ClassLoader classLoader) {
loaders.add(new CodeActionRepoLoader(jar, classLoader));
envBuilder.scanJar(jar, Collections.emptyList(), classLoader);
return this;
}
public StsEnvironment build() {
return new StsEnvironment(envBuilder.build(), loaders);
}
public void load(ResourceLoader loader) {
envBuilder.load(loader, Collections.emptyList());
}
}
public List<RecipeCodeActionDescriptor> listCodeActionDescriptors() {
return codeActionRepos.get().flatMap(r -> r.getCodeActionDescriptors().stream()).collect(Collectors.toList());
}
public Collection<Recipe> listRecipes() {
return env.listRecipes();
}
public Collection<RecipeDescriptor> listRecipeDescriptors() {
return env.listRecipeDescriptors();
}
public static Builder builder() {
return new Builder();
}
}

View File

@@ -1,22 +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.commons.rewrite.config;
import java.util.List;
import org.openrewrite.config.ResourceLoader;
public interface StsResourceLoader extends ResourceLoader {
List<CodeActionRepository> listCodeActionDescriptorsRepositories();
}

View File

@@ -16,7 +16,6 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ide.vscode.boot.java.reconcilers.JdtReconciler;
import org.springframework.ide.vscode.boot.java.rewrite.RewriteCodeActionHandler;
import org.springframework.ide.vscode.boot.java.rewrite.RewriteCompilationUnitCache;
import org.springframework.ide.vscode.boot.java.rewrite.RewriteRecipeRepository;
import org.springframework.ide.vscode.boot.java.rewrite.RewriteRefactorings;
import org.springframework.ide.vscode.boot.java.rewrite.SpringBootUpgrade;
@@ -32,11 +31,6 @@ public class RewriteConfig {
return new RewriteRecipeRepository(server, projectFinder, config);
}
@ConditionalOnBean(RewriteRecipeRepository.class)
@Bean RewriteCompilationUnitCache orcuCache(SimpleLanguageServer server, BootLanguageServerParams params) {
return new RewriteCompilationUnitCache(params.projectFinder, server, params.projectObserver);
}
@ConditionalOnBean(RewriteRecipeRepository.class)
@Bean RewriteRefactorings rewriteRefactorings(SimpleLanguageServer server, JavaProjectFinder projectFinder, RewriteRecipeRepository recipeRepo) {
return new RewriteRefactorings(server, projectFinder, recipeRepo);
@@ -51,15 +45,5 @@ public class RewriteConfig {
@Bean SpringBootUpgrade springBootUpgrade(SimpleLanguageServer server, RewriteRecipeRepository recipeRepo, JavaProjectFinder projectFinder) {
return new SpringBootUpgrade(server, recipeRepo, projectFinder);
}
// @ConditionalOnBean(RewriteRecipeRepository.class)
// @Bean RewriteReconciler rewriteJavaReconciler(RewriteRecipeRepository recipeRepo, RewriteCompilationUnitCache cuCache, SimpleLanguageServer server, BootJavaConfig config) {
// return new RewriteReconciler(
// recipeRepo,
// cuCache,
// server.getQuickfixRegistry(),
// config
// );
// }
}

View File

@@ -47,16 +47,16 @@ public abstract class AbstractSecurityLamdaDslReconciler implements JdtAstReconc
MethodInvocation topMethodInvocation = findTopLevelMethodInvocation(node);
ReconcileProblemImpl problem = new ReconcileProblemImpl(getProblemType(), getProblemLabel(), topMethodInvocation.getStartPosition(), topMethodInvocation.getLength());
String uri = docUri.toASCIIString();
RewriteQuickFixUtils.setRewriteFixes(registry, problem, List.of(
ReconcileUtils.setRewriteFixes(registry, problem, List.of(
new FixDescriptor(getRecipeId(), List.of(uri),
RewriteQuickFixUtils.buildLabel(getFixLabel(), RecipeScope.NODE))
.withRangeScope(RewriteQuickFixUtils.createOpenRewriteRange(cu, topMethodInvocation))
ReconcileUtils.buildLabel(getFixLabel(), RecipeScope.NODE))
.withRangeScope(ReconcileUtils.createOpenRewriteRange(cu, topMethodInvocation))
.withRecipeScope(RecipeScope.NODE),
new FixDescriptor(getRecipeId(), List.of(uri),
RewriteQuickFixUtils.buildLabel(getFixLabel(), RecipeScope.FILE))
ReconcileUtils.buildLabel(getFixLabel(), RecipeScope.FILE))
.withRecipeScope(RecipeScope.FILE),
new FixDescriptor(getRecipeId(), List.of(uri),
RewriteQuickFixUtils.buildLabel(getFixLabel(), RecipeScope.PROJECT))
ReconcileUtils.buildLabel(getFixLabel(), RecipeScope.PROJECT))
.withRecipeScope(RecipeScope.PROJECT)
));
problemCollector.accept(problem);
@@ -69,7 +69,7 @@ public abstract class AbstractSecurityLamdaDslReconciler implements JdtAstReconc
});
} else {
if (RewriteQuickFixUtils.isAnyTypeUsed(cu, List.of(getTargetTypeFqName()))) {
if (ReconcileUtils.isAnyTypeUsed(cu, List.of(getTargetTypeFqName()))) {
throw new RequiredCompleteAstException();
}
}

View File

@@ -73,12 +73,12 @@ public class AddConfigurationIfBeansPresentReconciler implements JdtAstReconcile
ReconcileProblemImpl problem = new ReconcileProblemImpl(getProblemType(), PROBLEM_LABEL,
nameAst.getStartPosition(), nameAst.getLength());
RewriteQuickFixUtils.setRewriteFixes(quickfixRegistry, problem,
ReconcileUtils.setRewriteFixes(quickfixRegistry, problem,
List.of(new FixDescriptor(ID, List.of(docUri.toASCIIString()),
RewriteQuickFixUtils.buildLabel(FIX_LABEL, RecipeScope.FILE))
ReconcileUtils.buildLabel(FIX_LABEL, RecipeScope.FILE))
.withRecipeScope(RecipeScope.FILE),
new FixDescriptor(ID, List.of(docUri.toASCIIString()),
RewriteQuickFixUtils.buildLabel(FIX_LABEL, RecipeScope.PROJECT))
ReconcileUtils.buildLabel(FIX_LABEL, RecipeScope.PROJECT))
.withRecipeScope(RecipeScope.PROJECT)));
problemCollector.accept(problem);
@@ -137,7 +137,7 @@ public class AddConfigurationIfBeansPresentReconciler implements JdtAstReconcile
if (applicationContext != null) {
SpringSymbolIndex index = applicationContext.getBean(SpringSymbolIndex.class);
if (index != null) {
final String beanClassName = RewriteQuickFixUtils.getDeepErasureType(classDecl.resolveBinding()).getQualifiedName();
final String beanClassName = ReconcileUtils.getDeepErasureType(classDecl.resolveBinding()).getQualifiedName();
for (EnhancedSymbolInformation s : index.getEnhancedSymbols(project)) {
SymbolAddOnInformation[] additionalInformation = s.getAdditionalInformation();
if (additionalInformation != null) {

View File

@@ -71,14 +71,14 @@ public class AuthorizeHttpRequestsReconciler implements JdtAstReconciler {
AUTHORIZE_REQUESTS_PROBLEM_LABEL, node.getName().getStartPosition(),
node.getName().getLength());
String uri = docUri.toASCIIString();
RewriteQuickFixUtils
ReconcileUtils
.setRewriteFixes(registry, problem, List.of(
new FixDescriptor(ID, List.of(uri),
RewriteQuickFixUtils.buildLabel(AUTHORIZE_REQUESTS_FIX_LABEL,
ReconcileUtils.buildLabel(AUTHORIZE_REQUESTS_FIX_LABEL,
RecipeScope.FILE))
.withRecipeScope(RecipeScope.FILE),
new FixDescriptor(ID, List.of(uri),
RewriteQuickFixUtils.buildLabel(AUTHORIZE_REQUESTS_FIX_LABEL,
ReconcileUtils.buildLabel(AUTHORIZE_REQUESTS_FIX_LABEL,
RecipeScope.PROJECT))
.withRecipeScope(RecipeScope.PROJECT)));
problemCollector.accept(problem);
@@ -91,10 +91,10 @@ public class AuthorizeHttpRequestsReconciler implements JdtAstReconciler {
@Override
public boolean visit(SimpleType node) {
String replacementClass = null;
if (RewriteQuickFixUtils.isApplicableTypeWithoutResolving(cu,
if (ReconcileUtils.isApplicableTypeWithoutResolving(cu,
List.of(FQN_AUTH_REQ_CONFIG, FQN_EXPR_AUTH_CONFIG), node.getName())) {
replacementClass = "AuthorizeHttpRequestsConfigurer";
} else if (RewriteQuickFixUtils.isApplicableTypeWithoutResolving(cu, List.of(FQN_EXPR_INTERCEPT_REG),
} else if (ReconcileUtils.isApplicableTypeWithoutResolving(cu, List.of(FQN_EXPR_INTERCEPT_REG),
node.getName())) {
replacementClass = "AuthorizationManagerRequestMatcherRegistry";
}
@@ -103,14 +103,14 @@ public class AuthorizeHttpRequestsReconciler implements JdtAstReconciler {
"Use of type '" + node.getName().getFullyQualifiedName() + "' is outdated",
node.getName().getStartPosition(), node.getName().getLength());
String uri = docUri.toASCIIString();
RewriteQuickFixUtils
ReconcileUtils
.setRewriteFixes(registry, problem, List.of(
new FixDescriptor(ID, List.of(uri),
RewriteQuickFixUtils.buildLabel(String.format(CLASS_FIX_LABEL_TEMPLATE,
ReconcileUtils.buildLabel(String.format(CLASS_FIX_LABEL_TEMPLATE,
replacementClass), RecipeScope.FILE))
.withRecipeScope(RecipeScope.FILE),
new FixDescriptor(ID, List.of(uri),
RewriteQuickFixUtils.buildLabel(
ReconcileUtils.buildLabel(
String.format(CLASS_FIX_LABEL_TEMPLATE, replacementClass),
RecipeScope.PROJECT))
.withRecipeScope(RecipeScope.PROJECT)));
@@ -122,7 +122,7 @@ public class AuthorizeHttpRequestsReconciler implements JdtAstReconciler {
});
} else {
boolean needsFullAst = RewriteQuickFixUtils.isAnyTypeUsed(cu, List.of(
boolean needsFullAst = ReconcileUtils.isAnyTypeUsed(cu, List.of(
FQN_HTTP_SECURITY,
FQN_AUTH_REQ_CONFIG,
FQN_EXPR_AUTH_CONFIG,

View File

@@ -70,7 +70,7 @@ public class AutowiredFieldIntoConstructorParameterReconciler implements JdtAstR
@Override
public boolean visit(FieldDeclaration field) {
if (field.fragments().size() == 1) {
Annotation annotation = RewriteQuickFixUtils.findAnnotation(field, Annotations.AUTOWIRED,
Annotation annotation = ReconcileUtils.findAnnotation(field, Annotations.AUTOWIRED,
false);
if (annotation != null && field.getParent() instanceof TypeDeclaration) {
TypeDeclaration typeDecl = (TypeDeclaration) field.getParent();
@@ -94,7 +94,7 @@ public class AutowiredFieldIntoConstructorParameterReconciler implements JdtAstR
}
} else {
List<MethodDeclaration> autowiredConstructors = constructors.stream()
.filter(constr -> RewriteQuickFixUtils.findAnnotation(constr,
.filter(constr -> ReconcileUtils.findAnnotation(constr,
Annotations.AUTOWIRED, true) != null)
.limit(2).collect(Collectors.toList());
if (autowiredConstructors.size() == 1) {
@@ -129,9 +129,9 @@ public class AutowiredFieldIntoConstructorParameterReconciler implements JdtAstR
String typeFqName = (cu.getPackage() != null && cu.getPackage().getName() != null
? cu.getPackage().getName().getFullyQualifiedName() + "."
: "") + typeDecl.getName().getFullyQualifiedName();
RewriteQuickFixUtils.setRewriteFixes(registry, problem,
ReconcileUtils.setRewriteFixes(registry, problem,
List.of(new FixDescriptor(ID, List.of(docUri.toASCIIString()), LABEL)
.withRangeScope(RewriteQuickFixUtils.createOpenRewriteRange(cu, typeDecl))
.withRangeScope(ReconcileUtils.createOpenRewriteRange(cu, typeDecl))
.withParameters(Map.of("classFqName", typeFqName, "fieldName", fieldName))
.withRecipeScope(RecipeScope.NODE)));
return problem;

View File

@@ -40,7 +40,6 @@ import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixTy
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblemImpl;
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.FixDescriptor;
@@ -106,15 +105,15 @@ public class BeanMethodNotPublicReconciler implements JdtAstReconciler {
FixDescriptor fix1 = new FixDescriptor(ID, List.of(docUri.toASCIIString()), LABEL)
.withRecipeScope(RecipeScope.NODE)
.withRangeScope(RewriteQuickFixUtils.createOpenRewriteRange(cu, method));
.withRangeScope(ReconcileUtils.createOpenRewriteRange(cu, method));
Range methodRange = RewriteQuickFixUtils.createOpenRewriteRange(cu, method);
Range methodRange = ReconcileUtils.createOpenRewriteRange(cu, method);
fix1 = fix1.withRangeScope(methodRange);
FixDescriptor fix2 = new FixDescriptor(ID, List.of(docUri.toASCIIString()), RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.FILE))
FixDescriptor fix2 = new FixDescriptor(ID, List.of(docUri.toASCIIString()), ReconcileUtils.buildLabel(LABEL, RecipeScope.FILE))
.withRecipeScope(RecipeScope.FILE);
FixDescriptor fix3 = new FixDescriptor(ID, List.of(docUri.toASCIIString()), RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.PROJECT))
FixDescriptor fix3 = new FixDescriptor(ID, List.of(docUri.toASCIIString()), ReconcileUtils.buildLabel(LABEL, RecipeScope.PROJECT))
.withRecipeScope(RecipeScope.PROJECT);

View File

@@ -86,9 +86,9 @@ public class BeanPostProcessingIgnoreInAotReconciler implements JdtAstReconciler
if (markProblem) {
ReconcileProblemImpl problem = new ReconcileProblemImpl(getProblemType(), LABEL, typeDecl.getName().getStartPosition(), typeDecl.getName().getLength());
RewriteQuickFixUtils.setRewriteFixes(registry, problem, List.of(
new FixDescriptor(RECIPE_ID, List.of(docUri.toASCIIString()), RewriteQuickFixUtils.buildLabel(LABEL, RecipeScope.NODE))
.withRangeScope(RewriteQuickFixUtils.createOpenRewriteRange(cu, typeDecl))
ReconcileUtils.setRewriteFixes(registry, problem, List.of(
new FixDescriptor(RECIPE_ID, List.of(docUri.toASCIIString()), ReconcileUtils.buildLabel(LABEL, RecipeScope.NODE))
.withRangeScope(ReconcileUtils.createOpenRewriteRange(cu, typeDecl))
.withRecipeScope(RecipeScope.NODE)
));
problemCollector.accept(problem);
@@ -98,7 +98,7 @@ public class BeanPostProcessingIgnoreInAotReconciler implements JdtAstReconciler
}
private boolean isApplicable(ITypeBinding type) {
return RewriteQuickFixUtils.implementsType(RUNTIME_BEAN_POST_PROCESSOR, type) && RewriteQuickFixUtils.implementsType(COMPILE_BEAN_POST_PROCESSOR, type);
return ReconcileUtils.implementsType(RUNTIME_BEAN_POST_PROCESSOR, type) && ReconcileUtils.implementsType(COMPILE_BEAN_POST_PROCESSOR, type);
}
});

View File

@@ -70,15 +70,15 @@ public class NoAutowiredOnConstructorReconciler implements JdtAstReconciler {
}
if (constructor != null) {
Annotation autowiredAnnotation = RewriteQuickFixUtils.findAnnotation(constructor,
Annotation autowiredAnnotation = ReconcileUtils.findAnnotation(constructor,
Annotations.AUTOWIRED, false);
if (autowiredAnnotation != null) {
ReconcileProblemImpl problem = new ReconcileProblemImpl(getProblemType(), LABEL,
autowiredAnnotation.getStartPosition(), autowiredAnnotation.getLength());
RewriteQuickFixUtils.setRewriteFixes(registry, problem,
ReconcileUtils.setRewriteFixes(registry, problem,
List.of(new FixDescriptor(ID, List.of(docUri.toASCIIString()), LABEL)
.withRecipeScope(RecipeScope.NODE)
.withRangeScope(RewriteQuickFixUtils.createOpenRewriteRange(cu, typeDecl))));
.withRangeScope(ReconcileUtils.createOpenRewriteRange(cu, typeDecl))));
problemCollector.accept(problem);
}
}

View File

@@ -29,7 +29,6 @@ import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixRegistry;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblemImpl;
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.FixDescriptor;
@@ -62,16 +61,16 @@ public class NoRepoAnnotationReconciler implements JdtAstReconciler {
if (type != null && isRepo(type)) {
ReconcileProblemImpl problem = new ReconcileProblemImpl(getProblemType(), LABEL, a.getStartPosition(), a.getLength());
String uri = docUri.toASCIIString();
RewriteQuickFixUtils.setRewriteFixes(registry, problem, List.of(
ReconcileUtils.setRewriteFixes(registry, problem, List.of(
// new FixDescriptor(ID, List.of(uri), LABEL)
// .withRangeScope(RewriteQuickFixUtils.createOpenRewriteRange(cu, typeDecl))
// .withRecipeScope(RecipeScope.NODE),
new FixDescriptor(ID, List.of(uri),
RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.FILE))
.withRecipeScope(RecipeScope.FILE),
ReconcileUtils.buildLabel(LABEL, RecipeScope.FILE))
.withRecipeScope(RecipeScope.FILE),
new FixDescriptor(ID, List.of(uri),
RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.PROJECT))
.withRecipeScope(RecipeScope.PROJECT)
ReconcileUtils.buildLabel(LABEL, RecipeScope.PROJECT))
.withRecipeScope(RecipeScope.PROJECT)
));
problemCollector.accept(problem);
}

View File

@@ -33,7 +33,6 @@ import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixRe
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblemImpl;
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.FixDescriptor;
@@ -75,13 +74,13 @@ public class NoRequestMappingAnnotationReconciler implements JdtAstReconciler {
if (a.getParent() instanceof MethodDeclaration && isRequestMappingAnnotation(cu, a)) {
String uri = docUri.toASCIIString();
ReconcileProblemImpl problem = new ReconcileProblemImpl(getProblemType(), LABEL, a.getStartPosition(), a.getLength());
RewriteQuickFixUtils.setRewriteFixes(registry, problem, List.of(
ReconcileUtils.setRewriteFixes(registry, problem, List.of(
// new FixDescriptor(ID, List.of(uri), RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.NODE))
// .withRangeScope(RewriteQuickFixUtils.createOpenRewriteRange(cu, a))
// .withRecipeScope(RecipeScope.NODE),
new FixDescriptor(ID, List.of(uri), RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.FILE))
new FixDescriptor(ID, List.of(uri), ReconcileUtils.buildLabel(LABEL, RecipeScope.FILE))
.withRecipeScope(RecipeScope.FILE),
new FixDescriptor(ID, List.of(uri), RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.PROJECT))
new FixDescriptor(ID, List.of(uri), ReconcileUtils.buildLabel(LABEL, RecipeScope.PROJECT))
.withRecipeScope(RecipeScope.PROJECT)
));
problemCollector.accept(problem);

View File

@@ -77,7 +77,7 @@ public class NotRegisteredBeansReconciler implements JdtAstReconciler, Applicati
public boolean visit(TypeDeclaration node) {
if (!node.isInterface() && !Modifier.isAbstract(node.getModifiers())) {
ITypeBinding type = node.resolveBinding();
if (type != null && RewriteQuickFixUtils.implementsAnyType(AOT_BEANS, type)) {
if (type != null && ReconcileUtils.implementsAnyType(AOT_BEANS, type)) {
String beanClassName =type.getQualifiedName();
SpringSymbolIndex index = applicationContext.getBean(SpringSymbolIndex.class);
List<WorkspaceSymbol> beanSymbols = index.getSymbols(data -> {
@@ -135,7 +135,7 @@ public class NotRegisteredBeansReconciler implements JdtAstReconciler, Applicati
}
}
ReconcileProblemImpl problem = new ReconcileProblemImpl(getProblemType(), getProblemType().getLabel(), node.getName().getStartPosition(), node.getName().getLength());
RewriteQuickFixUtils.setRewriteFixes(registry, problem, fixListBuilder.build());
ReconcileUtils.setRewriteFixes(registry, problem, fixListBuilder.build());
problemCollector.accept(problem);
}
}
@@ -196,7 +196,7 @@ public class NotRegisteredBeansReconciler implements JdtAstReconciler, Applicati
if (type.isArray()) {
return typePattern(type.getErasure()) + "[]";
} else {
return RewriteQuickFixUtils.getDeepErasureType(type).getQualifiedName();
return ReconcileUtils.getDeepErasureType(type).getQualifiedName();
}
}

View File

@@ -34,7 +34,6 @@ import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixRe
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblemImpl;
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.FixDescriptor;
@@ -91,13 +90,13 @@ public class PreciseBeanTypeReconciler implements JdtAstReconciler {
} else if (currentReturnTypes.size() == 1 && !method.resolveBinding().getReturnType().isAssignmentCompatible(currentReturnTypes.get(0))) {
String uri = docUri.toASCIIString();
String replacementType = currentReturnTypes.get(0).getName();
RewriteQuickFixUtils.setRewriteFixes(registry, problem, List.of(
new FixDescriptor(RECIPE_ID, List.of(uri), RecipeCodeActionDescriptor.buildLabel("Replace return type with '" + replacementType + "'", RecipeScope.NODE))
ReconcileUtils.setRewriteFixes(registry, problem, List.of(
new FixDescriptor(RECIPE_ID, List.of(uri), ReconcileUtils.buildLabel("Replace return type with '" + replacementType + "'", RecipeScope.NODE))
.withRecipeScope(RecipeScope.NODE)
.withRangeScope(RewriteQuickFixUtils.createOpenRewriteRange(cu, method)),
new FixDescriptor(RECIPE_ID, List.of(uri), RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.FILE))
.withRangeScope(ReconcileUtils.createOpenRewriteRange(cu, method)),
new FixDescriptor(RECIPE_ID, List.of(uri), ReconcileUtils.buildLabel(LABEL, RecipeScope.FILE))
.withRecipeScope(RecipeScope.FILE),
new FixDescriptor(RECIPE_ID, List.of(uri), RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.PROJECT))
new FixDescriptor(RECIPE_ID, List.of(uri), ReconcileUtils.buildLabel(LABEL, RecipeScope.PROJECT))
.withRecipeScope(RecipeScope.PROJECT)
));
problemCollector.accept(problem);

View File

@@ -34,7 +34,7 @@ import org.springframework.ide.vscode.commons.languageserver.reconcile.Reconcile
import org.springframework.ide.vscode.commons.rewrite.config.RecipeScope;
import org.springframework.ide.vscode.commons.rewrite.java.FixDescriptor;
public class RewriteQuickFixUtils {
public class ReconcileUtils {
public static Range createOpenRewriteRange(CompilationUnit cu, ASTNode node) {
@@ -139,7 +139,7 @@ public class RewriteQuickFixUtils {
@Override
public boolean visit(SimpleType node) {
if (RewriteQuickFixUtils.isApplicableTypeWithoutResolving(cu, types, node.getName())) {
if (ReconcileUtils.isApplicableTypeWithoutResolving(cu, types, node.getName())) {
typeUsed.set(true);
}
return !typeUsed.get();

View File

@@ -85,8 +85,8 @@ public class UnnecessarySpringExtensionReconciler implements JdtAstReconciler {
}
if (testAnnotation != null && extendWithAnnotation != null) {
ReconcileProblemImpl problem = new ReconcileProblemImpl(getProblemType(), LABEL, extendWithAnnotation.getStartPosition(), extendWithAnnotation.getLength());
RewriteQuickFixUtils.setRewriteFixes(registry, problem, List.of(
new FixDescriptor(ID, List.of(docUri.toASCIIString()), RewriteQuickFixUtils.buildLabel(LABEL, RecipeScope.PROJECT))
ReconcileUtils.setRewriteFixes(registry, problem, List.of(
new FixDescriptor(ID, List.of(docUri.toASCIIString()), ReconcileUtils.buildLabel(LABEL, RecipeScope.PROJECT))
));
problemCollector.accept(problem);
break;

View File

@@ -30,7 +30,6 @@ import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixRe
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblemImpl;
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.FixDescriptor;
@@ -89,17 +88,17 @@ public class WebSecurityConfigurerAdapterReconciler implements JdtAstReconciler
Type type = typeDecl.getSuperclassType();
if (isWebSecurityConfigurerAdapter(cu, type)) {
ReconcileProblemImpl problem = new ReconcileProblemImpl(getProblemType(), PROBLEM_LABEL, type.getStartPosition(), type.getLength());
if (RewriteQuickFixUtils.findAnnotation(typeDecl, Annotations.CONFIGURATION, true) != null) {
if (ReconcileUtils.findAnnotation(typeDecl, Annotations.CONFIGURATION, true) != null) {
ITypeBinding resolveBinding = type.resolveBinding();
String[] typeStubs = resolveBinding == null || resolveBinding.isRecovered() ? new String[] { STUB_WEB_SECURITY_CONFIG_ADAPTER } : new String[0];
String uri = docUri.toASCIIString();
RewriteQuickFixUtils.setRewriteFixes(registry, problem, List.of(
ReconcileUtils.setRewriteFixes(registry, problem, List.of(
new FixDescriptor(ID, List.of(uri),
RecipeCodeActionDescriptor.buildLabel(FIX_LABEL, RecipeScope.FILE))
ReconcileUtils.buildLabel(FIX_LABEL, RecipeScope.FILE))
.withRecipeScope(RecipeScope.FILE)
.withTypeStubs(typeStubs),
new FixDescriptor(ID, List.of(uri),
RecipeCodeActionDescriptor.buildLabel(FIX_LABEL, RecipeScope.PROJECT))
ReconcileUtils.buildLabel(FIX_LABEL, RecipeScope.PROJECT))
.withRecipeScope(RecipeScope.PROJECT)
.withTypeStubs(typeStubs))

View File

@@ -1,60 +0,0 @@
/*******************************************************************************
* Copyright (c) 2022, 2023 VMware, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
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.AuthorizeHttpRequestsCodeAction;
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;
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.Boot3NotSupportedTypeProblem;
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.EntityIdForRepoProblem;
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.HttpSecurityLamdaDslCodeAction;
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.ModulithTypeReferenceViolation;
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.NoAutowiredOnConstructorProblem;
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.NoRepoAnnotationProblem;
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.NoRequestMappingAnnotationCodeAction;
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.NotRegisteredBeansProblem;
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.PreciseBeanTypeProblem;
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.ServerHttpSecurityLambdaDslCodeAction;
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.UnnecessarySpringExtensionProblem;
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.WebSecurityConfigurerAdapterCodeAction;
import org.springframework.ide.vscode.commons.rewrite.config.CodeActionRepository;
import org.springframework.ide.vscode.commons.rewrite.config.RecipeCodeActionDescriptor;
public class BootCodeActionRepository extends CodeActionRepository {
@Override
public List<RecipeCodeActionDescriptor> getCodeActionDescriptors() {
return List.of(
new BeanMethodNotPublicProblem(),
new NoAutowiredOnConstructorProblem(),
new UnnecessarySpringExtensionProblem(),
new PreciseBeanTypeProblem(),
new BeanPostProcessingIgnoreInAotProblem(),
new NotRegisteredBeansProblem(),
new Boot3NotSupportedTypeProblem(),
new NoRequestMappingAnnotationCodeAction(),
new AutowiredFieldIntoConstructorParameterCodeAction(),
new NoRepoAnnotationProblem(),
new HttpSecurityLamdaDslCodeAction(),
new ServerHttpSecurityLambdaDslCodeAction(),
new AddConfigurationIfBeansPresentCodeAction(),
new AuthorizeHttpRequestsCodeAction(),
new WebSecurityConfigurerAdapterCodeAction(),
new EntityIdForRepoProblem(),
new ModulithTypeReferenceViolation()
);
}
}

View File

@@ -1,333 +0,0 @@
/*******************************************************************************
* Copyright (c) 2022, 2023 VMware, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.rewrite;
import java.io.ByteArrayInputStream;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.commons.io.IOUtils;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.openrewrite.Parser.Input;
import org.openrewrite.Tree;
import org.openrewrite.java.JavaParser;
import org.openrewrite.java.marker.JavaSourceSet;
import org.openrewrite.java.tree.J.CompilationUnit;
import org.openrewrite.java.tree.JavaType;
import org.openrewrite.java.tree.JavaType.FullyQualified;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.java.utils.DocumentContentProvider;
import org.springframework.ide.vscode.boot.java.utils.ServerUtils;
import org.springframework.ide.vscode.commons.java.IClasspathUtil;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
import org.springframework.ide.vscode.commons.rewrite.java.ORAstUtils;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader.InvalidCacheLoadException;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;
import com.google.common.util.concurrent.UncheckedExecutionException;
import reactor.core.Disposable;
public class RewriteCompilationUnitCache implements DocumentContentProvider, Disposable {
private static final Logger logger = LoggerFactory.getLogger(RewriteCompilationUnitCache.class);
private static final long CU_ACCESS_EXPIRATION = 1;
// private JavaProjectFinder projectFinder;
private ProjectObserver projectObserver;
private final ProjectObserver.Listener projectListener;
private final SimpleTextDocumentService documentService;
private final Cache<URI, CompletableFuture<CompilationUnit>> uriToCu;
private final Cache<URI, Set<URI>> projectToDocs;
private final Cache<URI, JavaParser> javaParsers;
private final Cache<URI, List<JavaType.FullyQualified>> sourceSetClasspath;
public RewriteCompilationUnitCache(JavaProjectFinder projectFinder, SimpleLanguageServer server, ProjectObserver projectObserver) {
// this.projectFinder = projectFinder;
this.projectObserver = projectObserver;
// PT 154618835 - Avoid retaining the CU in the cache as it consumes memory if it hasn't been
// accessed after some time
this.uriToCu = CacheBuilder.newBuilder()
.maximumSize(100)
.expireAfterAccess(CU_ACCESS_EXPIRATION, TimeUnit.MINUTES)
.removalListener(new RemovalListener<URI, CompletableFuture<CompilationUnit>>() {
@Override
public void onRemoval(RemovalNotification<URI, CompletableFuture<CompilationUnit>> notification) {
URI uri = notification.getKey();
CompletableFuture<CompilationUnit> future = notification.getValue();
if (future != null) {
if (!future.isDone() && !future.isCancelled()) {
future.cancel(true);
}
Optional<IJavaProject> project = projectFinder.find(new TextDocumentIdentifier(uri.toASCIIString()));
if (project.isPresent()) {
JavaParser parser = javaParsers.getIfPresent(project.get().getLocationUri());
if (parser != null) {
// if (future.isDone()) {
// try {
// CompilationUnit cu = future.get();
// if (cu != null) {
// parser.resetCUs(List.of(cu));
// return;
// }
// } catch (Throwable t) {
// logger.error("", t);
// }
// }
// parser.reset(List.of(uri));
parser.reset();
}
}
}
}
})
.build();
this.projectToDocs = CacheBuilder.newBuilder().build();
this.javaParsers = CacheBuilder.newBuilder()
.removalListener(new RemovalListener<URI, JavaParser>() {
@Override
public void onRemoval(RemovalNotification<URI, JavaParser> notification) {
logger.info("CU Cache: invalidate project {}", notification.getKey());
sourceSetClasspath.invalidate(notification.getKey());
}
})
.build();
this.sourceSetClasspath = CacheBuilder.newBuilder().build();
this.documentService = server == null ? null : server.getTextDocumentService();
// IMPORTANT ===> these notifications arrive within the lsp message loop, so reactions to them have to be fast
// and not be blocked by waiting for anything
if (this.documentService != null) {
this.documentService.onDidChangeContent(doc -> invalidateCuForJavaFile(doc.getDocument().getId().getUri()));
this.documentService.onDidClose(doc -> invalidateCuForJavaFile(doc.getId().getUri()));
}
// if (this.projectFinder != null) {
// for (IJavaProject project : this.projectFinder.all()) {
// logger.info("CU Cache: initial lookup env creation for project <{}>", project.getElementName());
// loadJavaParser(project);
// }
// }
this.projectListener = new ProjectObserver.Listener() {
@Override
public void deleted(IJavaProject project) {
logger.debug("CU Cache: deleted project {}", project.getElementName());
invalidateProject(project);
}
@Override
public void created(IJavaProject project) {
logger.debug("CU Cache: created project {}", project.getElementName());
invalidateProject(project);
// loadJavaParser(project);
}
@Override
public void changed(IJavaProject project) {
logger.debug("CU Cache: changed project {}", project.getElementName());
invalidateProject(project);
// Load the new cache the value right away
// loadJavaParser(project);
}
};
if (this.projectObserver != null) {
this.projectObserver.addListener(this.projectListener);
}
if (server != null) {
ServerUtils.listenToClassFileChanges(server.getWorkspaceService().getFileObserver(), projectFinder, this::invalidateProject);
}
}
public void dispose() {
if (this.projectObserver != null) {
this.projectObserver.removeListener(this.projectListener);
}
}
private JavaParser loadJavaParser(IJavaProject project) {
try {
return javaParsers.get(project.getLocationUri(), () -> ORAstUtils.createJavaParser(project));
} catch (ExecutionException e) {
logger.error("{}", e);
return null;
}
}
private void invalidateCuForJavaFile(String uriStr) {
URI uri = URI.create(uriStr);
uriToCu.invalidate(uri);
}
private void invalidateProject(IJavaProject project) {
Set<URI> docUris = projectToDocs.getIfPresent(project.getLocationUri());
if (docUris != null) {
uriToCu.invalidateAll(docUris);
projectToDocs.invalidate(project.getLocationUri());
}
javaParsers.invalidate(project.getLocationUri());
}
@Override
public String fetchContent(URI uri) throws Exception {
if (documentService != null) {
TextDocument document = documentService.getLatestSnapshot(uri.toASCIIString());
if (document != null) {
return document.get();
}
}
return IOUtils.toString(uri);
}
public CompilationUnit getCU(IJavaProject project, URI uri) {
try {
if (project != null) {
try {
return uriToCu.get(uri, () -> {
CompletableFuture<CompilationUnit> future = CompletableFuture.supplyAsync(() -> {
try {
return doParse(project, uri);
} catch (Exception e) {
return null;
}
});
return future;
}).get();
} catch (UncheckedExecutionException e1) {
// ignore errors from rewrite parser. There could be many parser exceptions due to
// user incrementally typing code's text
return null;
} catch (InvalidCacheLoadException | CancellationException e) {
// ignore
} catch (Exception e) {
logger.error("", e);
return null;
}
}
} catch (Exception e) {
logger.error("Failed to parse {}", uri, e);
}
return null;
}
private CompilationUnit doParse(IJavaProject project, URI uri) throws Exception {
boolean newParser = javaParsers.getIfPresent(project.getLocationUri()) == null;
JavaParser javaParser = null;
try {
logger.debug("Parsing CU {}", uri);
javaParser = loadJavaParser(project);
Path sourcePath = Paths.get(uri);
Input input = new Input(sourcePath, () -> {
try {
return new ByteArrayInputStream(fetchContent(uri).getBytes());
} catch (Exception e) {
throw new IllegalStateException("Unexpected error fetching document content");
}
});
List<CompilationUnit> cus = ORAstUtils.parseInputs(javaParser, List.of(input), null);
CompilationUnit cu = cus.get(0);
// Manually add source set
JavaSourceSet sourceSet = createSourceSet(project, ORAstUtils.getSourceSetName(project, sourcePath));
cu = cu.withMarkers(cu.getMarkers().computeByType(sourceSet, (original, updated) -> updated));
if (cu != null) {
projectToDocs.get(project.getLocationUri(), () -> new HashSet<>()).add(uri);
return cu;
} else {
throw new IllegalStateException("Failed to parse Java source");
}
} catch (Exception e) {
if (newParser) {
javaParsers.invalidate(project);
}
throw e;
} finally {
if (javaParser != null) {
javaParser.reset(Collections.emptyList());
}
}
}
private JavaSourceSet createSourceSet(IJavaProject project, String name) {
List<FullyQualified> fqNames;
try {
fqNames = sourceSetClasspath.get(project.getLocationUri(), () -> {
List<Path> classpath = IClasspathUtil.getAllBinaryRoots(project.getClasspath()).stream().map(f -> f.toPath()).collect(Collectors.toList());
return JavaSourceSet.build("", classpath, null, false).getClasspath();
});
} catch (ExecutionException e) {
logger.error("", e);
fqNames = Collections.emptyList();
}
return new JavaSourceSet(Tree.randomId(), name, fqNames);
}
/**
* Does not need to be via callback - kept the same in order to keep the same API to replace JDT with Rewrite in distant future
*/
public <T> T withCompilationUnit(IJavaProject project, URI uri, Function<CompilationUnit, T> requestor) {
logger.info("CU Cache: work item submitted for doc {}", uri.toASCIIString());
CompilationUnit cu = getCU(project, uri);
if (cu != null) {
try {
logger.info("CU Cache: start work on AST for {}", uri.toASCIIString());
return requestor.apply(cu);
} catch (CancellationException e) {
throw e;
} catch (Exception e) {
logger.error("", e);
} finally {
logger.info("CU Cache: end work on AST for {}", uri.toASCIIString());
}
}
return requestor.apply(null);
}
}

View File

@@ -17,6 +17,7 @@ import java.net.URLClassLoader;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -43,6 +44,7 @@ import org.openrewrite.Result;
import org.openrewrite.SourceFile;
import org.openrewrite.Validated;
import org.openrewrite.config.DeclarativeRecipe;
import org.openrewrite.config.Environment;
import org.openrewrite.config.RecipeDescriptor;
import org.openrewrite.config.YamlResourceLoader;
import org.openrewrite.internal.InMemoryLargeSourceSet;
@@ -60,7 +62,6 @@ import org.springframework.ide.vscode.commons.protocol.java.ProjectBuild;
import org.springframework.ide.vscode.commons.rewrite.LoadUtils;
import org.springframework.ide.vscode.commons.rewrite.LoadUtils.DurationTypeConverter;
import org.springframework.ide.vscode.commons.rewrite.ORDocUtils;
import org.springframework.ide.vscode.commons.rewrite.config.StsEnvironment;
import org.springframework.ide.vscode.commons.rewrite.gradle.GradleIJavaProjectParser;
import org.springframework.ide.vscode.commons.rewrite.java.ProjectParser;
import org.springframework.ide.vscode.commons.rewrite.maven.MavenIJavaProjectParser;
@@ -152,7 +153,7 @@ public class RewriteRecipeRepository {
try {
log.info("Loading Rewrite Recipes...");
Recipe xmlbindRecipe = null;
StsEnvironment env = createRewriteEnvironment();
Environment env = createRewriteEnvironment();
for (Recipe r : env.listRecipes()) {
if (r.getName() != null) {
if ("org.openrewrite.java.migrate.jakarta.JavaxXmlBindMigrationToJakartaXmlBind".equals(r.getName())) {
@@ -209,7 +210,7 @@ public class RewriteRecipeRepository {
}
private static boolean isRecipeValid(Recipe r) {
Validated validation = Validated.invalid(null, null, null);
Validated<?> validation = Validated.invalid(null, null, null);
try {
validation = r.validate();
} catch (Exception e) {
@@ -218,8 +219,8 @@ public class RewriteRecipeRepository {
return validation.isValid();
}
private StsEnvironment createRewriteEnvironment() {
StsEnvironment.Builder builder = StsEnvironment.builder().scanRuntimeClasspath();
private Environment createRewriteEnvironment() {
Environment.Builder builder = Environment.builder().scanRuntimeClasspath();
for (String p : scanFiles) {
try {
Path f = Path.of(p);
@@ -227,7 +228,7 @@ public class RewriteRecipeRepository {
if (pathStr.endsWith(".jar")) {
URLClassLoader classLoader = new URLClassLoader(new URL[] { f.toUri().toURL() },
getClass().getClassLoader());
builder.scanJar(f, classLoader);
builder.scanJar(f, new ArrayList<>(), classLoader);
} else if (pathStr.endsWith(".yml") || pathStr.endsWith(".yaml")) {
builder.load(new YamlResourceLoader(new FileInputStream(f.toFile()), f.toUri(), new Properties()));
}

View File

@@ -1,349 +0,0 @@
/*******************************************************************************
* Copyright (c) 2022, 2023 VMware, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.rewrite;
import java.io.ByteArrayInputStream;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.openrewrite.ExecutionContext;
import org.openrewrite.InMemoryExecutionContext;
import org.openrewrite.Parser;
import org.openrewrite.Tree;
import org.openrewrite.internal.ListUtils;
import org.openrewrite.java.JavaParser;
import org.openrewrite.java.marker.JavaSourceSet;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.J.CompilationUnit;
import org.openrewrite.marker.Marker;
import org.openrewrite.marker.Range;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.app.BootJavaConfig;
import org.springframework.ide.vscode.boot.java.reconcilers.JavaReconciler;
import org.springframework.ide.vscode.commons.java.IClasspathUtil;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.java.SpringProjectUtil;
import org.springframework.ide.vscode.commons.languageserver.quickfix.Quickfix.QuickfixData;
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixRegistry;
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixType;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblem;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblemImpl;
import org.springframework.ide.vscode.commons.rewrite.config.RecipeCodeActionDescriptor;
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;
import org.springframework.ide.vscode.commons.rewrite.java.ORAstUtils;
import org.springframework.ide.vscode.commons.rewrite.java.ProjectParser;
import org.springframework.ide.vscode.commons.util.text.IDocument;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
public class RewriteReconciler implements JavaReconciler {
private static final Logger log = LoggerFactory.getLogger(RewriteReconciler.class);
private RewriteCompilationUnitCache cuCache;
private QuickfixRegistry quickfixRegistry;
private RewriteRecipeRepository recipeRepo;
private BootJavaConfig config;
public RewriteReconciler(RewriteRecipeRepository recipeRepo, RewriteCompilationUnitCache cuCache, QuickfixRegistry quickfixRegistry, BootJavaConfig config) {
this.recipeRepo = recipeRepo;
this.cuCache = cuCache;
this.quickfixRegistry = quickfixRegistry;
this.config = config;
}
@Override
public void reconcile(IJavaProject project, IDocument doc, IProblemCollector problemCollector) {
// if (!config.isRewriteReconcileEnabled()) {
// return;
// }
//
// long start = System.currentTimeMillis();
//
// try {
// problemCollector.beginCollecting();
//
// List<RecipeCodeActionDescriptor> descriptors = getProblemRecipeDescriptors(project);
//
// if (!descriptors.isEmpty()) {
// CompilationUnit cu = cuCache.getCU(project, URI.create(doc.getUri()));
// if (cu != null) {
// collectProblems(project, descriptors, doc, cu, problemCollector::accept);
// }
// }
// } catch (Exception e) {
// if (ORAstUtils.isExceptionFromInterrupedThread(e)) {
// log.debug("", e);
// } else {
// log.error("", e);
// }
// } finally {
// problemCollector.endCollecting();
// log.info("reconciling (OpenRewrite): " + doc.getUri() + " done in " + (System.currentTimeMillis() - start) + "ms");
// }
}
// private List<ReconcileProblem> createProblems(IDocument doc, FixAssistMarker m, J astNode) {
// if (astNode != null) {
// Range range = astNode.getMarkers().findFirst(Range.class).orElse(null);
// if (range != null) {
// RecipeCodeActionDescriptor recipeFixDescriptor = recipeRepo.getCodeActionRecipeDescriptor(m.getDescriptorId());
// if (recipeFixDescriptor != null) {
// return List.of(createProblem(doc, recipeFixDescriptor, m, range));
// }
// }
// }
// return Collections.emptyList();
// }
//
// private ReconcileProblemImpl createProblem(IDocument doc, RecipeCodeActionDescriptor recipeFixDescriptor,
// FixAssistMarker m, Range range) {
// ProblemType problemType = recipeFixDescriptor.getProblemType();
// 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()) {
// if (recipeRepo.getRecipe(f.getRecipeId()).isPresent()) {
// problem.addQuickfix(new QuickfixData<>(
// quickfixType,
// f,
// f.getLabel()
// ));
// }
// }
// }
// return problem;
// }
@Override
public Map<IDocument, Collection<ReconcileProblem>> reconcile(IJavaProject project, List<TextDocument> docs, Runnable incrementProgress) {
// if (!config.isJavaSourceReconcileEnabled()) {
// return Collections.emptyMap();
// }
//
// long start = System.currentTimeMillis();
//
// Map<IDocument, Collection<ReconcileProblem>> allProblems = new HashMap<>();
// List<Path> testSourceFolders = IClasspathUtil.getProjectTestJavaSources(project.getClasspath()).map(f -> f.toPath()).collect(Collectors.toList());
// List<TextDocument> testSources = new ArrayList<>(docs.size());
// List<TextDocument> mainSources = new ArrayList<>(docs.size());
// for (TextDocument d : docs) {
// Path p = Paths.get(URI.create(d.getUri()));
// if (testSourceFolders.stream().anyMatch(t -> p.startsWith(t))) {
// testSources.add(d);
// } else {
// mainSources.add(d);
// }
// }
//
// List<Path> classpath = IClasspathUtil.getAllBinaryRoots(project.getClasspath()).stream().map(f -> f.toPath()).collect(Collectors.toList());
// JavaParser javaParser = ORAstUtils.createJavaParser(() -> JavaParser.fromJavaVersion().classpath(classpath));
//
// // Pass in source sets created from classpath. (Perhaps it is a good idea to have separate classpath and parsers for test and main, TBD)
// // Perhaps it is even better to create empty classpath java source sets as reconcile step seem to only need name of the java source set
// // Usually java source set classpath is required to figure out how to organize imports for sources
// JavaSourceSet mainJavaSourceSet = JavaSourceSet.build(ProjectParser.MAIN, classpath, null, false);
// JavaSourceSet testJavaSourceSet = new JavaSourceSet(Tree.randomId(), ProjectParser.TEST, mainJavaSourceSet.getClasspath());
// allProblems.putAll(doReconcile(project, mainSources, javaParser, mainJavaSourceSet, incrementProgress));
// allProblems.putAll(doReconcile(project, testSources, javaParser, testJavaSourceSet, incrementProgress));
//
// long end = System.currentTimeMillis();
// log.info("reconciling project (OpenRewrite): " + project.getElementName() + " - " + docs.size() + " done in " + (end - start) + "ms");
//
// return allProblems;
return Collections.emptyMap();
}
// Parse all at once
// private Map<IDocument, Collection<ReconcileProblem>> doReconcile(IJavaProject project, List<TextDocument> docs,
// Function<TextDocument, IProblemCollector> problemCollectorFactory, JavaParser javaParser) {
// Map<IDocument, Collection<ReconcileProblem>> allProblems = new HashMap<>();
//
// if (javaParser != null && config.isRewriteReconcileEnabled()) {
// try {
// List<RecipeCodeActionDescriptor> descriptors = getProblemRecipeDescriptors(project);
//
// List<CompilationUnit> cus = ORAstUtils.parseInputs(javaParser,
// docs.stream().map(d -> new Parser.Input(Paths.get(URI.create(d.getUri())), () -> {
// return new ByteArrayInputStream(d.get().getBytes());
// })).collect(Collectors.toList()));
//
// if (!descriptors.isEmpty()) {
//
// for (int i = 0; i < cus.size(); i++) {
// final IDocument doc = docs.get(i);
// List<ReconcileProblem> problems = new ArrayList<>();
// collectProblems(descriptors, doc, cus.get(i), problems::add);
// if (!problems.isEmpty()) {
// allProblems.put(doc, problems);
// }
// }
// }
// } catch (Exception e) {
// if (ORAstUtils.isExceptionFromInterrupedThread(e)) {
// log.debug("", e);
// } else {
// log.error("", e);
// }
// }
// }
// return allProblems;
// }
// Parse One-by-one and share the parser
// private Map<IDocument, Collection<ReconcileProblem>> doReconcile(IJavaProject project, List<TextDocument> docs,
// Function<TextDocument, IProblemCollector> problemCollectorFactory, JavaParser javaParser) {
// Map<IDocument, Collection<ReconcileProblem>> allProblems = new HashMap<>();
//
// if (javaParser != null && config.isRewriteReconcileEnabled()) {
// try {
// List<RecipeCodeActionDescriptor> descriptors = getProblemRecipeDescriptors(project);
//
// if (!descriptors.isEmpty()) {
//
// for (IDocument doc : docs) {
// List<ReconcileProblem> problems = new ArrayList<>();
// CompilationUnit source = ORAstUtils.parseInputs(javaParser, List.of(new Parser.Input(Paths.get(URI.create(doc.getUri())), () -> {
// return new ByteArrayInputStream(doc.get().getBytes());
// }))).get(0);
// collectProblems(descriptors, doc, source, problems::add);
// if (!problems.isEmpty()) {
// allProblems.put(doc, problems);
// }
// }
// }
// } catch (Exception e) {
// if (ORAstUtils.isExceptionFromInterrupedThread(e)) {
// log.debug("", e);
// } else {
// log.error("", e);
// }
// }
// }
// return allProblems;
// }
private static final int BATCH = 50;
// Parse in batches and share the parser
// private Map<IDocument, Collection<ReconcileProblem>> doReconcile(IJavaProject project, List<TextDocument> docs, JavaParser javaParser, JavaSourceSet javaSourceSet, Runnable incrementProgress) {
// Map<IDocument, Collection<ReconcileProblem>> allProblems = new HashMap<>();
// if (javaParser != null && config.isJavaSourceReconcileEnabled()) {
// try {
// List<RecipeCodeActionDescriptor> descriptors = getProblemRecipeDescriptors(project);
//
//
// if (!descriptors.isEmpty()) {
//
// for (int i = 0; i < docs.size(); i += BATCH) {
// List<TextDocument> batchList = docs.subList(i, Math.min(i + BATCH, docs.size()));
//
// List<CompilationUnit> cus = ORAstUtils.parseInputs(javaParser,
// batchList.stream().map(d -> new Parser.Input(Paths.get(URI.create(d.getUri())), () -> {
// return new ByteArrayInputStream(d.get().getBytes());
// })).collect(Collectors.toList()), source -> incrementProgress.run());
//
// cus = ListUtils.map(cus, cu -> cu.withMarkers(cu.getMarkers().computeByType(javaSourceSet, (original, updated) -> updated)));
//
// /*
// * If exception occurs during parsing inputs the list of inputs would become shorter than the list of corresponding documents
// */
//
// for (int j = 0, k = 0; j < batchList.size() && k < cus.size(); j++) {
// final IDocument doc = batchList.get(j);
// List<ReconcileProblem> problems = new ArrayList<>();
// CompilationUnit cu = cus.get(k);
// Path sourcePath = Paths.get(URI.create(doc.getUri()));
// if (cu.getSourcePath().equals(sourcePath)) {
// k++;
// collectProblems(project, descriptors, doc, cu, problems::add);
// if (!problems.isEmpty()) {
// allProblems.put(doc, problems);
// }
// } else {
// log.warn("(OpenRewrite) Failed to parse source for " + sourcePath);
// }
// incrementProgress.run();
// }
//
// }
// }
// } catch (Exception e) {
// if (ORAstUtils.isExceptionFromInterrupedThread(e)) {
// log.debug("", e);
// } else {
// log.error("", e);
// }
// }
// }
// return allProblems;
// }
//
// private List<RecipeCodeActionDescriptor> getProblemRecipeDescriptors(IJavaProject project)
// throws InterruptedException, ExecutionException {
// return recipeRepo.getProblemRecipeDescriptors().stream().filter(d -> d.getProblemType() != null).filter(d -> {
// switch (config.getProblemApplicability(d.getProblemType())) {
// case ON:
// return SpringProjectUtil.isBootProject(project);
// case OFF:
// return false;
// default: // AUTO
// return d.isApplicable(project);
// }
// }).collect(Collectors.toList());
// }
//
// private void collectProblems(IJavaProject project, List<RecipeCodeActionDescriptor> descriptors, IDocument doc, CompilationUnit compilationUnit, Consumer<ReconcileProblem> problemHandler) {
// CompilationUnit cu = recipeRepo.mark(project, descriptors, compilationUnit);
// if (compilationUnit != cu) {
// new JavaMarkerVisitor<ExecutionContext>() {
//
// @Override
// public J visit(Tree tree, ExecutionContext context) {
// J t = super.visit(tree, context);
// if (t instanceof J) {
// for (Marker m : t.getMarkers().entries()) {
// if (m instanceof FixAssistMarker) {
// for (ReconcileProblem problem : createProblems(doc, (FixAssistMarker) m, t)) {
// problemHandler.accept(problem);
// }
// }
// }
// }
// return t;
// }
//
// }.visit(cu, new InMemoryExecutionContext(e -> log.error("", e)));
// }
// }
//
// public int getTotalWorkUnits(List<TextDocument> docs) {
// return docs.size() * 2;
// }
}

View File

@@ -1,95 +0,0 @@
/*******************************************************************************
* 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.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.MarkerVisitorContext;
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 = AddConfigurationAnnotationIfBeansPresent.class.getName();
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<ExecutionContext> getMarkerVisitor(MarkerVisitorContext context) {
return new JavaMarkerVisitor<ExecutionContext>() {
@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;
}
}

View File

@@ -1,129 +0,0 @@
/*******************************************************************************
* 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.MethodMatcher;
import org.openrewrite.java.spring.boot2.AuthorizeHttpRequests;
import org.openrewrite.java.tree.J.MethodInvocation;
import org.openrewrite.java.tree.J.VariableDeclarations;
import org.openrewrite.java.tree.JavaType.FullyQualified;
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.MarkerVisitorContext;
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 AuthorizeHttpRequestsCodeAction implements RecipeCodeActionDescriptor {
private static final String ID = AuthorizeHttpRequests.class.getName();
private static final MethodMatcher MATCH_AUTHORIZE_REQUESTS = new MethodMatcher(
"org.springframework.security.config.annotation.web.builders.HttpSecurity 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 CLASS_FIX_LABEL_TEMPLATE = "Replace with %s and use 'HttpSecurity.authorizeHttpRequests(...) and related types";
@Override
public String getId() {
return ID;
}
@Override
public ProblemType getProblemType() {
return Boot2JavaProblemType.HTTP_SECURITY_AUTHORIZE_HTTP_REQUESTS;
}
@Override
public JavaVisitor<ExecutionContext> getMarkerVisitor(MarkerVisitorContext context) {
return new JavaMarkerVisitor<>() {
@Override
public MethodInvocation visitMethodInvocation(MethodInvocation method, ExecutionContext p) {
MethodInvocation m = super.visitMethodInvocation(method, p);
if (MATCH_AUTHORIZE_REQUESTS.matches(method)) {
String uri = getCursor().firstEnclosing(SourceFile.class).getSourcePath().toUri().toASCIIString();
FixAssistMarker marker = new FixAssistMarker(Tree.randomId(), getId())
.withLabel(AUTHORIZE_REQUESTS_PROBLEM_LABEL).withFixes(
new FixDescriptor(ID, List.of(uri),
RecipeCodeActionDescriptor.buildLabel(AUTHORIZE_REQUESTS_FIX_LABEL,
RecipeScope.FILE))
.withRecipeScope(RecipeScope.FILE),
new FixDescriptor(ID, List.of(uri), RecipeCodeActionDescriptor
.buildLabel(AUTHORIZE_REQUESTS_FIX_LABEL, RecipeScope.PROJECT))
.withRecipeScope(RecipeScope.PROJECT));
m = m.withName(m.getName().withMarkers(m.getName().getMarkers().add(marker)));
}
return m;
}
@Override
public VariableDeclarations visitVariableDeclarations(VariableDeclarations multiVariable,
ExecutionContext p) {
VariableDeclarations mv = super.visitVariableDeclarations(multiVariable, p);
FullyQualified type = mv.getTypeAsFullyQualified();
if (type != null) {
String replacementClass = null;
switch (type.getFullyQualifiedName()) {
case "org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer":
case "org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer":
replacementClass = "AuthorizeHttpRequestsConfigurer";
break;
case "org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer$ExpressionInterceptUrlRegistry":
replacementClass = "AuthorizationManagerRequestMatcherRegistry";
}
if (replacementClass != null) {
String uri = getCursor().firstEnclosing(SourceFile.class).getSourcePath().toUri()
.toASCIIString();
FixAssistMarker marker = new FixAssistMarker(Tree.randomId(), getId())
.withLabel("Use of type '" + type.getClassName() + "' is outdated").withFixes(
new FixDescriptor(ID, List.of(uri),
RecipeCodeActionDescriptor.buildLabel(
String.format(CLASS_FIX_LABEL_TEMPLATE, replacementClass),
RecipeScope.FILE))
.withRecipeScope(RecipeScope.FILE),
new FixDescriptor(ID, List.of(uri),
RecipeCodeActionDescriptor.buildLabel(
String.format(CLASS_FIX_LABEL_TEMPLATE, replacementClass),
RecipeScope.PROJECT))
.withRecipeScope(RecipeScope.PROJECT));
mv = mv.withTypeExpression(
mv.getTypeExpression().withMarkers(mv.getTypeExpression().getMarkers().add(marker)));
}
}
return mv;
}
};
}
@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;
}
}

View File

@@ -1,130 +0,0 @@
/*******************************************************************************
* Copyright (c) 2022, 2023 VMware, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* 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 java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import org.openrewrite.Cursor;
import org.openrewrite.ExecutionContext;
import org.openrewrite.SourceFile;
import org.openrewrite.Tree;
import org.openrewrite.java.JavaVisitor;
import org.openrewrite.java.marker.JavaSourceSet;
import org.openrewrite.java.spring.AutowiredFieldIntoConstructorParameterVisitor;
import org.openrewrite.java.tree.J.Block;
import org.openrewrite.java.tree.J.ClassDeclaration;
import org.openrewrite.java.tree.J.CompilationUnit;
import org.openrewrite.java.tree.J.MethodDeclaration;
import org.openrewrite.java.tree.J.VariableDeclarations;
import org.openrewrite.java.tree.JavaType.FullyQualified;
import org.openrewrite.java.tree.TypeUtils;
import org.openrewrite.marker.Range;
import org.springframework.ide.vscode.boot.java.Boot2JavaProblemType;
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.MarkerVisitorContext;
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.AnnotationHierarchies;
import org.springframework.ide.vscode.commons.rewrite.java.ConvertAutowiredFieldIntoConstructorParameter;
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;
import org.springframework.ide.vscode.commons.rewrite.java.ORAstUtils;
import org.springframework.ide.vscode.commons.rewrite.java.ProjectParser;
public class AutowiredFieldIntoConstructorParameterCodeAction implements RecipeCodeActionDescriptor {
private static final String LABEL = "Convert @Autowired field into Constructor Parameter";
private static final String ID = ConvertAutowiredFieldIntoConstructorParameter.class.getName();
private static final String AUTOWIRED = "org.springframework.beans.factory.annotation.Autowired";
@Override
public JavaVisitor<ExecutionContext> getMarkerVisitor(MarkerVisitorContext context) {
return new JavaMarkerVisitor<>() {
@Override
public CompilationUnit visitCompilationUnit(CompilationUnit cu, ExecutionContext p) {
JavaSourceSet sourceSet = cu.getMarkers().findFirst(JavaSourceSet.class).orElse(null);
if (sourceSet != null && ProjectParser.TEST.equals(sourceSet.getName())) {
return cu;
}
return super.visitCompilationUnit(cu, p);
}
@Override
public VariableDeclarations visitVariableDeclarations(VariableDeclarations multiVariable,
ExecutionContext p) {
VariableDeclarations m = super.visitVariableDeclarations(multiVariable, p);
Cursor blockCursor = getCursor().dropParentUntil(Block.class::isInstance);
if (multiVariable.getVariables().size() == 1
&& multiVariable.getLeadingAnnotations().stream().anyMatch(a -> TypeUtils.isOfClassType(a.getType(), AUTOWIRED))
&& blockCursor.getParent().getValue() instanceof ClassDeclaration) {
ClassDeclaration classDeclaration = (ClassDeclaration) blockCursor.getParent().getValue();
FullyQualified fqType = TypeUtils.asFullyQualified(classDeclaration.getType());
if (fqType != null && isApplicableType(fqType)) {
List<MethodDeclaration> constructors = ORAstUtils.getMethods(classDeclaration).stream().filter(c -> c.isConstructor()).limit(2).collect(Collectors.toList());
String fieldName = multiVariable.getVariables().get(0).getSimpleName();
String uri = getCursor().firstEnclosing(SourceFile.class).getSourcePath().toUri().toASCIIString();
FixAssistMarker marker = new FixAssistMarker(Tree.randomId(), getId())
.withFix(
new FixDescriptor(ID, List.of(uri), LABEL)
.withRangeScope(classDeclaration.getMarkers().findFirst(Range.class).get())
.withParameters(Map.of("classFqName", fqType.getFullyQualifiedName(), "fieldName", fieldName))
.withRecipeScope(RecipeScope.NODE)
);
if (constructors.size() == 0) {
m = m.withMarkers(m.getMarkers().add(marker));
} else if (constructors.size() == 1 && AutowiredFieldIntoConstructorParameterVisitor.isNotConstructorInitializingField(constructors.get(0), fieldName)) {
m = m.withMarkers(m.getMarkers().add(marker));
} else {
List<MethodDeclaration> autowiredConstructors = constructors.stream().filter(constr -> constr.getLeadingAnnotations().stream()
.map(a -> TypeUtils.asFullyQualified(a.getType()))
.filter(Objects::nonNull)
.map(FullyQualified::getFullyQualifiedName)
.anyMatch(AUTOWIRED::equals)
)
.limit(2)
.collect(Collectors.toList());
if (autowiredConstructors.size() == 1 && AutowiredFieldIntoConstructorParameterVisitor.isNotConstructorInitializingField(autowiredConstructors.get(0), fieldName)) {
m = m.withMarkers(m.getMarkers().add(marker));
}
}
}
}
return m;
}
private boolean isApplicableType(FullyQualified type) {
return !AnnotationHierarchies
.getTransitiveSuperAnnotations(type, fq -> fq.getFullyQualifiedName().startsWith("java."))
.contains("org.springframework.boot.test.context.SpringBootTest");
}
};
}
@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,89 +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.java.rewrite.reconcile;
import java.util.List;
import org.openrewrite.ExecutionContext;
import org.openrewrite.SourceFile;
import org.openrewrite.Tree;
import org.openrewrite.internal.ListUtils;
import org.openrewrite.java.AnnotationMatcher;
import org.openrewrite.java.JavaVisitor;
import org.openrewrite.java.spring.BeanMethodsNotPublic;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.TypeUtils;
import org.openrewrite.marker.Range;
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.rewrite.config.MarkerVisitorContext;
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 BeanMethodNotPublicProblem implements RecipeCodeActionDescriptor {
private static final String ID = BeanMethodsNotPublic.class.getName();
private static final String LABEL = "Remove 'public' from @Bean method";
private static final AnnotationMatcher BEAN_ANNOTATION_MATCHER = new AnnotationMatcher("@org.springframework.context.annotation.Bean");
@Override
public JavaVisitor<ExecutionContext> getMarkerVisitor(MarkerVisitorContext context) {
return new JavaMarkerVisitor<ExecutionContext>() {
@Override
public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, ExecutionContext executionContext) {
J.MethodDeclaration m = super.visitMethodDeclaration(method, executionContext);
if (m.getAllAnnotations().stream().anyMatch(BEAN_ANNOTATION_MATCHER::matches)
&& Boolean.FALSE.equals(TypeUtils.isOverride(method.getMethodType()))) {
// mark public modifier
String uri = getCursor().firstEnclosing(SourceFile.class).getSourcePath().toUri().toASCIIString();
FixAssistMarker fixAssistMarker = new FixAssistMarker(Tree.randomId(), getId())
.withFixes(
new FixDescriptor(ID, List.of(uri), LABEL)
.withRangeScope(m.getMarkers().findFirst(Range.class).get())
.withRecipeScope(RecipeScope.NODE),
new FixDescriptor(ID, List.of(uri), RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.FILE))
.withRecipeScope(RecipeScope.FILE),
new FixDescriptor(ID, List.of(uri), RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.PROJECT))
.withRecipeScope(RecipeScope.PROJECT)
);
m = m.withModifiers(ListUtils.map(m.getModifiers(), modifier -> {
if (modifier.getType() == J.Modifier.Type.Public) {
return modifier.withMarkers(modifier.getMarkers().add(fixAssistMarker));
}
return modifier;
}));
}
return m;
}
};
}
@Override
public boolean isApplicable(IJavaProject project) {
return SpringProjectUtil.getDependencyVersion(project, SpringProjectUtil.SPRING_BOOT) != null;
}
@Override
public Boot2JavaProblemType getProblemType() {
return Boot2JavaProblemType.JAVA_PUBLIC_BEAN_METHOD;
}
}

View File

@@ -1,87 +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.java.rewrite.reconcile;
import static org.springframework.ide.vscode.commons.java.SpringProjectUtil.springBootVersionGreaterOrEqual;
import java.util.List;
import java.util.stream.Collectors;
import org.openrewrite.ExecutionContext;
import org.openrewrite.SourceFile;
import org.openrewrite.Tree;
import org.openrewrite.java.JavaVisitor;
import org.openrewrite.java.tree.J.ClassDeclaration;
import org.openrewrite.java.tree.J.MethodDeclaration;
import org.openrewrite.marker.Range;
import org.springframework.ide.vscode.boot.java.SpringAotJavaProblemType;
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.MarkerVisitorContext;
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.BeanPostProcessingIgnoreInAot;
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 BeanPostProcessingIgnoreInAotProblem implements RecipeCodeActionDescriptor {
private static final String RECIPE_ID = BeanPostProcessingIgnoreInAot.class.getName();
private static final String LABEL = "Add method 'isBeanExcludedFromAotProcessing' that returns 'false'";
@Override
public JavaVisitor<ExecutionContext> getMarkerVisitor(MarkerVisitorContext context) {
return new JavaMarkerVisitor<ExecutionContext>() {
@Override
public ClassDeclaration visitClassDeclaration(ClassDeclaration classDecl, ExecutionContext p) {
ClassDeclaration c = super.visitClassDeclaration(classDecl, p);
if (BeanPostProcessingIgnoreInAot.isApplicableClass(classDecl)) {
List<MethodDeclaration> methods = classDecl.getBody().getStatements().stream()
.filter(MethodDeclaration.class::isInstance).map(MethodDeclaration.class::cast)
.filter(BeanPostProcessingIgnoreInAot::isApplicableMethod)
.collect(Collectors.toList());
String uri = getCursor().firstEnclosing(SourceFile.class).getSourcePath().toUri().toASCIIString();
FixAssistMarker marker = new FixAssistMarker(Tree.randomId(), getId())
.withFixes(
new FixDescriptor(RECIPE_ID, List.of(uri), RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.NODE))
.withRangeScope(classDecl.getMarkers().findFirst(Range.class).orElse(null))
.withRecipeScope(RecipeScope.NODE)
);
if (methods.isEmpty()) {
// Didn't find a method. Default implementation return true therefore mark it.
c = c.withName(c.getName().withMarkers(c.getName().getMarkers().add(marker)));
} else {
MethodDeclaration m = methods.stream().filter(BeanPostProcessingIgnoreInAot::isReturnTrue).findFirst().orElse(null);
// Found method that return true explicitly
if (m != null) {
c = c.withName(c.getName().withMarkers(c.getName().getMarkers().add(marker)));
}
}
}
return c;
}
};
}
@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;
}
}

View File

@@ -1,129 +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.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.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.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.MarkerVisitorContext;
import org.springframework.ide.vscode.commons.rewrite.config.RecipeCodeActionDescriptor;
import org.springframework.ide.vscode.commons.rewrite.java.FixAssistMarker;
import org.springframework.ide.vscode.commons.rewrite.java.JavaMarkerVisitor;
public class Boot3NotSupportedTypeProblem implements RecipeCodeActionDescriptor {
private static final List<String> TYPE_FQNAMES = List.of(
"org.springframework.web.multipart.commons.CommonsMultipartResolver",
"java.lang.SecurityManager",
"java.security.AccessControlException"
);
@Override
public JavaVisitor<ExecutionContext> getMarkerVisitor(MarkerVisitorContext context) {
return new JavaMarkerVisitor<>() {
@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 extends NameTree> 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;
}
}

View File

@@ -1,59 +0,0 @@
/*******************************************************************************
* 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 static org.springframework.ide.vscode.commons.java.SpringProjectUtil.springBootVersionGreaterOrEqual;
import org.openrewrite.ExecutionContext;
import org.openrewrite.Tree;
import org.openrewrite.java.JavaVisitor;
import org.openrewrite.java.spring.boot2.search.EntityIdForRepositoryVisitor;
import org.openrewrite.java.tree.JavaType;
import org.openrewrite.marker.Marker;
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.languageserver.reconcile.ProblemType;
import org.springframework.ide.vscode.commons.rewrite.config.MarkerVisitorContext;
import org.springframework.ide.vscode.commons.rewrite.config.RecipeCodeActionDescriptor;
import org.springframework.ide.vscode.commons.rewrite.java.FixAssistMarker;
public class EntityIdForRepoProblem implements RecipeCodeActionDescriptor {
private static final String ID = EntityIdForRepositoryVisitor.class.getName();
@Override
public JavaVisitor<ExecutionContext> getMarkerVisitor(MarkerVisitorContext context) {
boolean considerIdField = context.project() != null && SpringProjectUtil.hasSpecificLibraryOnClasspath(context.project(), "spring-data-mongodb-", true);
return new EntityIdForRepositoryVisitor<>(considerIdField) {
@Override
protected Marker createMarker(JavaType domainIdType) {
return new FixAssistMarker(Tree.randomId(), ID).withLabel("Expected Domain ID type is '" + domainIdType + "'");
}
};
}
@Override
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(2, 0, 0).test(project);
}
@Override
public String getId() {
return ID;
}
@Override
public ProblemType getProblemType() {
return Boot2JavaProblemType.DOMAIN_ID_FOR_REPOSITORY;
}
}

View File

@@ -1,84 +0,0 @@
/*******************************************************************************
* 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.ConvertToSecurityDslVisitor;
import org.openrewrite.java.spring.boot2.HttpSecurityLambdaDsl;
import org.openrewrite.java.tree.J.MethodInvocation;
import org.openrewrite.marker.Range;
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.MarkerVisitorContext;
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 HttpSecurityLamdaDslCodeAction implements RecipeCodeActionDescriptor {
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 HttpSecurityLambdaDsl recipe = new HttpSecurityLambdaDsl();
@Override
public JavaVisitor<ExecutionContext> getMarkerVisitor(MarkerVisitorContext context) {
return new JavaMarkerVisitor<ExecutionContext>() {
@Override
public MethodInvocation visitMethodInvocation(MethodInvocation method, ExecutionContext p) {
if (((ConvertToSecurityDslVisitor<?>) recipe.getVisitor()).isApplicableTopLevelMethodInvocation(method)) {
// Don't step into the method any further
String uri = getCursor().firstEnclosing(SourceFile.class).getSourcePath().toUri().toASCIIString();
FixAssistMarker marker = new FixAssistMarker(Tree.randomId(), getId()).withLabel(PROBLEM_LABEL)
.withFixes(
new FixDescriptor(recipe.getName(), List.of(uri),
RecipeCodeActionDescriptor.buildLabel(FIX_LABEL, RecipeScope.NODE))
.withRangeScope(method.getMarkers().findFirst(Range.class).get())
.withRecipeScope(RecipeScope.NODE),
new FixDescriptor(recipe.getName(), List.of(uri),
RecipeCodeActionDescriptor.buildLabel(FIX_LABEL, RecipeScope.FILE))
.withRecipeScope(RecipeScope.FILE),
new FixDescriptor(recipe.getName(), List.of(uri),
RecipeCodeActionDescriptor.buildLabel(FIX_LABEL, RecipeScope.PROJECT))
.withRecipeScope(RecipeScope.PROJECT));
return method.withMarkers(method.getMarkers().add(marker));
}
return super.visitMethodInvocation(method, p);
}
};
}
@Override
public boolean isApplicable(IJavaProject project) {
Version version = SpringProjectUtil.getDependencyVersion(project, "spring-security-config");
return version != null && version.compareTo(new Version(5, 2, 0, null)) >= 0;
}
@Override
public ProblemType getProblemType() {
return Boot2JavaProblemType.JAVA_LAMBDA_DSL;
}
}

View File

@@ -1,110 +0,0 @@
/*******************************************************************************
* 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.Optional;
import org.openrewrite.ExecutionContext;
import org.openrewrite.Tree;
import org.openrewrite.java.JavaIsoVisitor;
import org.openrewrite.java.JavaVisitor;
import org.openrewrite.java.marker.JavaSourceSet;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.J.CompilationUnit;
import org.openrewrite.java.tree.J.FieldAccess;
import org.openrewrite.java.tree.J.Identifier;
import org.openrewrite.java.tree.JavaType.FullyQualified;
import org.openrewrite.java.tree.TypeUtils;
import org.springframework.ide.vscode.boot.java.Boot3JavaProblemType;
import org.springframework.ide.vscode.boot.modulith.AppModules;
import org.springframework.ide.vscode.boot.modulith.ModulithService;
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.MarkerVisitorContext;
import org.springframework.ide.vscode.commons.rewrite.config.RecipeCodeActionDescriptor;
import org.springframework.ide.vscode.commons.rewrite.java.FixAssistMarker;
import org.springframework.ide.vscode.commons.rewrite.java.ProjectParser;
public class ModulithTypeReferenceViolation implements RecipeCodeActionDescriptor {
private static final String MSG_PKG_NAME = "packageName";
@Override
public JavaVisitor<ExecutionContext> getMarkerVisitor(MarkerVisitorContext context) {
ModulithService modulithService = context.appContext().getBean(ModulithService.class);
AppModules appModules = modulithService.getModulesData(context.project());
return new JavaIsoVisitor<ExecutionContext>() {
@Override
public CompilationUnit visitCompilationUnit(CompilationUnit cu, ExecutionContext p) {
if (appModules == null) {
return cu;
} else {
JavaSourceSet sourceSet = cu.getMarkers().findFirst(JavaSourceSet.class).orElse(null);
if (sourceSet != null && ProjectParser.TEST.equals(sourceSet.getName())) {
return cu;
}
String pkgName = cu.getPackageDeclaration() == null ? "" : cu.getPackageDeclaration().getPackageName();
p.putMessage(MSG_PKG_NAME, pkgName);
return super.visitCompilationUnit(cu, p);
}
}
@Override
public FieldAccess visitFieldAccess(FieldAccess fieldAccess, ExecutionContext p) {
FieldAccess fa = super.visitFieldAccess(fieldAccess, p);
return process(fa, p.getMessage(MSG_PKG_NAME), TypeUtils.asFullyQualified(fa.getType()));
}
@Override
public Identifier visitIdentifier(Identifier identifier, ExecutionContext p) {
Identifier i = super.visitIdentifier(identifier, p);
if (getCursor().getParent().firstEnclosingOrThrow(J.class) instanceof J.FieldAccess) {
return i;
}
// check if identifier is a simple name of the type
FullyQualified type = TypeUtils.asFullyQualified(identifier.getType());
if (type != null && identifier.getSimpleName().equals(type.getClassName())) {
return process(i, p.getMessage(MSG_PKG_NAME), type);
}
return i;
}
private <T extends J> T process(T node, String packageName, FullyQualified type) {
if (type != null) {
Optional<T> opt = appModules.getModuleNotExposingType(packageName, type.getFullyQualifiedName()).map(module -> {
FixAssistMarker fixMarker = new FixAssistMarker(Tree.randomId(), getId())
.withLabel("Cannot use type in this package. Type is not exposed in module '" + module.name() + "'." );
return node.withMarkers(node.getMarkers().add(fixMarker));
});
return opt.orElse(node);
}
return node;
}
};
}
@Override
public boolean isApplicable(IJavaProject project) {
return ModulithService.isModulithDependentProject(project);
}
@Override
public ProblemType getProblemType() {
return Boot3JavaProblemType.MODULITH_TYPE_REF_VIOLATION;
}
}

View File

@@ -1,117 +0,0 @@
/*******************************************************************************
* Copyright (c) 2022, 2023 VMware, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* 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.SourceFile;
import org.openrewrite.Tree;
import org.openrewrite.internal.ListUtils;
import org.openrewrite.java.AnnotationMatcher;
import org.openrewrite.java.JavaVisitor;
import org.openrewrite.java.spring.NoAutowiredOnConstructor;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.J.ClassDeclaration;
import org.openrewrite.java.tree.J.MethodDeclaration;
import org.openrewrite.java.tree.JavaType.FullyQualified;
import org.openrewrite.java.tree.Statement;
import org.openrewrite.java.tree.TypeUtils;
import org.openrewrite.marker.Range;
import org.springframework.ide.vscode.boot.java.Annotations;
import org.springframework.ide.vscode.boot.java.Boot2JavaProblemType;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.rewrite.config.MarkerVisitorContext;
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 NoAutowiredOnConstructorProblem implements RecipeCodeActionDescriptor {
private static final AnnotationMatcher BOOT_TEST_ANNOTATION_MATCHER = new AnnotationMatcher(
"@org.springframework.boot.test.context.SpringBootTest", true);
private static final String ID = NoAutowiredOnConstructor.class.getName();
private static final String LABEL = "Remove Unnecessary @Autowired";
@Override
public JavaVisitor<ExecutionContext> getMarkerVisitor(MarkerVisitorContext context) {
return new JavaMarkerVisitor<ExecutionContext>() {
public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl, ExecutionContext context) {
J.ClassDeclaration cd = super.visitClassDeclaration(classDecl, context);
int constructorCount = 0;
for (Statement s : cd.getBody().getStatements()) {
if (isConstructor(s)) {
constructorCount++;
if (constructorCount > 1) {
return cd;
}
}
}
FullyQualified type = TypeUtils.asFullyQualified(classDecl.getType());
if (type != null && isApplicableType(type)) {
return cd.withBody(cd.getBody().withStatements(ListUtils.map(cd.getBody().getStatements(), s -> {
if (!isConstructor(s)) {
return s;
}
MethodDeclaration constructor = (MethodDeclaration) s;
String uri = getCursor().firstEnclosing(SourceFile.class).getSourcePath().toUri()
.toASCIIString();
FixAssistMarker fixAssistMarker = new FixAssistMarker(Tree.randomId(), getId())
.withFix(new FixDescriptor(ID, List.of(uri), LABEL).withRecipeScope(RecipeScope.NODE)
.withRangeScope(getCursor().firstEnclosing(ClassDeclaration.class).getMarkers()
.findFirst(Range.class).get()));
constructor = constructor
.withLeadingAnnotations(ListUtils.map(constructor.getLeadingAnnotations(), a -> {
if (TypeUtils.isOfClassType(a.getType(), Annotations.AUTOWIRED)) {
a = a.withMarkers(a.getMarkers().add(fixAssistMarker));
}
return a;
}));
return constructor;
})));
}
return cd;
}
private boolean isApplicableType(FullyQualified type) {
for (FullyQualified annotationType : type.getAnnotations()) {
if (BOOT_TEST_ANNOTATION_MATCHER.matchesAnnotationOrMetaAnnotation(annotationType)) {
return false;
}
}
FullyQualified superType = type.getSupertype();
return superType == null ? true : isApplicableType(superType);
}
};
}
@Override
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(2, 0, 0).test(project);
}
@Override
public Boot2JavaProblemType getProblemType() {
return Boot2JavaProblemType.JAVA_AUTOWIRED_CONSTRUCTOR;
}
private static boolean isConstructor(Statement s) {
return s instanceof J.MethodDeclaration && ((J.MethodDeclaration) s).isConstructor();
}
}

View File

@@ -1,101 +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.java.rewrite.reconcile;
import static org.springframework.ide.vscode.commons.java.SpringProjectUtil.springBootVersionGreaterOrEqual;
import java.util.List;
import org.openrewrite.ExecutionContext;
import org.openrewrite.SourceFile;
import org.openrewrite.Tree;
import org.openrewrite.internal.ListUtils;
import org.openrewrite.java.JavaVisitor;
import org.openrewrite.java.spring.NoRepoAnnotationOnRepoInterface;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.J.ClassDeclaration;
import org.openrewrite.java.tree.JavaType;
import org.openrewrite.java.tree.TypeUtils;
import org.openrewrite.marker.Range;
import org.springframework.ide.vscode.boot.java.Annotations;
import org.springframework.ide.vscode.boot.java.Boot2JavaProblemType;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.rewrite.config.MarkerVisitorContext;
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 NoRepoAnnotationProblem implements RecipeCodeActionDescriptor {
private static final String ID = NoRepoAnnotationOnRepoInterface.class.getName();
private static final String LABEL = "Remove Unnecessary @Repository";
private static final String INTERFACE_REPOSITORY = "org.springframework.data.repository.Repository";
private static final String ANNOTATION_REPOSITORY = Annotations.REPOSITORY;
@Override
public JavaVisitor<ExecutionContext> getMarkerVisitor(MarkerVisitorContext context) {
return new JavaMarkerVisitor<ExecutionContext>() {
@Override
public ClassDeclaration visitClassDeclaration(ClassDeclaration classDecl,
ExecutionContext executionContext) {
J.ClassDeclaration c = super.visitClassDeclaration(classDecl, executionContext);
if (c.getKind() == ClassDeclaration.Kind.Type.Interface) {
final J.Annotation repoAnnotation = c.getLeadingAnnotations().stream().filter(annotation -> {
if (annotation.getArguments() == null || annotation.getArguments().isEmpty()
|| annotation.getArguments().get(0) instanceof J.Empty) {
JavaType.FullyQualified type = TypeUtils.asFullyQualified(annotation.getType());
return type != null && ANNOTATION_REPOSITORY.equals(type.getFullyQualifiedName());
}
return false;
}).findFirst().orElse(null);
if (repoAnnotation != null && TypeUtils.isAssignableTo(INTERFACE_REPOSITORY, c.getType())) {
c = c.withLeadingAnnotations(ListUtils.map(c.getLeadingAnnotations(), a -> {
if (a == repoAnnotation) {
String uri = getCursor().firstEnclosing(SourceFile.class).getSourcePath().toUri()
.toASCIIString();
FixAssistMarker fixAssistMarker = new FixAssistMarker(Tree.randomId(), getId()).withFixes(
new FixDescriptor(ID, List.of(uri), LABEL)
.withRangeScope(classDecl.getMarkers().findFirst(Range.class).get())
.withRecipeScope(RecipeScope.NODE),
new FixDescriptor(ID, List.of(uri),
RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.FILE))
.withRecipeScope(RecipeScope.FILE),
new FixDescriptor(ID, List.of(uri),
RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.PROJECT))
.withRecipeScope(RecipeScope.PROJECT)
);
return a.withMarkers(a.getMarkers().add(fixAssistMarker));
}
return a;
}));
}
}
return c;
}
};
}
@Override
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(2, 0, 0).test(project);
}
@Override
public Boot2JavaProblemType getProblemType() {
return Boot2JavaProblemType.JAVA_REPOSITORY;
}
}

View File

@@ -1,77 +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.java.rewrite.reconcile;
import static org.springframework.ide.vscode.commons.java.SpringProjectUtil.springBootVersionGreaterOrEqual;
import java.util.List;
import org.openrewrite.ExecutionContext;
import org.openrewrite.SourceFile;
import org.openrewrite.Tree;
import org.openrewrite.java.AnnotationMatcher;
import org.openrewrite.java.JavaVisitor;
import org.openrewrite.java.spring.NoRequestMappingAnnotation;
import org.openrewrite.java.tree.J;
import org.openrewrite.marker.Range;
import org.springframework.ide.vscode.boot.java.Boot2JavaProblemType;
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.MarkerVisitorContext;
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 NoRequestMappingAnnotationCodeAction implements RecipeCodeActionDescriptor {
private static final String LABEL = "Replace @RequestMapping with specific @GetMapping, @PostMapping etc.";
private static final String ID = NoRequestMappingAnnotation.class.getName();
private static final AnnotationMatcher REQUEST_MAPPING_ANNOTATION_MATCHER = new AnnotationMatcher("@org.springframework.web.bind.annotation.RequestMapping");
@Override
public JavaVisitor<ExecutionContext> getMarkerVisitor(MarkerVisitorContext context) {
return new JavaMarkerVisitor<ExecutionContext>() {
@Override
public J.Annotation visitAnnotation(J.Annotation annotation, ExecutionContext ctx) {
J.Annotation a = super.visitAnnotation(annotation, ctx);
if (REQUEST_MAPPING_ANNOTATION_MATCHER.matches(a) && getCursor().getParentOrThrow().getValue() instanceof J.MethodDeclaration) {
String uri = getCursor().firstEnclosing(SourceFile.class).getSourcePath().toUri().toASCIIString();
FixAssistMarker fixAssistMarker = new FixAssistMarker(Tree.randomId(), getId())
.withFixes(
// new FixDescriptor(ID, List.of(uri), RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.NODE))
// .withRangeScope(a.getMarkers().findFirst(Range.class).get())
// .withRecipeScope(RecipeScope.NODE),
new FixDescriptor(ID, List.of(uri), RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.FILE))
.withRecipeScope(RecipeScope.FILE),
new FixDescriptor(ID, List.of(uri), RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.PROJECT))
.withRecipeScope(RecipeScope.PROJECT)
);
a = a.withMarkers(a.getMarkers().add(fixAssistMarker));
}
return a;
}
};
}
@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,204 +0,0 @@
/*******************************************************************************
* Copyright (c) 2022, 2023 VMware, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* 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.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.eclipse.lsp4j.WorkspaceSymbol;
import org.openrewrite.ExecutionContext;
import org.openrewrite.SourceFile;
import org.openrewrite.Tree;
import org.openrewrite.java.JavaVisitor;
import org.openrewrite.java.tree.J.ClassDeclaration;
import org.openrewrite.java.tree.JavaType;
import org.openrewrite.java.tree.JavaType.FullyQualified;
import org.openrewrite.java.tree.TypeUtils;
import org.springframework.ide.vscode.boot.app.SpringSymbolIndex;
import org.springframework.ide.vscode.boot.java.SpringAotJavaProblemType;
import org.springframework.ide.vscode.boot.java.beans.BeansSymbolAddOnInformation;
import org.springframework.ide.vscode.boot.java.beans.ConfigBeanSymbolAddOnInformation;
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
import org.springframework.ide.vscode.boot.java.handlers.SymbolAddOnInformation;
import org.springframework.ide.vscode.commons.java.IClasspathUtil;
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.MarkerVisitorContext;
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.DefineMethod;
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;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import com.google.common.collect.ImmutableSet;
public class NotRegisteredBeansProblem implements RecipeCodeActionDescriptor {
private static final String DEFINE_METHOD_RECIPE = DefineMethod.class.getName();
private static final List<String> AOT_BEANS = List.of(
"org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor",
"org.springframework.beans.factory.aot.BeanRegistrationAotProcessor"
);
@Override
public JavaVisitor<ExecutionContext> getMarkerVisitor(MarkerVisitorContext context) {
return new JavaMarkerVisitor<ExecutionContext>() {
@Override
public ClassDeclaration visitClassDeclaration(ClassDeclaration classDecl, ExecutionContext p) {
ClassDeclaration c = super.visitClassDeclaration(classDecl, p);
FullyQualified type = c.getType();
if (type != null) {
String beanClassName = type.getFullyQualifiedName();
boolean applicable = AOT_BEANS.stream().filter(fqName -> TypeUtils.isAssignableTo(fqName, type)).findFirst().isPresent();
if (applicable) {
SpringSymbolIndex index = context.appContext().getBean(SpringSymbolIndex.class);
List<WorkspaceSymbol> beanSymbols = index.getSymbols(data -> {
SymbolAddOnInformation[] additionalInformation = data.getAdditionalInformation();
if (additionalInformation != null) {
for (SymbolAddOnInformation info : additionalInformation) {
if (info instanceof BeansSymbolAddOnInformation) {
BeansSymbolAddOnInformation info2 = (BeansSymbolAddOnInformation) info;
return beanClassName.equals(info2.getBeanType());
}
}
}
return false;
}).limit(1).collect(Collectors.toList());
Builder<FixDescriptor> fixListBuilder = ImmutableList.builder();
List<JavaType.Method> constructors = c.getType().getMethods().stream().filter(m -> m.isConstructor()).collect(Collectors.toList());
if (beanSymbols.isEmpty()) {
SourceFile source = getCursor().firstEnclosing(SourceFile.class);
FixAssistMarker marker = new FixAssistMarker(Tree.randomId(), getId());
IJavaProject project = context.project();
if (project != null) {
for (EnhancedSymbolInformation s : index.getEnhancedSymbols(project)) {
if (s.getAdditionalInformation() != null) {
ConfigBeanSymbolAddOnInformation configInfo = Arrays.stream(s.getAdditionalInformation()).filter(ConfigBeanSymbolAddOnInformation.class::isInstance).map(ConfigBeanSymbolAddOnInformation.class::cast).findFirst().orElse(null);
if (configInfo != null) {
for (JavaType.Method constructor : constructors) {
String constructorParamsSignature = "(" + constructor.getParameterTypes().stream().map(pt -> typePattern(pt)).collect(Collectors.joining(",")) + ")";
String beanMethodName = "get" + type.getClassName();
String pattern = beanMethodName + constructorParamsSignature;
String contructorParamsLabel = "(" + constructor.getParameterTypes().stream().map(NotRegisteredBeansProblem::typeStr).collect(Collectors.joining(", ")) + ")";
Builder<String> paramBuilder = ImmutableList.builder();
for (int i = 0; i < constructor.getParameterNames().size() && i < constructor.getParameterTypes().size(); i++) {
JavaType paramType = constructor.getParameterTypes().get(i);
String paramName = constructor.getParameterNames().get(i);
paramBuilder.add(typeStr(paramType) + ' ' + paramName);
}
String paramsStr = String.join(", ", paramBuilder.build().toArray(String[]::new));
fixListBuilder.add(new FixDescriptor(DEFINE_METHOD_RECIPE, List.of(s.getSymbol().getLocation().getLeft().getUri()), "Define bean in config '" + configInfo.getBeanID() + "' with constructor " + contructorParamsLabel)
.withRecipeScope(RecipeScope.FILE)
.withParameters(Map.of(
"targetFqName", configInfo.getBeanType(),
"signature", pattern,
"template", "@Bean\n"
+ type.getClassName() + " " + beanMethodName + "(" + paramsStr + ") {\n"
+ "return new " + type.getClassName() + "(" + constructor.getParameterNames().stream().collect(Collectors.joining(", ")) + ");\n"
+ "}\n",
"imports", allFQTypes(constructor).toArray(String[]::new),
"typeStubs", new String[] { source.printAll() },
"classpath", IClasspathUtil.getAllBinaryRoots(project.getClasspath()).stream().map(f -> f.toPath().toString()).toArray(String[]::new)
))
);
}
}
}
}
}
marker.withFixes(fixListBuilder.build().toArray(FixDescriptor[]::new));
c = c.withName(c.getName().withMarkers(c.getName().getMarkers().add(marker)));
}
}
}
return c;
}
};
}
private static Set<String> allFQTypes(JavaType type) {
ImmutableSet.Builder<String> b = ImmutableSet.builder();
if (type instanceof JavaType.FullyQualified) {
b.add(((JavaType.FullyQualified) type).getFullyQualifiedName());
if (type instanceof JavaType.Parameterized) {
((JavaType.Parameterized) type).getTypeParameters().forEach(t -> b.addAll(allFQTypes(t)));
}
} else if (type instanceof JavaType.Array) {
b.addAll(allFQTypes(((JavaType.Array) type).getElemType()));
} else if (type instanceof JavaType.Method) {
JavaType.Method m = (JavaType.Method) type;
b.addAll(allFQTypes(m.getDeclaringType()));
b.addAll(allFQTypes(m.getReturnType()));
m.getParameterTypes().forEach(pt -> b.addAll(allFQTypes(pt)));
}
return b.build();
}
@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;
}
private static String typePattern(JavaType type) {
if (type instanceof JavaType.Primitive) {
if (type.equals(JavaType.Primitive.String)) {
return ((JavaType.Primitive) type).getClassName();
}
return ((JavaType.Primitive) type).getKeyword();
} else if (type instanceof JavaType.FullyQualified) {
return ((JavaType.FullyQualified) type).getFullyQualifiedName();
} else if (type instanceof JavaType.Array) {
JavaType elemType = ((JavaType.Array) type).getElemType();
return typePattern(elemType) + "[]";
}
return null;
}
private static String typeStr(JavaType type) {
if (type instanceof JavaType.Primitive) {
if (type.equals(JavaType.Primitive.String)) {
return ((JavaType.Primitive) type).getClassName();
}
return ((JavaType.Primitive) type).getKeyword();
} else if (type instanceof JavaType.Parameterized) {
JavaType.Parameterized parametereized = (JavaType.Parameterized) type;
return parametereized.getClassName() + "<" + parametereized.getTypeParameters().stream().map(NotRegisteredBeansProblem::typeStr).collect(Collectors.joining(", ")) + ">";
} else if (type instanceof JavaType.FullyQualified) {
return ((JavaType.FullyQualified) type).getClassName();
} else if (type instanceof JavaType.Array) {
JavaType elemType = ((JavaType.Array) type).getElemType();
return typeStr(elemType) + "[]";
}
return null;
}
}

View File

@@ -1,136 +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.java.rewrite.reconcile;
import static org.springframework.ide.vscode.commons.java.SpringProjectUtil.springBootVersionGreaterOrEqual;
import java.util.List;
import org.openrewrite.Cursor;
import org.openrewrite.ExecutionContext;
import org.openrewrite.SourceFile;
import org.openrewrite.Tree;
import org.openrewrite.java.JavaVisitor;
import org.openrewrite.java.spring.boot3.PreciseBeanType;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.J.Return;
import org.openrewrite.java.tree.JavaType;
import org.openrewrite.java.tree.TypeUtils;
import org.openrewrite.marker.Range;
import org.springframework.ide.vscode.boot.java.SpringAotJavaProblemType;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.rewrite.config.MarkerVisitorContext;
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 PreciseBeanTypeProblem implements RecipeCodeActionDescriptor {
private static final String RECIPE_ID = PreciseBeanType.class.getName();
private static final String LABEL = "Ensure concrete bean type";
private static final String MSG_KEY = "returnType";
@Override
public JavaVisitor<ExecutionContext> getMarkerVisitor(MarkerVisitorContext context) {
return new JavaMarkerVisitor<>() {
public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, ExecutionContext executionContext) {
J.MethodDeclaration m = super.visitMethodDeclaration(method, executionContext);
if (m.getLeadingAnnotations().stream().anyMatch(a -> TypeUtils.isOfClassType(a.getType(), "org.springframework.context.annotation.Bean"))) {
Object o = getCursor().pollMessage(MSG_KEY);
if (o != null && !areTypesEqual((JavaType) o, m.getReturnTypeExpression().getType())) {
if ((o instanceof JavaType.FullyQualified && m.getReturnTypeExpression().getType() instanceof JavaType.FullyQualified)
|| (o instanceof JavaType.Array && m.getReturnTypeExpression().getType() instanceof JavaType.Array)) {
String uri = getCursor().firstEnclosing(SourceFile.class).getSourcePath().toUri().toASCIIString();
FixAssistMarker marker = new FixAssistMarker(Tree.randomId(), getId())
.withFixes(
new FixDescriptor(RECIPE_ID, List.of(uri), RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.NODE))
.withRecipeScope(RecipeScope.NODE)
.withRangeScope(m.getMarkers().findFirst(Range.class).get()),
new FixDescriptor(RECIPE_ID, List.of(uri), RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.FILE))
.withRecipeScope(RecipeScope.FILE),
new FixDescriptor(RECIPE_ID, List.of(uri), RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.PROJECT))
.withRecipeScope(RecipeScope.PROJECT)
);
m = m.withReturnTypeExpression(m.getReturnTypeExpression().withMarkers(m.getReturnTypeExpression().getMarkers().add(marker)));
}
}
}
return m;
}
@Override
public Return visitReturn(Return _return, ExecutionContext executionContext) {
Cursor methodCursor = getCursor();
if (_return.getExpression() != null) {
while (methodCursor != null && !(methodCursor.getValue() instanceof J.Lambda || methodCursor.getValue() instanceof J.MethodDeclaration)) {
methodCursor = methodCursor.getParent();
}
if (methodCursor != null && methodCursor.getValue() instanceof J.MethodDeclaration) {
methodCursor.putMessage(MSG_KEY, _return.getExpression().getType());
}
}
return super.visitReturn(_return, executionContext);
}
};
}
private static boolean areTypesEqual(JavaType a, JavaType b) {
if (a instanceof JavaType.Parameterized && b instanceof JavaType.Parameterized) {
JavaType.Parameterized ap = (JavaType.Parameterized) a;
JavaType.Parameterized bp = (JavaType.Parameterized) b;
if (ap.getTypeParameters().size() != bp.getTypeParameters().size()) {
return false;
}
if (areTypesEqual(ap.getType(), bp.getType())) {
for (int i = 0; i < ap.getTypeParameters().size(); i++) {
if (!areTypesEqual(ap.getTypeParameters().get(i), bp.getTypeParameters().get(i))) {
return false;
}
}
}
} else if (a instanceof JavaType.Parameterized && b instanceof JavaType.FullyQualified) {
return areTypesEqual(((JavaType.Parameterized) a).getType(), b);
} else if (a instanceof JavaType.FullyQualified && b instanceof JavaType.Parameterized) {
return areTypesEqual(a, ((JavaType.Parameterized) b).getType());
} else if (a instanceof JavaType.Array && b instanceof JavaType.Array) {
return areTypesEqual(((JavaType.Array) a).getElemType(), ((JavaType.Array) b).getElemType());
}
if (a instanceof JavaType.GenericTypeVariable || b instanceof JavaType.GenericTypeVariable) {
return true;
}
if (a == JavaType.Primitive.String && b instanceof JavaType.FullyQualified) {
return JavaType.Primitive.String.getClassName().equals(((JavaType.FullyQualified) b).getFullyQualifiedName());
}
if (b == JavaType.Primitive.String && b instanceof JavaType.FullyQualified) {
return JavaType.Primitive.String.getClassName().equals(((JavaType.FullyQualified) a).getFullyQualifiedName());
}
return a.equals(b);
}
@Override
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(3, 0, 0).test(project);
}
@Override
public SpringAotJavaProblemType getProblemType() {
return SpringAotJavaProblemType.JAVA_CONCRETE_BEAN_TYPE;
}
}

View File

@@ -1,83 +0,0 @@
/*******************************************************************************
* 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.ConvertToSecurityDslVisitor;
import org.openrewrite.java.spring.boot2.ServerHttpSecurityLambdaDsl;
import org.openrewrite.java.tree.J.MethodInvocation;
import org.openrewrite.marker.Range;
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.MarkerVisitorContext;
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 ServerHttpSecurityLambdaDslCodeAction implements RecipeCodeActionDescriptor {
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 ServerHttpSecurityLambdaDsl recipe = new ServerHttpSecurityLambdaDsl();
@Override
public JavaVisitor<ExecutionContext> getMarkerVisitor(MarkerVisitorContext context) {
return new JavaMarkerVisitor<ExecutionContext>() {
@Override
public MethodInvocation visitMethodInvocation(MethodInvocation method, ExecutionContext p) {
if (((ConvertToSecurityDslVisitor<?>)recipe.getVisitor()).isApplicableTopLevelMethodInvocation(method)) {
// Don't step into the method any further
String uri = getCursor().firstEnclosing(SourceFile.class).getSourcePath().toUri().toASCIIString();
FixAssistMarker marker = new FixAssistMarker(Tree.randomId(), getId()).withLabel(PROBLEM_LABEL)
.withFixes(
new FixDescriptor(recipe.getName(), List.of(uri),
RecipeCodeActionDescriptor.buildLabel(FIX_LABEL, RecipeScope.NODE))
.withRangeScope(method.getMarkers().findFirst(Range.class).get())
.withRecipeScope(RecipeScope.NODE),
new FixDescriptor(recipe.getName(), List.of(uri),
RecipeCodeActionDescriptor.buildLabel(FIX_LABEL, RecipeScope.FILE))
.withRecipeScope(RecipeScope.FILE),
new FixDescriptor(recipe.getName(), List.of(uri),
RecipeCodeActionDescriptor.buildLabel(FIX_LABEL, RecipeScope.PROJECT))
.withRecipeScope(RecipeScope.PROJECT));
return method.withMarkers(method.getMarkers().add(marker));
}
return super.visitMethodInvocation(method, p);
}
};
}
@Override
public boolean isApplicable(IJavaProject project) {
Version version = SpringProjectUtil.getDependencyVersion(project, "spring-security-config");
return version != null && version.compareTo(new Version(5, 2, 0, null)) >= 0;
}
@Override
public ProblemType getProblemType() {
return Boot2JavaProblemType.JAVA_LAMBDA_DSL;
}
}

View File

@@ -1,98 +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.java.rewrite.reconcile;
import static org.springframework.ide.vscode.commons.java.SpringProjectUtil.springBootVersionGreaterOrEqual;
import java.util.Arrays;
import java.util.List;
import org.openrewrite.ExecutionContext;
import org.openrewrite.SourceFile;
import org.openrewrite.Tree;
import org.openrewrite.internal.ListUtils;
import org.openrewrite.java.AnnotationMatcher;
import org.openrewrite.java.JavaVisitor;
import org.openrewrite.java.spring.boot2.UnnecessarySpringExtension;
import org.openrewrite.java.tree.J.ClassDeclaration;
import org.openrewrite.java.tree.JavaType.FullyQualified;
import org.openrewrite.java.tree.TypeUtils;
import org.springframework.ide.vscode.boot.java.Boot2JavaProblemType;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.rewrite.config.MarkerVisitorContext;
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 UnnecessarySpringExtensionProblem implements RecipeCodeActionDescriptor {
private static final String LABEL = "Remove unnecessary @SpringExtension";
private static final String ID = UnnecessarySpringExtension.class.getName();
private static final List<String> SPRING_BOOT_TEST_ANNOTATIONS = Arrays.asList(
"org.springframework.boot.test.context.SpringBootTest",
"org.springframework.boot.test.autoconfigure.jdbc.JdbcTest",
"org.springframework.boot.test.autoconfigure.web.client.RestClientTest",
"org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest",
"org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest",
"org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest",
"org.springframework.boot.test.autoconfigure.webservices.client.WebServiceClientTest",
"org.springframework.boot.test.autoconfigure.jooq.JooqTest",
"org.springframework.boot.test.autoconfigure.json.JsonTest",
"org.springframework.boot.test.autoconfigure.data.cassandra.DataCassandraTest",
"org.springframework.boot.test.autoconfigure.data.jdbc.DataJdbcTest",
"org.springframework.boot.test.autoconfigure.data.ldap.DataLdapTest",
"org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest",
"org.springframework.boot.test.autoconfigure.data.neo4j.DataNeo4jTest",
"org.springframework.boot.test.autoconfigure.data.r2dbc.DataR2dbcTest",
"org.springframework.boot.test.autoconfigure.data.redis.DataRedisTest"
);
private static final AnnotationMatcher SPRING_EXTENSION_ANNOTATIN_MATCHER = new AnnotationMatcher("@org.junit.jupiter.api.extension.ExtendWith(org.springframework.test.context.junit.jupiter.SpringExtension.class)");
@Override
public JavaVisitor<ExecutionContext> getMarkerVisitor(MarkerVisitorContext context) {
return new JavaMarkerVisitor<>() {
@Override
public ClassDeclaration visitClassDeclaration(ClassDeclaration classDecl, ExecutionContext p) {
ClassDeclaration c = super.visitClassDeclaration(classDecl, p);
if (c.getLeadingAnnotations().stream().anyMatch(a -> {
FullyQualified fq = TypeUtils.asFullyQualified(a.getType());
return fq != null && SPRING_BOOT_TEST_ANNOTATIONS.contains(fq.getFullyQualifiedName());
})) {
c = c.withLeadingAnnotations(ListUtils.map(c.getLeadingAnnotations(), a -> {
if (SPRING_EXTENSION_ANNOTATIN_MATCHER.matches(a)) {
String uri = getCursor().firstEnclosing(SourceFile.class).getSourcePath().toUri().toASCIIString();
FixAssistMarker fixMarker = new FixAssistMarker(Tree.randomId(), getId())
.withFix(new FixDescriptor(ID, List.of(uri), RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.PROJECT)));
return a.withMarkers(a.getMarkers().add(fixMarker));
}
return a;
}));
}
return c;
}
};
}
@Override
public boolean isApplicable(IJavaProject project) {
return springBootVersionGreaterOrEqual(2, 1, 0).test(project);
}
@Override
public Boot2JavaProblemType getProblemType() {
return Boot2JavaProblemType.JAVA_TEST_SPRING_EXTENSION;
}
}

View File

@@ -1,140 +0,0 @@
/*******************************************************************************
* 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.Collection;
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.security5.WebSecurityConfigurerAdapter;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.J.ClassDeclaration;
import org.openrewrite.java.tree.JavaType;
import org.openrewrite.java.tree.TypeTree;
import org.openrewrite.java.tree.TypeUtils;
import org.springframework.ide.vscode.boot.java.Annotations;
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.MarkerVisitorContext;
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 WebSecurityConfigurerAdapterCodeAction implements RecipeCodeActionDescriptor {
private static final String ID = WebSecurityConfigurerAdapter.class.getName();
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 = """
package org.springframework.security.config.annotation.web.configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
public abstract class WebSecurityConfigurerAdapter {
public void init(WebSecurity web) throws Exception {}
public AuthenticationManager authenticationManagerBean() throws Exception { return null; }
public UserDetailsService userDetailsServiceBean() throws Exception { return null; }
protected void configure(HttpSecurity http) throws Exception {}
public void configure(WebSecurity web) throws Exception {}
protected void configure(AuthenticationManagerBuilder auth) throws Exception {}
}
""";
@Override
public String getId() {
return ID;
}
@Override
public ProblemType getProblemType() {
return Boot2JavaProblemType.WEB_SECURITY_CONFIGURER_ADAPTER;
}
@Override
public JavaVisitor<ExecutionContext> getMarkerVisitor(MarkerVisitorContext context) {
return new JavaMarkerVisitor<>() {
@Override
public ClassDeclaration visitClassDeclaration(ClassDeclaration classDecl, ExecutionContext p) {
ClassDeclaration c = super.visitClassDeclaration(classDecl, p);
TypeTree superClass = c.getExtends();
boolean isExtendingWebSecurityConfigurerAdapter = false;
boolean isUnresolved = false;
if (superClass != null) {
if (superClass.getType() instanceof JavaType.Unknown) {
String strType = superClass.printTrimmed(getCursor());
isExtendingWebSecurityConfigurerAdapter = "WebSecurityConfigurerAdapter".equals(strType) || FQN_WEB_SECURITY_CONFIGURER_ADAPTER.equals(strType);
isUnresolved = true;
} else if (superClass.getType() instanceof JavaType.FullyQualified) {
isExtendingWebSecurityConfigurerAdapter = FQN_WEB_SECURITY_CONFIGURER_ADAPTER.equals( ((JavaType.FullyQualified)superClass.getType()).getFullyQualifiedName());
}
}
if (isExtendingWebSecurityConfigurerAdapter) {
if (isAnnotatedWith(c.getLeadingAnnotations(), Annotations.CONFIGURATION)) {
String uri = getCursor().firstEnclosing(SourceFile.class).getSourcePath().toUri().toASCIIString();
String[] typeStubs = new String[0];
if (isUnresolved) {
typeStubs = new String[] { STUB_WEB_SECURITY_CONFIG_ADAPTER };
}
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)
.withTypeStubs(typeStubs),
new FixDescriptor(ID, List.of(uri),
RecipeCodeActionDescriptor.buildLabel(FIX_LABEL, RecipeScope.PROJECT))
.withRecipeScope(RecipeScope.PROJECT)
.withTypeStubs(typeStubs));
c = c.withName(c.getName().withMarkers(c.getName().getMarkers().add(marker)));
}
}
return c;
}
};
}
@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;
}
private static boolean isAnnotatedWith(Collection<J.Annotation> annotations, String annotationType) {
return annotations.stream().anyMatch(a -> TypeUtils.isOfClassType(a.getType(), annotationType));
}
}