Refactorings. Bean methods not public.
This commit is contained in:
@@ -21,6 +21,8 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SpringProjectUtil {
|
||||
|
||||
public static final String SPRING_BOOT = "spring-boot";
|
||||
|
||||
private static final String VERION_PATTERN_STR = "(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?";
|
||||
|
||||
public static final Logger log = LoggerFactory.getLogger(SpringProjectUtil.class);
|
||||
@@ -37,7 +39,7 @@ public class SpringProjectUtil {
|
||||
}
|
||||
|
||||
public static boolean isBootProject(IJavaProject jp) {
|
||||
return hasSpecificLibraryOnClasspath(jp, "spring-boot", true);
|
||||
return hasSpecificLibraryOnClasspath(jp, SPRING_BOOT, true);
|
||||
}
|
||||
|
||||
public static boolean hasBootActuators(IJavaProject jp) {
|
||||
|
||||
@@ -19,6 +19,7 @@ import java.util.Set;
|
||||
|
||||
import org.eclipse.lsp4j.CodeAction;
|
||||
import org.eclipse.lsp4j.CodeActionCapabilities;
|
||||
import org.eclipse.lsp4j.CodeActionContext;
|
||||
import org.eclipse.lsp4j.Command;
|
||||
import org.eclipse.lsp4j.Hover;
|
||||
import org.eclipse.lsp4j.HoverParams;
|
||||
@@ -105,16 +106,16 @@ public class CompositeLanguageServerComponents implements LanguageServerComponen
|
||||
this.codeActionHandler = new CodeActionHandler() {
|
||||
|
||||
@Override
|
||||
public List<Either<Command, CodeAction>> handle(CancelChecker cancelToken, CodeActionCapabilities capabilities, TextDocument doc,
|
||||
IRegion region) {
|
||||
public List<Either<Command, CodeAction>> handle(CancelChecker cancelToken,
|
||||
CodeActionCapabilities capabilities, CodeActionContext context, TextDocument doc, IRegion region) {
|
||||
LanguageId language = doc.getLanguageId();
|
||||
LanguageServerComponents subComponents = componentsByLanguageId.get(language);
|
||||
if (subComponents != null) {
|
||||
return subComponents.getCodeActionProvider()
|
||||
.map(subEngine -> subEngine.handle(cancelToken, capabilities, doc, region))
|
||||
.map(subEngine -> subEngine.handle(cancelToken, capabilities, context, doc, region))
|
||||
.orElse(Collections.emptyList());
|
||||
}
|
||||
//No applicable subEngine...
|
||||
// No applicable subEngine...
|
||||
return Collections.emptyList();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,9 +1,20 @@
|
||||
/*******************************************************************************
|
||||
* 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.languageserver.util;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.lsp4j.CodeAction;
|
||||
import org.eclipse.lsp4j.CodeActionCapabilities;
|
||||
import org.eclipse.lsp4j.CodeActionContext;
|
||||
import org.eclipse.lsp4j.Command;
|
||||
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.Either;
|
||||
@@ -12,6 +23,6 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
public interface CodeActionHandler {
|
||||
|
||||
List<Either<Command, CodeAction>> handle(CancelChecker cancelToken, CodeActionCapabilities capabilities, TextDocument doc, IRegion region);
|
||||
List<Either<Command, CodeAction>> handle(CancelChecker cancelToken, CodeActionCapabilities capabilities, CodeActionContext context, TextDocument doc, IRegion region);
|
||||
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ import java.util.stream.Collectors;
|
||||
import org.eclipse.lsp4j.ClientCapabilities;
|
||||
import org.eclipse.lsp4j.CodeAction;
|
||||
import org.eclipse.lsp4j.CodeActionCapabilities;
|
||||
import org.eclipse.lsp4j.CodeActionContext;
|
||||
import org.eclipse.lsp4j.CodeActionKind;
|
||||
import org.eclipse.lsp4j.CodeActionParams;
|
||||
import org.eclipse.lsp4j.CodeLens;
|
||||
import org.eclipse.lsp4j.CodeLensParams;
|
||||
@@ -82,6 +84,7 @@ import org.springframework.ide.vscode.commons.util.text.Region;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableList.Builder;
|
||||
|
||||
public class SimpleTextDocumentService implements TextDocumentService, DocumentEventListenerManager {
|
||||
|
||||
@@ -425,23 +428,27 @@ public class SimpleTextDocumentService implements TextDocumentService, DocumentE
|
||||
}
|
||||
|
||||
private List<Either<Command, CodeAction>> computeCodeActions(CancelChecker cancelToken, CodeActionCapabilities capabilities, TrackedDocument doc, CodeActionParams params) {
|
||||
List<Either<Command,CodeAction>> list = doc.getQuickfixes().stream()
|
||||
.filter((fix) -> fix.appliesTo(params.getRange(), params.getContext()))
|
||||
.map(f -> f.getCodeAction(params.getContext()))
|
||||
.map(command -> Either.<Command, CodeAction>forRight(command))
|
||||
.collect(Collectors.toList());
|
||||
Builder<Either<Command,CodeAction>> listBuilder = ImmutableList.builder();
|
||||
CodeActionContext context = params.getContext();
|
||||
if (!context.getDiagnostics().isEmpty() || (context.getOnly() != null && context.getOnly().contains(CodeActionKind.QuickFix))) {
|
||||
doc.getQuickfixes().stream()
|
||||
.filter((fix) -> fix.appliesTo(params.getRange(), context))
|
||||
.map(f -> f.getCodeAction(params.getContext()))
|
||||
.map(command -> Either.<Command, CodeAction>forRight(command))
|
||||
.forEach(listBuilder::add);
|
||||
}
|
||||
|
||||
if (codeActionHandler != null) {
|
||||
try {
|
||||
int start = doc.getDocument().toOffset(params.getRange().getStart());
|
||||
int end = doc.getDocument().toOffset(params.getRange().getEnd());
|
||||
list.addAll(codeActionHandler.handle(cancelToken, capabilities, doc.getDocument(), new Region(start, end - start)));
|
||||
listBuilder.addAll(codeActionHandler.handle(cancelToken, capabilities, context, doc.getDocument(), new Region(start, end - start)));
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to compute quick refactorings", e);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
return listBuilder.build();
|
||||
}
|
||||
|
||||
private static CodeActionCapabilities getCodeActionCapabilities(ClientCapabilities capabilities) {
|
||||
|
||||
@@ -15,14 +15,17 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.AutowiredConstructorReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.reconcilers.AutowiredConstructorReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.reconcilers.BeanMethodNotPublicReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.ORCompilationUnitCache;
|
||||
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.codeaction.BeanMethodsNoPublicCodeAction;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.codeaction.ConvertAutowiredField;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.codeaction.NoRequestMapping;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.codeaction.NoRequestMappings;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.quickfix.AutowiredConstructorQuickFixHandler;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.quickfix.BeanMethodNoPublicQuickFixHandler;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixRegistry;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
@@ -62,11 +65,20 @@ public class RewriteConfig implements InitializingBean {
|
||||
return new NoRequestMappings(server, projectFinder, rewriteRefactorings, orCuCache);
|
||||
}
|
||||
|
||||
@ConditionalOnClass({org.openrewrite.java.spring.BeanMethodsNotPublic.class})
|
||||
@Bean
|
||||
BeanMethodsNoPublicCodeAction beanMethodsNoPublic(SimpleLanguageServer server, JavaProjectFinder projectFinder,
|
||||
RewriteRefactorings rewriteRefactorings, RewriteRecipeRepository recipesRepo,
|
||||
ORCompilationUnitCache orCuCache) {
|
||||
return new BeanMethodsNoPublicCodeAction(server, projectFinder, rewriteRefactorings, orCuCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
QuickfixRegistry registry = server.getQuickfixRegistry();
|
||||
|
||||
registry.register(AutowiredConstructorReconciler.REMOVE_UNNECESSARY_AUTOWIRED_FROM_CONSTRUCTOR, new AutowiredConstructorQuickFixHandler(server, projectFinder, orCuCache));
|
||||
registry.register(BeanMethodNotPublicReconciler.REMOVE_PUBLIC_FROM_BEAN_METHOD, new BeanMethodNoPublicQuickFixHandler(server, projectFinder, orCuCache));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,10 @@ public enum SpringJavaProblemType implements ProblemType {
|
||||
|
||||
JAVA_SPEL_EXPRESSION_SYNTAX(ERROR, "SpEL parser raised a ParseException", "SpEL Expression Syntax"),
|
||||
|
||||
JAVA_AUTOWIRED_CONSTRUCTOR(WARNING, "Unnecessary @Autowired over the only constructor", "Unnecessary @Autowired");
|
||||
JAVA_AUTOWIRED_CONSTRUCTOR(WARNING, "Unnecessary @Autowired over the only constructor", "Unnecessary @Autowired"),
|
||||
|
||||
JAVA_PUBLIC_BEAN_METHOD(HINT, "Public modifier on @Bean method. They no longer have to be public visibility to be usable by Spring.", "public @Bean method");
|
||||
|
||||
private final ProblemSeverity defaultSeverity;
|
||||
private String description;
|
||||
private String label;
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.eclipse.jdt.core.dom.ASTNode;
|
||||
import org.eclipse.jdt.core.dom.NodeFinder;
|
||||
import org.eclipse.lsp4j.CodeAction;
|
||||
import org.eclipse.lsp4j.CodeActionCapabilities;
|
||||
import org.eclipse.lsp4j.CodeActionContext;
|
||||
import org.eclipse.lsp4j.Command;
|
||||
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.Either;
|
||||
@@ -44,14 +45,14 @@ public class BootJavaCodeActionProvider implements CodeActionHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Either<Command, CodeAction>> handle(CancelChecker cancelToken, CodeActionCapabilities capabilities, TextDocument doc, IRegion region) {
|
||||
public List<Either<Command, CodeAction>> handle(CancelChecker cancelToken, CodeActionCapabilities capabilities, CodeActionContext context, TextDocument doc, IRegion region) {
|
||||
Optional<IJavaProject> project = projectFinder.find(doc.getId());
|
||||
if (project.isPresent()) {
|
||||
return cuCache.withCompilationUnit(project.get(), URI.create(doc.getId().getUri()), cu -> {
|
||||
ASTNode found = NodeFinder.perform(cu, region.getOffset(), region.getLength());
|
||||
List<Either<Command, CodeAction>> codeActions = new ArrayList<>();
|
||||
for (JavaCodeAction jca : javaCodeActions) {
|
||||
List<Either<Command, CodeAction>> cas = jca.getCodeActions(capabilities, doc, region, project.get(), cu, found);
|
||||
List<Either<Command, CodeAction>> cas = jca.getCodeActions(capabilities, context, doc, region, project.get(), cu, found);
|
||||
if (cas != null) {
|
||||
codeActions.addAll(cas);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,10 @@ import org.eclipse.jdt.core.dom.MarkerAnnotation;
|
||||
import org.eclipse.jdt.core.dom.NormalAnnotation;
|
||||
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
|
||||
import org.eclipse.lsp4j.TextDocumentIdentifier;
|
||||
import org.springframework.ide.vscode.boot.java.reconcilers.AnnotationParamReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.reconcilers.AnnotationReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.reconcilers.AutowiredConstructorReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.reconcilers.BeanMethodNotPublicReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.utils.CompilationUnitCache;
|
||||
import org.springframework.ide.vscode.boot.java.value.Constants;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
@@ -87,7 +91,8 @@ public class BootJavaReconcileEngine implements IReconcileEngine {
|
||||
new AnnotationParamReconciler(SPRING_CONDITIONAL_ON_EXPRESSION, null, "", "", spelExpressionReconciler),
|
||||
new AnnotationParamReconciler(SPRING_CONDITIONAL_ON_EXPRESSION, "value", "", "", spelExpressionReconciler),
|
||||
|
||||
new AutowiredConstructorReconciler(quickfixRegistry)
|
||||
new AutowiredConstructorReconciler(quickfixRegistry),
|
||||
new BeanMethodNotPublicReconciler(quickfixRegistry)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import org.eclipse.jdt.core.dom.ASTNode;
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit;
|
||||
import org.eclipse.lsp4j.CodeAction;
|
||||
import org.eclipse.lsp4j.CodeActionCapabilities;
|
||||
import org.eclipse.lsp4j.CodeActionContext;
|
||||
import org.eclipse.lsp4j.Command;
|
||||
import org.eclipse.lsp4j.WorkspaceEdit;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.Either;
|
||||
@@ -27,6 +28,6 @@ public interface JavaCodeAction {
|
||||
|
||||
default WorkspaceEdit perform(List<?> args) { return null; }
|
||||
|
||||
List<Either<Command, CodeAction>> getCodeActions(CodeActionCapabilities capabilities, TextDocument doc, IRegion region, IJavaProject project, CompilationUnit cu, ASTNode node);
|
||||
List<Either<Command, CodeAction>> getCodeActions(CodeActionCapabilities capabilities, CodeActionContext context, TextDocument doc, IRegion region, IJavaProject project, CompilationUnit cu, ASTNode node);
|
||||
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.handlers;
|
||||
package org.springframework.ide.vscode.boot.java.reconcilers;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -21,6 +21,7 @@ import org.eclipse.jdt.core.dom.NormalAnnotation;
|
||||
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
|
||||
import org.eclipse.jdt.core.dom.StringLiteral;
|
||||
import org.springframework.ide.vscode.boot.java.annotations.AnnotationHierarchies;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.Reconciler;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
|
||||
import org.springframework.ide.vscode.commons.util.text.IDocument;
|
||||
@@ -8,7 +8,7 @@
|
||||
* Contributors:
|
||||
* VMware, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.handlers;
|
||||
package org.springframework.ide.vscode.boot.java.reconcilers;
|
||||
|
||||
import org.eclipse.jdt.core.dom.Annotation;
|
||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||
@@ -8,7 +8,7 @@
|
||||
* Contributors:
|
||||
* VMware, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.handlers;
|
||||
package org.springframework.ide.vscode.boot.java.reconcilers;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -41,7 +41,7 @@ public class AutowiredConstructorReconciler implements AnnotationReconciler {
|
||||
|
||||
@Override
|
||||
public void visit(IJavaProject project, IDocument doc, Annotation node, ITypeBinding typeBinding, IProblemCollector problemCollector) {
|
||||
Version version = SpringProjectUtil.getDependencyVersion(project, "spring-boot");
|
||||
Version version = SpringProjectUtil.getDependencyVersion(project, SpringProjectUtil.SPRING_BOOT);
|
||||
|
||||
if (version.getMajor() >= 2) {
|
||||
getSingleAutowiredConstructorDeclaringType(node, typeBinding).ifPresent(type -> {
|
||||
@@ -0,0 +1,113 @@
|
||||
/*******************************************************************************
|
||||
* 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.reconcilers;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jdt.core.dom.Annotation;
|
||||
import org.eclipse.jdt.core.dom.IMethodBinding;
|
||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||
import org.eclipse.jdt.core.dom.MethodDeclaration;
|
||||
import org.eclipse.jdt.core.dom.Modifier;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.boot.java.Annotations;
|
||||
import org.springframework.ide.vscode.boot.java.SpringJavaProblemType;
|
||||
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.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.ReconcileProblemImpl;
|
||||
import org.springframework.ide.vscode.commons.util.text.IDocument;
|
||||
|
||||
public class BeanMethodNotPublicReconciler implements AnnotationReconciler {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(BeanMethodNotPublicReconciler.class);
|
||||
|
||||
public static final String REMOVE_PUBLIC_FROM_BEAN_METHOD = "RemovePublicFromBeanMethod";
|
||||
|
||||
private QuickfixRegistry quickfixRegistry;
|
||||
|
||||
public BeanMethodNotPublicReconciler(QuickfixRegistry quickfixRegistry) {
|
||||
this.quickfixRegistry = quickfixRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(IJavaProject project, IDocument doc, Annotation node, ITypeBinding typeBinding,
|
||||
IProblemCollector problemCollector) {
|
||||
|
||||
if (Annotations.BEAN.equals(typeBinding.getQualifiedName()) && node.getParent() instanceof MethodDeclaration) {
|
||||
MethodDeclaration m = (MethodDeclaration) node.getParent();
|
||||
Version version = SpringProjectUtil.getDependencyVersion(project, SpringProjectUtil.SPRING_BOOT);
|
||||
if (version.getMajor() >= 2) {
|
||||
IMethodBinding methodBinding = m.resolveBinding();
|
||||
if (isNotOverridingPublicMethod(methodBinding)) {
|
||||
|
||||
ReconcileProblemImpl problem = ((List<?>)m.modifiers()).stream()
|
||||
.filter(Modifier.class::isInstance)
|
||||
.map(Modifier.class::cast)
|
||||
.filter(modifier -> modifier.isPublic())
|
||||
.findFirst()
|
||||
.map(modifier -> new ReconcileProblemImpl(
|
||||
SpringJavaProblemType.JAVA_PUBLIC_BEAN_METHOD, "public @Bean method",
|
||||
modifier.getStartPosition(), modifier.getLength()))
|
||||
.orElse(new ReconcileProblemImpl(
|
||||
SpringJavaProblemType.JAVA_PUBLIC_BEAN_METHOD, "public @Bean method",
|
||||
m.getName().getStartPosition(), m.getName().getLength()));
|
||||
|
||||
QuickfixType quickfixType = quickfixRegistry.getQuickfixType(REMOVE_PUBLIC_FROM_BEAN_METHOD);
|
||||
if (quickfixType != null) {
|
||||
problem.addQuickfix(new QuickfixData<>(
|
||||
quickfixType,
|
||||
createParameters(doc, methodBinding),
|
||||
"Remove public from @Bean method"
|
||||
));
|
||||
}
|
||||
problemCollector.accept(problem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final boolean isOverriding(IMethodBinding binding) {
|
||||
try {
|
||||
Field f = binding.getClass().getDeclaredField("binding");
|
||||
f.setAccessible(true);
|
||||
org.eclipse.jdt.internal.compiler.lookup.MethodBinding value = (org.eclipse.jdt.internal.compiler.lookup.MethodBinding) f.get(binding);
|
||||
return value.isOverriding();
|
||||
} catch (Exception e) {
|
||||
log.error("", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static final boolean isNotOverridingPublicMethod(IMethodBinding methodBinding) {
|
||||
return !isOverriding(methodBinding) && (methodBinding.getModifiers() & Modifier.PUBLIC) != 0;
|
||||
}
|
||||
|
||||
public static final List<String> createParameters(IDocument doc, IMethodBinding methodBinding) {
|
||||
StringBuilder methodPattern = new StringBuilder(methodBinding.getDeclaringClass().getQualifiedName());
|
||||
methodPattern.append(' ');
|
||||
methodPattern.append(methodBinding.getName());
|
||||
methodPattern.append('(');
|
||||
methodPattern.append(Arrays.stream(methodBinding.getParameterTypes()).map(p -> p.getErasure().getQualifiedName()).collect(Collectors.joining(",")));
|
||||
methodPattern.append(')');
|
||||
return List.of(doc.getUri(), methodPattern.toString());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -292,6 +292,10 @@ public class ORAstUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static Recipe nodeRecipe(JavaVisitor<ExecutionContext> v, Predicate<J> condition) {
|
||||
return new NodeRecipe((JavaVisitor<ExecutionContext>) v, condition);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Recipe nodeRecipe(Recipe r, Predicate<J> condition) {
|
||||
return new NodeRecipe((JavaVisitor<ExecutionContext>) getVisitor(r), condition);
|
||||
|
||||
@@ -12,7 +12,9 @@ package org.springframework.ide.vscode.boot.java.rewrite;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collections;
|
||||
@@ -264,4 +266,17 @@ public class ORCompilationUnitCache implements DocumentContentProvider, Disposab
|
||||
return requestor.apply(null);
|
||||
}
|
||||
|
||||
public List<CompilationUnit> getCompiulationUnits(IJavaProject project) {
|
||||
List<Path> javaFiles = IClasspathUtil.getProjectJavaSourceFolders(project.getClasspath()).flatMap(folder -> {
|
||||
try {
|
||||
return Files.walk(folder.toPath());
|
||||
} catch (IOException e) {
|
||||
logger.error("", e);
|
||||
}
|
||||
return Stream.empty();
|
||||
}).filter(Files::isRegularFile).filter(p -> p.getFileName().toString().endsWith(".java")).collect(Collectors.toList());
|
||||
JavaParser javaParser = loadJavaParser(project);
|
||||
return ORAstUtils.parse(javaParser, javaFiles);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,24 +10,39 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.rewrite.codeaction;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jdt.core.dom.ASTNode;
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit;
|
||||
import org.eclipse.lsp4j.CodeAction;
|
||||
import org.eclipse.lsp4j.CodeActionCapabilities;
|
||||
import org.eclipse.lsp4j.CodeActionContext;
|
||||
import org.eclipse.lsp4j.CodeActionKind;
|
||||
import org.eclipse.lsp4j.CodeActionResolveSupportCapabilities;
|
||||
import org.eclipse.lsp4j.Command;
|
||||
import org.eclipse.lsp4j.ResourceOperation;
|
||||
import org.eclipse.lsp4j.TextDocumentEdit;
|
||||
import org.eclipse.lsp4j.TextDocumentIdentifier;
|
||||
import org.eclipse.lsp4j.WorkspaceEdit;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.Either;
|
||||
import org.openrewrite.Recipe;
|
||||
import org.openrewrite.Result;
|
||||
import org.openrewrite.java.tree.J;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.JavaCodeAction;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.ORCompilationUnitCache;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.ORDocUtils;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RewriteRefactorings;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.LspClient;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.LspClient.Client;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
import org.springframework.ide.vscode.commons.util.text.IRegion;
|
||||
import org.springframework.ide.vscode.commons.util.text.LanguageId;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
public abstract class AbstractRewriteJavaCodeAction implements JavaCodeAction {
|
||||
@@ -54,17 +69,22 @@ public abstract class AbstractRewriteJavaCodeAction implements JavaCodeAction {
|
||||
return ca;
|
||||
}
|
||||
|
||||
protected WorkspaceEdit applyRecipe(Recipe r, TextDocument doc, org.openrewrite.java.tree.J.CompilationUnit cu) {
|
||||
List<Result> results = r.run(List.of(cu));
|
||||
if (!results.isEmpty() && results.get(0).getAfter() != null) {
|
||||
Optional<TextDocumentEdit> edit = ORDocUtils.computeTextDocEdit(doc, results.get(0));
|
||||
return edit.map(e -> {
|
||||
WorkspaceEdit workspaceEdit = new WorkspaceEdit();
|
||||
workspaceEdit.setDocumentChanges(List.of(Either.forLeft(e)));
|
||||
return workspaceEdit;
|
||||
}).orElse(null);
|
||||
protected WorkspaceEdit applyRecipe(Recipe r, IJavaProject project, List<J.CompilationUnit> cus) {
|
||||
List<Result> results = r.run(cus);
|
||||
List<Either<TextDocumentEdit, ResourceOperation>> edits = results.stream().filter(res -> res.getAfter() != null).map(res -> {
|
||||
URI docUri = project.getLocationUri().resolve(res.getAfter().getSourcePath().toString());
|
||||
TextDocument doc = server.getTextDocumentService().getLatestSnapshot(docUri.toString());
|
||||
if (doc == null) {
|
||||
doc = new TextDocument(docUri.toString(), LanguageId.JAVA, 0, res.getBefore() == null ? "" : res.getBefore().printAll());
|
||||
}
|
||||
return ORDocUtils.computeTextDocEdit(doc, res);
|
||||
}).filter(e -> e.isPresent()).map(e -> e.get()).map(e -> Either.<TextDocumentEdit, ResourceOperation>forLeft(e)).collect(Collectors.toList());
|
||||
if (edits.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
WorkspaceEdit workspaceEdit = new WorkspaceEdit();
|
||||
workspaceEdit.setDocumentChanges(edits);
|
||||
return workspaceEdit;
|
||||
}
|
||||
|
||||
protected static boolean isResolve(CodeActionCapabilities capabilities, String property) {
|
||||
@@ -77,5 +97,58 @@ public abstract class AbstractRewriteJavaCodeAction implements JavaCodeAction {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean isSupported(CodeActionCapabilities capabilities, CodeActionContext context) {
|
||||
// Default case is anything non-quick fix related.
|
||||
if (isResolve(capabilities, "edit")) {
|
||||
if (context.getOnly() != null) {
|
||||
return context.getOnly().contains(CodeActionKind.Refactor);
|
||||
} else {
|
||||
if (LspClient.currentClient() == Client.ECLIPSE) {
|
||||
// Eclipse would have no diagnostics in the context for QuickAssists refactoring. Diagnostics will be around for QuickFix only
|
||||
return context.getDiagnostics().isEmpty();
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
final public List<Either<Command, CodeAction>> getCodeActions(CodeActionCapabilities capabilities,
|
||||
CodeActionContext context, TextDocument doc, IRegion region, IJavaProject project, CompilationUnit cu,
|
||||
ASTNode node) {
|
||||
if (isSupported(capabilities, context)) {
|
||||
return provideCodeActions(context, doc, region, project, cu, node);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
final protected WorkspaceEdit perform(List<?> args, Supplier<Recipe> recipeSupplier) {
|
||||
String docUri = (String) args.get(0);
|
||||
boolean projectWide = ((Boolean) args.get(1)).booleanValue();
|
||||
|
||||
Optional<IJavaProject> project = projectFinder.find(new TextDocumentIdentifier(docUri));
|
||||
|
||||
if (project.isPresent()) {
|
||||
if (projectWide) {
|
||||
return applyRecipe(recipeSupplier.get(), project.get(), orCuCache.getCompiulationUnits(project.get()));
|
||||
} else {
|
||||
return orCuCache.withCompilationUnit(project.get(), URI.create(docUri), cu -> {
|
||||
if (cu == null) {
|
||||
throw new IllegalStateException("Cannot parse Java file: " + docUri);
|
||||
}
|
||||
return applyRecipe(recipeSupplier.get(), project.get(), List.of(cu));
|
||||
});
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
protected abstract List<Either<Command, CodeAction>> provideCodeActions(CodeActionContext context, TextDocument doc,
|
||||
IRegion region, IJavaProject project, CompilationUnit cu, ASTNode node);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*******************************************************************************
|
||||
* 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.codeaction;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.core.dom.ASTNode;
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit;
|
||||
import org.eclipse.jdt.core.dom.IAnnotationBinding;
|
||||
import org.eclipse.jdt.core.dom.IMethodBinding;
|
||||
import org.eclipse.jdt.core.dom.MethodDeclaration;
|
||||
import org.eclipse.lsp4j.CodeAction;
|
||||
import org.eclipse.lsp4j.CodeActionContext;
|
||||
import org.eclipse.lsp4j.Command;
|
||||
import org.eclipse.lsp4j.WorkspaceEdit;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.Either;
|
||||
import org.openrewrite.java.spring.BeanMethodsNotPublic;
|
||||
import org.springframework.ide.vscode.boot.java.Annotations;
|
||||
import org.springframework.ide.vscode.boot.java.reconcilers.BeanMethodNotPublicReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.ORCompilationUnitCache;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RewriteRefactorings;
|
||||
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.java.JavaProjectFinder;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
import org.springframework.ide.vscode.commons.util.text.IRegion;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
public class BeanMethodsNoPublicCodeAction extends AbstractRewriteJavaCodeAction {
|
||||
|
||||
private static final String REMOVE_PUBLIC_FROM_BEAN_METHODS_IN_FILE = "Remove 'public' from @Bean methods in file";
|
||||
private static final String REMOVE_PUBLIC_FROM_BEAN_METHODS_IN_PROJECT = "Remove 'public' from @Bean methods in project";
|
||||
private static final String CODE_ACTION_ID = "RemovePublicFromBeanMethod";
|
||||
|
||||
public BeanMethodsNoPublicCodeAction(SimpleLanguageServer server, JavaProjectFinder projectFinder,
|
||||
RewriteRefactorings rewriteRefactorings, ORCompilationUnitCache orCuCache) {
|
||||
super(server, projectFinder, rewriteRefactorings, orCuCache, CODE_ACTION_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Either<Command, CodeAction>> provideCodeActions(CodeActionContext context, TextDocument doc,
|
||||
IRegion region, IJavaProject project, CompilationUnit cu, ASTNode node) {
|
||||
for (; node != null && !(node instanceof MethodDeclaration); node = node.getParent()) {
|
||||
// nothing
|
||||
}
|
||||
if (node instanceof MethodDeclaration) {
|
||||
MethodDeclaration m = (MethodDeclaration) node;
|
||||
IMethodBinding binding = m.resolveBinding();
|
||||
if (binding != null) {
|
||||
Optional<IAnnotationBinding> beanAnnotationPresent = Arrays.stream(binding.getAnnotations())
|
||||
.filter(a -> Annotations.BEAN.equals(a.getAnnotationType().getQualifiedName()))
|
||||
.findFirst();
|
||||
if (beanAnnotationPresent.isPresent() && BeanMethodNotPublicReconciler.isNotOverridingPublicMethod(binding)) {
|
||||
Version version = SpringProjectUtil.getDependencyVersion(project, SpringProjectUtil.SPRING_BOOT);
|
||||
if (version.getMajor() >= 2) {
|
||||
return List.of(
|
||||
Either.forRight(createCodeAction(REMOVE_PUBLIC_FROM_BEAN_METHODS_IN_FILE, List.of(doc.getUri(), false))),
|
||||
Either.forRight(createCodeAction(REMOVE_PUBLIC_FROM_BEAN_METHODS_IN_PROJECT, List.of(doc.getUri(), true)))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorkspaceEdit perform(List<?> args) {
|
||||
return perform(args, () -> new BeanMethodsNotPublic());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import org.eclipse.jdt.core.dom.IAnnotationBinding;
|
||||
import org.eclipse.jdt.core.dom.TypeDeclaration;
|
||||
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
|
||||
import org.eclipse.lsp4j.CodeAction;
|
||||
import org.eclipse.lsp4j.CodeActionCapabilities;
|
||||
import org.eclipse.lsp4j.CodeActionContext;
|
||||
import org.eclipse.lsp4j.Command;
|
||||
import org.eclipse.lsp4j.TextDocumentIdentifier;
|
||||
import org.eclipse.lsp4j.WorkspaceEdit;
|
||||
@@ -35,7 +35,6 @@ import org.springframework.ide.vscode.boot.java.rewrite.RewriteRefactorings;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
|
||||
import org.springframework.ide.vscode.commons.util.text.IRegion;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
@@ -50,11 +49,9 @@ public class ConvertAutowiredField extends AbstractRewriteJavaCodeAction {
|
||||
|
||||
@Override
|
||||
public WorkspaceEdit perform(List<?> args) {
|
||||
SimpleTextDocumentService documents = server.getTextDocumentService();
|
||||
String docUri = (String) args.get(0);
|
||||
String classFqName = (String) args.get(1);
|
||||
String fieldName = (String) args.get(2);
|
||||
TextDocument doc = documents.getLatestSnapshot(docUri);
|
||||
|
||||
Optional<IJavaProject> project = projectFinder.find(new TextDocumentIdentifier(docUri));
|
||||
|
||||
@@ -63,20 +60,15 @@ public class ConvertAutowiredField extends AbstractRewriteJavaCodeAction {
|
||||
if (cu == null) {
|
||||
throw new IllegalStateException("Cannot parse Java file: " + docUri);
|
||||
}
|
||||
return applyRecipe(new ConvertAutowiredParameterIntoConstructorParameter(classFqName, fieldName), doc, cu);
|
||||
return applyRecipe(new ConvertAutowiredParameterIntoConstructorParameter(classFqName, fieldName), project.get(), List.of(cu));
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Either<Command, CodeAction>> getCodeActions(CodeActionCapabilities capabilities, TextDocument doc, IRegion region, IJavaProject project,
|
||||
CompilationUnit cu, ASTNode node) {
|
||||
// Only supports resolvable code action for now
|
||||
if (!isResolve(capabilities, "edit")) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
protected List<Either<Command, CodeAction>> provideCodeActions(CodeActionContext context, TextDocument doc, IRegion region, IJavaProject project,
|
||||
CompilationUnit cu, ASTNode node) {
|
||||
for (; node != null && !(node instanceof FieldDeclaration); node = node.getParent()) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import org.eclipse.jdt.core.dom.ASTNode;
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit;
|
||||
import org.eclipse.jdt.core.dom.IMethodBinding;
|
||||
import org.eclipse.lsp4j.CodeAction;
|
||||
import org.eclipse.lsp4j.CodeActionCapabilities;
|
||||
import org.eclipse.lsp4j.CodeActionContext;
|
||||
import org.eclipse.lsp4j.Command;
|
||||
import org.eclipse.lsp4j.TextDocumentIdentifier;
|
||||
import org.eclipse.lsp4j.WorkspaceEdit;
|
||||
@@ -34,7 +34,6 @@ import org.springframework.ide.vscode.boot.java.rewrite.RewriteRefactorings;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
|
||||
import org.springframework.ide.vscode.commons.util.text.IRegion;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
@@ -49,10 +48,8 @@ public class NoRequestMapping extends NoRequestMappings {
|
||||
|
||||
@Override
|
||||
public WorkspaceEdit perform(List<?> args) {
|
||||
SimpleTextDocumentService documents = server.getTextDocumentService();
|
||||
String docUri = (String) args.get(0);
|
||||
String matchStr = (String) args.get(1);
|
||||
TextDocument doc = documents.getLatestSnapshot(docUri);
|
||||
|
||||
Optional<IJavaProject> project = projectFinder.find(new TextDocumentIdentifier(docUri));
|
||||
|
||||
@@ -69,19 +66,15 @@ public class NoRequestMapping extends NoRequestMappings {
|
||||
return macther.matches(m.getMethodType());
|
||||
}
|
||||
return false;
|
||||
}), doc, cu);
|
||||
}), project.get(), List.of(cu));
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Either<Command, CodeAction>> getCodeActions(CodeActionCapabilities capabilities, TextDocument doc, IRegion region, IJavaProject project,
|
||||
protected List<Either<Command, CodeAction>> provideCodeActions(CodeActionContext context, TextDocument doc, IRegion region, IJavaProject project,
|
||||
CompilationUnit cu, ASTNode node) {
|
||||
// Only supports resolvable code action for now
|
||||
if (!isResolve(capabilities, "edit")) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return findAppropriateMethodDeclaration(node).map(method -> {
|
||||
String methodMatcher = "* " + method.getName().getIdentifier() + "(*)";
|
||||
IMethodBinding methodBinding = method.resolveBinding();
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.rewrite.codeaction;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -21,9 +20,8 @@ import org.eclipse.jdt.core.dom.CompilationUnit;
|
||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||
import org.eclipse.jdt.core.dom.MethodDeclaration;
|
||||
import org.eclipse.lsp4j.CodeAction;
|
||||
import org.eclipse.lsp4j.CodeActionCapabilities;
|
||||
import org.eclipse.lsp4j.CodeActionContext;
|
||||
import org.eclipse.lsp4j.Command;
|
||||
import org.eclipse.lsp4j.TextDocumentIdentifier;
|
||||
import org.eclipse.lsp4j.WorkspaceEdit;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.Either;
|
||||
import org.openrewrite.java.spring.NoRequestMappingAnnotation;
|
||||
@@ -33,7 +31,6 @@ import org.springframework.ide.vscode.boot.java.rewrite.RewriteRefactorings;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
|
||||
import org.springframework.ide.vscode.commons.util.text.IRegion;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
@@ -70,33 +67,16 @@ public class NoRequestMappings extends AbstractRewriteJavaCodeAction {
|
||||
|
||||
@Override
|
||||
public WorkspaceEdit perform(List<?> args) {
|
||||
SimpleTextDocumentService documents = server.getTextDocumentService();
|
||||
String docUri = (String) args.get(0);
|
||||
TextDocument doc = documents.getLatestSnapshot(docUri);
|
||||
|
||||
Optional<IJavaProject> project = projectFinder.find(new TextDocumentIdentifier(docUri));
|
||||
|
||||
if (project.isPresent()) {
|
||||
return orCuCache.withCompilationUnit(project.get(), URI.create(docUri), cu -> {
|
||||
if (cu == null) {
|
||||
throw new IllegalStateException("Cannot parse Java file: " + docUri);
|
||||
}
|
||||
return applyRecipe(new NoRequestMappingAnnotation(), doc, cu);
|
||||
});
|
||||
}
|
||||
return null;
|
||||
return perform(args, () -> new NoRequestMappingAnnotation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Either<Command, CodeAction>> getCodeActions(CodeActionCapabilities capabilities, TextDocument doc, IRegion region, IJavaProject project,
|
||||
protected List<Either<Command, CodeAction>> provideCodeActions(CodeActionContext context, TextDocument doc, IRegion region, IJavaProject project,
|
||||
CompilationUnit cu, ASTNode node) {
|
||||
// Only supports resolvable code action for now
|
||||
if (!isResolve(capabilities, "edit")) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return findAppropriateMethodDeclaration(node).map(m -> createCodeAction("Replace all @RequestMapping with @GetMapping etc.", List.of(
|
||||
doc.getId().getUri()
|
||||
))).map(ca -> List.of(Either.<Command, CodeAction>forRight(ca))).orElse(Collections.emptyList());
|
||||
return findAppropriateMethodDeclaration(node).map(m -> List.of(
|
||||
Either.<Command, CodeAction>forRight(createCodeAction("Replace @RequestMapping with @GetMapping etc. in file", List.of(doc.getId().getUri(), false))),
|
||||
Either.<Command, CodeAction>forRight(createCodeAction("Replace @RequestMapping with @GetMapping etc. in project", List.of(doc.getId().getUri(), true)))
|
||||
)).orElse(Collections.emptyList());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -10,19 +10,13 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.rewrite.quickfix;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.lsp4j.TextDocumentEdit;
|
||||
import org.eclipse.lsp4j.TextDocumentIdentifier;
|
||||
import org.eclipse.lsp4j.WorkspaceEdit;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.Either;
|
||||
import org.openrewrite.Result;
|
||||
import org.openrewrite.java.spring.NoAutowiredOnConstructor;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.ORAstUtils;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.ORCompilationUnitCache;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.ORDocUtils;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
@@ -58,28 +52,12 @@ public class AutowiredConstructorQuickFixHandler extends RewriteQuickFixHandler
|
||||
}
|
||||
|
||||
private WorkspaceEdit removeUnnecessaryAutowiredFromConstructor(IJavaProject project, TextDocument doc, String classFqName) {
|
||||
String docUri = doc.getId().getUri();
|
||||
return orCuCache.withCompilationUnit(project, URI.create(docUri), cu -> {
|
||||
if (cu == null) {
|
||||
throw new IllegalStateException("Cannot parse Java file: " + docUri);
|
||||
return applyRecipe(orCuCache, new NoAutowiredOnConstructor(), project, doc, t -> {
|
||||
if (t instanceof org.openrewrite.java.tree.J.ClassDeclaration) {
|
||||
org.openrewrite.java.tree.J.ClassDeclaration c = (org.openrewrite.java.tree.J.ClassDeclaration) t;
|
||||
return c.getType() != null && classFqName.equals(c.getType().getFullyQualifiedName());
|
||||
}
|
||||
List<Result> results = ORAstUtils.nodeRecipe(new NoAutowiredOnConstructor(), t -> {
|
||||
if (t instanceof org.openrewrite.java.tree.J.ClassDeclaration) {
|
||||
org.openrewrite.java.tree.J.ClassDeclaration c = (org.openrewrite.java.tree.J.ClassDeclaration) t;
|
||||
return c.getType() != null && classFqName.equals(c.getType().getFullyQualifiedName());
|
||||
}
|
||||
return false;
|
||||
}).run(List.of(cu));
|
||||
if (!results.isEmpty() && results.get(0).getAfter() != null) {
|
||||
Optional<TextDocumentEdit> edit = ORDocUtils.computeTextDocEdit(doc, results.get(0));
|
||||
return edit.map(e -> {
|
||||
WorkspaceEdit workspaceEdit = new WorkspaceEdit();
|
||||
workspaceEdit.setDocumentChanges(List.of(Either.forLeft(e)));
|
||||
return workspaceEdit;
|
||||
}).orElse(null);
|
||||
}
|
||||
|
||||
return null;
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*******************************************************************************
|
||||
* 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.quickfix;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.lsp4j.TextDocumentIdentifier;
|
||||
import org.eclipse.lsp4j.WorkspaceEdit;
|
||||
import org.openrewrite.java.MethodMatcher;
|
||||
import org.openrewrite.java.spring.BeanMethodsNotPublic;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.ORCompilationUnitCache;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
public class BeanMethodNoPublicQuickFixHandler extends RewriteQuickFixHandler {
|
||||
|
||||
final private SimpleLanguageServer server;
|
||||
final private JavaProjectFinder projectFinder;
|
||||
final private ORCompilationUnitCache orCuCache;
|
||||
|
||||
|
||||
public BeanMethodNoPublicQuickFixHandler(SimpleLanguageServer server, JavaProjectFinder projectFinder,
|
||||
ORCompilationUnitCache orCuCache) {
|
||||
this.server = server;
|
||||
this.projectFinder = projectFinder;
|
||||
this.orCuCache = orCuCache;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected WorkspaceEdit perform(List<?> args) {
|
||||
SimpleTextDocumentService documents = server.getTextDocumentService();
|
||||
String docUri = (String) args.get(0);
|
||||
String methodMatch = (String) args.get(1);
|
||||
TextDocument doc = documents.getLatestSnapshot(docUri);
|
||||
|
||||
Optional<IJavaProject> project = projectFinder.find(new TextDocumentIdentifier(docUri));
|
||||
|
||||
if (project.isPresent()) {
|
||||
MethodMatcher matcher = new MethodMatcher(methodMatch);
|
||||
return applyRecipe(orCuCache, new BeanMethodsNotPublic(), project.get(), doc, t -> {
|
||||
if (t instanceof org.openrewrite.java.tree.J.MethodDeclaration) {
|
||||
org.openrewrite.java.tree.J.MethodDeclaration m = (org.openrewrite.java.tree.J.MethodDeclaration) t;
|
||||
return matcher.matches(m.getMethodType());
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -10,11 +10,26 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.rewrite.quickfix;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.eclipse.lsp4j.TextDocumentEdit;
|
||||
import org.eclipse.lsp4j.WorkspaceEdit;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.Either;
|
||||
import org.openrewrite.ExecutionContext;
|
||||
import org.openrewrite.Recipe;
|
||||
import org.openrewrite.Result;
|
||||
import org.openrewrite.java.JavaVisitor;
|
||||
import org.openrewrite.java.tree.J;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.ORAstUtils;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.ORCompilationUnitCache;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.ORDocUtils;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixEdit;
|
||||
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixHandler;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
@@ -34,4 +49,33 @@ public abstract class RewriteQuickFixHandler implements QuickfixHandler {
|
||||
|
||||
abstract protected WorkspaceEdit perform(List<?> l);
|
||||
|
||||
final protected WorkspaceEdit applyRecipe(ORCompilationUnitCache orCuCache, Recipe r, IJavaProject project, TextDocument doc, Predicate<J> nodeFilter) {
|
||||
return doApplyRecipe(orCuCache, ORAstUtils.nodeRecipe(r, nodeFilter), project, doc);
|
||||
}
|
||||
|
||||
final protected WorkspaceEdit applyVisitor(ORCompilationUnitCache orCuCache, JavaVisitor<ExecutionContext> v, IJavaProject project, TextDocument doc, Predicate<J> nodeFilter) {
|
||||
return doApplyRecipe(orCuCache, ORAstUtils.nodeRecipe(v, nodeFilter), project, doc);
|
||||
}
|
||||
|
||||
final protected WorkspaceEdit doApplyRecipe(ORCompilationUnitCache orCuCache, Recipe r, IJavaProject project, TextDocument doc) {
|
||||
String docUri = doc.getId().getUri();
|
||||
return orCuCache.withCompilationUnit(project, URI.create(docUri), cu -> {
|
||||
if (cu == null) {
|
||||
throw new IllegalStateException("Cannot parse Java file: " + docUri);
|
||||
}
|
||||
List<Result> results = r.run(List.of(cu));
|
||||
if (!results.isEmpty() && results.get(0).getAfter() != null) {
|
||||
Optional<TextDocumentEdit> edit = ORDocUtils.computeTextDocEdit(doc, results.get(0));
|
||||
return edit.map(e -> {
|
||||
WorkspaceEdit workspaceEdit = new WorkspaceEdit();
|
||||
workspaceEdit.setDocumentChanges(List.of(Either.forLeft(e)));
|
||||
return workspaceEdit;
|
||||
}).orElse(null);
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user