GH-1068: added quick fix information to diagnostics for the first simple validation - caching probably does not work for that yet

This commit is contained in:
Martin Lippert
2023-07-25 17:36:02 +02:00
parent 7fcb9af8f2
commit 575cd22b68
5 changed files with 58 additions and 6 deletions

View File

@@ -83,6 +83,7 @@ import org.springframework.ide.vscode.commons.languageserver.LanguageServerRunne
import org.springframework.ide.vscode.commons.languageserver.java.FutureProjectFinder;
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.quickfix.QuickfixRegistry;
import org.springframework.ide.vscode.commons.languageserver.util.DocumentEventListenerManager;
import org.springframework.ide.vscode.commons.languageserver.util.LanguageComputer;
import org.springframework.ide.vscode.commons.languageserver.util.LspClient;
@@ -241,8 +242,8 @@ public class BootLanguageServerBootApp {
return new CompilationUnitCache(params.projectFinder, server, params.projectObserver);
}
@Bean JdtReconciler jdtReconciler(CompilationUnitCache cuCache, BootJavaConfig config) {
return new JdtReconciler(cuCache, config);
@Bean JdtReconciler jdtReconciler(CompilationUnitCache cuCache, RewriteRecipeRepository recipeRepo, BootJavaConfig config, SimpleLanguageServer server) {
return new JdtReconciler(cuCache, recipeRepo, server.getQuickfixRegistry(), config);
}
@Bean SpringXMLCompletionEngine xmlCompletionEngine(SimpleLanguageServer server, JavaProjectFinder projectFinder, SpringSymbolIndex symbolIndex, BootJavaConfig config) {

View File

@@ -56,6 +56,7 @@ import org.springframework.ide.vscode.boot.java.handlers.SymbolAddOnInformation;
import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider;
import org.springframework.ide.vscode.boot.java.reconcilers.AnnotationReconciler;
import org.springframework.ide.vscode.boot.java.reconcilers.BeanMethodNotPublicReconciler;
import org.springframework.ide.vscode.boot.java.rewrite.RewriteRecipeRepository;
import org.springframework.ide.vscode.boot.java.utils.DocumentDescriptor;
import org.springframework.ide.vscode.boot.java.utils.SpringFactoriesIndexer;
import org.springframework.ide.vscode.boot.java.utils.SpringIndexer;
@@ -71,6 +72,7 @@ import org.springframework.ide.vscode.commons.languageserver.java.FutureProjectF
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.java.ProjectObserver.Listener;
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.util.ListenerList;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
@@ -101,6 +103,7 @@ public class SpringSymbolIndex implements InitializingBean, SpringIndex {
@Autowired IndexCache cache;
@Autowired FutureProjectFinder futureProjectFinder;
@Autowired SpringMetamodelIndex springIndex;
@Autowired RewriteRecipeRepository recipeRepo;
private static final String QUERY_PARAM_LOCATION_PREFIX = "locationPrefix:";
@@ -246,7 +249,7 @@ public class SpringSymbolIndex implements InitializingBean, SpringIndex {
springIndexerXML = new SpringIndexerXML(handler, namespaceHandler, this.cache, projectFinder());
List<AnnotationReconciler> reconcilers = new ArrayList<>();
reconcilers.add(new BeanMethodNotPublicReconciler());
reconcilers.add(new BeanMethodNotPublicReconciler(recipeRepo, server.getQuickfixRegistry()));
BiFunction<AtomicReference<TextDocument>, BiConsumer<String, Diagnostic>, IProblemCollector> problemCollectorFactory = (docRef, aggregator) -> server.createProblemCollector(docRef, aggregator);
springIndexerJava = new SpringIndexerJava(handler, specificProviders, this.cache, projectFinder(), server.getProgressService(), reconcilers, problemCollectorFactory);

View File

@@ -18,21 +18,41 @@ 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.openrewrite.java.spring.BeanMethodsNotPublic;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.java.Annotations;
import org.springframework.ide.vscode.boot.java.Boot2JavaProblemType;
import org.springframework.ide.vscode.boot.java.rewrite.RewriteRecipeRepository;
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.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.rewrite.config.RecipeCodeActionDescriptor;
import org.springframework.ide.vscode.commons.rewrite.config.RecipeScope;
import org.springframework.ide.vscode.commons.rewrite.java.FixDescriptor;
import org.springframework.ide.vscode.commons.util.text.IDocument;
public class BeanMethodNotPublicReconciler implements AnnotationReconciler {
private static final Logger log = LoggerFactory.getLogger(BeanMethodNotPublicReconciler.class);
private static final String ID = BeanMethodsNotPublic.class.getName();
private static final String LABEL = "Remove 'public' from @Bean method";
private final RewriteRecipeRepository recipeRepo;
private final QuickfixRegistry quickfixRegistry;
public BeanMethodNotPublicReconciler(RewriteRecipeRepository recipeRepo, QuickfixRegistry quickfixRegistry) {
this.recipeRepo = recipeRepo;
this.quickfixRegistry = quickfixRegistry;
}
@Override
public void visit(IJavaProject project, IDocument doc, Annotation node, ITypeBinding typeBinding,
IProblemCollector problemCollector) {
@@ -56,6 +76,8 @@ public class BeanMethodNotPublicReconciler implements AnnotationReconciler {
.orElse(new ReconcileProblemImpl(
Boot2JavaProblemType.JAVA_PUBLIC_BEAN_METHOD, "super special DIAGNOSTICS with public @Bean method",
m.getName().getStartPosition(), m.getName().getLength()));
addQuickFixes(doc.getUri(), problem);
problemCollector.accept(problem);
}
@@ -79,4 +101,28 @@ public class BeanMethodNotPublicReconciler implements AnnotationReconciler {
return !isOverriding(methodBinding) && (methodBinding.getModifiers() & Modifier.PUBLIC) != 0;
}
private void addQuickFixes(String uri, ReconcileProblemImpl problem) {
if (recipeRepo != null && quickfixRegistry != null) {
FixDescriptor fix1 = new FixDescriptor(ID, List.of(uri), LABEL)
// .withRangeScope(m.getMarkers().findFirst(Range.class).get()) // TODO create OpenRewrite range
.withRecipeScope(RecipeScope.NODE);
FixDescriptor fix2 = new FixDescriptor(ID, List.of(uri), RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.FILE))
.withRecipeScope(RecipeScope.FILE);
FixDescriptor fix3 = new FixDescriptor(ID, List.of(uri), RecipeCodeActionDescriptor.buildLabel(LABEL, RecipeScope.PROJECT))
.withRecipeScope(RecipeScope.PROJECT);
QuickfixType quickfixType = quickfixRegistry.getQuickfixType(RewriteRefactorings.REWRITE_RECIPE_QUICKFIX);
if (quickfixType != null && recipeRepo.getRecipe(ID).isPresent()) {
problem.addQuickfix(new QuickfixData<>(quickfixType, fix1, fix1.getLabel()));
problem.addQuickfix(new QuickfixData<>(quickfixType, fix2, fix2.getLabel()));
problem.addQuickfix(new QuickfixData<>(quickfixType, fix3, fix3.getLabel()));
}
}
}
}

View File

@@ -28,8 +28,10 @@ import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.app.BootJavaConfig;
import org.springframework.ide.vscode.boot.java.Annotations;
import org.springframework.ide.vscode.boot.java.handlers.SpelExpressionReconciler;
import org.springframework.ide.vscode.boot.java.rewrite.RewriteRecipeRepository;
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.QuickfixRegistry;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblem;
import org.springframework.ide.vscode.commons.util.text.IDocument;
@@ -58,7 +60,7 @@ public class JdtReconciler implements JavaReconciler {
private BootJavaConfig config;
public JdtReconciler(CompilationUnitCache compilationUnitCache, BootJavaConfig config) {
public JdtReconciler(CompilationUnitCache compilationUnitCache, RewriteRecipeRepository recipeRepo, QuickfixRegistry quickfixRegistry, BootJavaConfig config) {
this.compilationUnitCache = compilationUnitCache;
this.config = config;
config.addListener(evt -> setSpelExpressionSyntaxValidationEnabled(config.isSpelExpressionValidationEnabled()));
@@ -90,7 +92,7 @@ public class JdtReconciler implements JavaReconciler {
new AnnotationParamReconciler(SPRING_CONDITIONAL_ON_EXPRESSION, null, "", "", spelExpressionReconciler),
new AnnotationParamReconciler(SPRING_CONDITIONAL_ON_EXPRESSION, "value", "", "", spelExpressionReconciler),
new BeanMethodNotPublicReconciler()
new BeanMethodNotPublicReconciler(recipeRepo, quickfixRegistry)
};
}

View File

@@ -148,7 +148,7 @@ public class ValueSpelExpressionValidationTest {
problemCollector = new TestProblemCollector();
reconcileEngine = new BootJavaReconcileEngine(projectFinder, new JavaReconciler[] {
new JdtReconciler(compilationUnitCache, config)
new JdtReconciler(compilationUnitCache, null, null, config)
}, server);
}