Switch Rewrite code action handler to JDT reconcilers
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
/*******************************************************************************
|
||||
* 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.languageserver.reconcile;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class BasicProblemCollector implements IProblemCollector {
|
||||
|
||||
private final Collection<ReconcileProblem> problems;
|
||||
|
||||
public BasicProblemCollector(Collection<ReconcileProblem> problems) {
|
||||
this.problems = problems;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginCollecting() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endCollecting() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(ReconcileProblem problem) {
|
||||
problems.add(problem);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,12 +14,13 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
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.RewriteReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RewriteRefactorings;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.SpringBootUpgrade;
|
||||
import org.springframework.ide.vscode.boot.java.utils.CompilationUnitCache;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
|
||||
@@ -42,8 +43,8 @@ public class RewriteConfig {
|
||||
}
|
||||
|
||||
@ConditionalOnBean(RewriteRecipeRepository.class)
|
||||
@Bean RewriteCodeActionHandler rewriteCodeActionHandler(RewriteCompilationUnitCache cuCache, RewriteRecipeRepository recipeRepo, BootJavaConfig config) {
|
||||
return new RewriteCodeActionHandler(cuCache, recipeRepo, config);
|
||||
@Bean RewriteCodeActionHandler rewriteCodeActionHandler(CompilationUnitCache cuCache, BootJavaConfig config, JdtReconciler jdtReconciler, SimpleLanguageServer server) {
|
||||
return new RewriteCodeActionHandler(cuCache, config, jdtReconciler, server.getQuickfixRegistry());
|
||||
}
|
||||
|
||||
@ConditionalOnBean(RewriteRecipeRepository.class)
|
||||
|
||||
@@ -24,24 +24,21 @@ import org.eclipse.lsp4j.CodeActionResolveSupportCapabilities;
|
||||
import org.eclipse.lsp4j.Command;
|
||||
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.Either;
|
||||
import org.openrewrite.ExecutionContext;
|
||||
import org.openrewrite.InMemoryExecutionContext;
|
||||
import org.openrewrite.Tree;
|
||||
import org.openrewrite.java.JavaIsoVisitor;
|
||||
import org.openrewrite.java.tree.J;
|
||||
import org.openrewrite.java.tree.J.CompilationUnit;
|
||||
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.handlers.JavaCodeActionHandler;
|
||||
import org.springframework.ide.vscode.boot.java.reconcilers.JdtReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.utils.CompilationUnitCache;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
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.BasicProblemCollector;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblem;
|
||||
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.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.util.text.IDocument;
|
||||
import org.springframework.ide.vscode.commons.util.text.IRegion;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
@@ -49,15 +46,18 @@ public class RewriteCodeActionHandler implements JavaCodeActionHandler {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(RewriteCodeActionHandler.class);
|
||||
|
||||
final private RewriteCompilationUnitCache cuCache;
|
||||
final private RewriteRecipeRepository recipeRepo;
|
||||
final private CompilationUnitCache cuCache;
|
||||
final private JdtReconciler jdtReconciler;
|
||||
|
||||
private BootJavaConfig config;
|
||||
|
||||
public RewriteCodeActionHandler(RewriteCompilationUnitCache cuCache, RewriteRecipeRepository recipeRepo, BootJavaConfig config) {
|
||||
private QuickfixRegistry quickfixRegistry;
|
||||
|
||||
public RewriteCodeActionHandler(CompilationUnitCache cuCache, BootJavaConfig config, JdtReconciler jdtReconciler, QuickfixRegistry quickfixRegistry) {
|
||||
this.cuCache = cuCache;
|
||||
this.recipeRepo = recipeRepo;
|
||||
this.config = config;
|
||||
this.jdtReconciler = jdtReconciler;
|
||||
this.quickfixRegistry = quickfixRegistry;
|
||||
}
|
||||
|
||||
protected static boolean isResolve(CodeActionCapabilities capabilities, String property) {
|
||||
@@ -97,47 +97,33 @@ public class RewriteCodeActionHandler implements JavaCodeActionHandler {
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
List<RecipeCodeActionDescriptor> descriptors = recipeRepo.getCodeActionRecipeDescriptors().stream()
|
||||
// If Recipe not present - don't show quick assist as it won't be handled without the Rewrite recipe present
|
||||
.filter(d -> d.isApplicable(project))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
|
||||
if (isSupported(capabilities, context)) {
|
||||
CompilationUnit cu = cuCache.getCU(project, URI.create(doc.getUri()));
|
||||
if (cu != null) {
|
||||
|
||||
cu = recipeRepo.mark(project, descriptors, cu);
|
||||
|
||||
List<CodeAction> codeActions = new ArrayList<>();
|
||||
new JavaIsoVisitor<ExecutionContext>() {
|
||||
public J visit(Tree tree, ExecutionContext ctx) {
|
||||
if (tree == null) {
|
||||
return null;
|
||||
}
|
||||
if (tree instanceof J) {
|
||||
J node = (J) tree;
|
||||
Range range = node.getMarkers().findFirst(Range.class).orElse(null);
|
||||
if (range != null
|
||||
&& range.getStart().getOffset() <= region.getOffset()
|
||||
&& region.getOffset() + region.getLength() <= range.getEnd().getOffset()) {
|
||||
|
||||
for (FixAssistMarker m : node.getMarkers().findAll(FixAssistMarker.class)) {
|
||||
for (CodeAction ca : createCodeActions(doc, m, node)) {
|
||||
codeActions.add(ca);
|
||||
}
|
||||
URI uri = URI.create(doc.getUri());
|
||||
final QuickfixType rewriteFixType = quickfixRegistry.getQuickfixType(RewriteRefactorings.REWRITE_RECIPE_QUICKFIX);
|
||||
if (isSupported(capabilities, context) && rewriteFixType != null) {
|
||||
List<CodeAction> codeActions = cuCache.withCompilationUnit(project, uri, cu -> {
|
||||
try {
|
||||
List<CodeAction> cas = new ArrayList<>();
|
||||
List<ReconcileProblem> problems = new ArrayList<>();
|
||||
BasicProblemCollector problemsCollector = new BasicProblemCollector(problems);
|
||||
jdtReconciler.reconcile(project, uri, cu, problemsCollector, true);
|
||||
for (ReconcileProblem p : problems) {
|
||||
if (p.getOffset() <= region.getOffset() && p.getOffset() + p.getLength() >= region.getOffset() + region.getLength()) {
|
||||
for (QuickfixData<?> qf : p.getQuickfixes()) {
|
||||
if (qf.params instanceof FixDescriptor) {
|
||||
cas.add(createCodeActionFromScope((FixDescriptor) qf.params));
|
||||
}
|
||||
return super.visit(tree, ctx);
|
||||
} else {
|
||||
return (J) tree;
|
||||
}
|
||||
}
|
||||
return (J) tree;
|
||||
};
|
||||
}.visitNonNull(cu, new InMemoryExecutionContext());
|
||||
return codeActions.stream().map(ca -> Either.<Command, CodeAction>forRight(ca)).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
return cas;
|
||||
} catch (Exception e) {
|
||||
log.error("", e);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
});
|
||||
|
||||
return codeActions.stream().map(ca -> Either.<Command, CodeAction>forRight(ca)).collect(Collectors.toList());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("", e);
|
||||
@@ -145,18 +131,7 @@ public class RewriteCodeActionHandler implements JavaCodeActionHandler {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private CodeAction[] createCodeActions(IDocument doc, FixAssistMarker m, J astNode) {
|
||||
if (astNode != null) {
|
||||
return m.getFixes().stream()
|
||||
.filter(d -> recipeRepo.getRecipe(d.getRecipeId()) != null)
|
||||
.map(d -> createCodeActionFromScope(doc, d))
|
||||
.toArray(CodeAction[]::new);
|
||||
}
|
||||
return new CodeAction[0];
|
||||
}
|
||||
|
||||
private CodeAction createCodeActionFromScope(IDocument doc,
|
||||
FixDescriptor d) {
|
||||
private CodeAction createCodeActionFromScope(FixDescriptor d) {
|
||||
CodeAction ca = new CodeAction();
|
||||
ca.setKind(CodeActionKind.Refactor);
|
||||
ca.setTitle(d.getLabel());
|
||||
|
||||
Reference in New Issue
Block a user