diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerBootApp.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerBootApp.java index 9e900356b..8bca3d69b 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerBootApp.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerBootApp.java @@ -268,8 +268,8 @@ public class BootLanguageServerBootApp { return new CompilationUnitCache(params.projectFinder, server, params.projectObserver); } - @Bean JdtReconciler jdtReconciler(CompilationUnitCache cuCache, BootJavaConfig config, SimpleLanguageServer server, JdtAstReconciler[] reconcilers) { - return new JdtReconciler(cuCache, config, reconcilers); + @Bean JdtReconciler jdtReconciler(CompilationUnitCache cuCache, BootJavaConfig config, SimpleLanguageServer server, JdtAstReconciler[] reconcilers, ProjectObserver projectObserver) { + return new JdtReconciler(cuCache, config, reconcilers, projectObserver); } @Bean SpringXMLCompletionEngine xmlCompletionEngine(SimpleLanguageServer server, JavaProjectFinder projectFinder, SpringSymbolIndex symbolIndex, BootJavaConfig config) { diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/reconcilers/JdtReconciler.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/reconcilers/JdtReconciler.java index ea6fac9f3..d7d3c8fa9 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/reconcilers/JdtReconciler.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/reconcilers/JdtReconciler.java @@ -16,6 +16,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.eclipse.jdt.core.dom.ASTVisitor; import org.eclipse.jdt.core.dom.CompilationUnit; @@ -25,6 +26,7 @@ import org.springframework.ide.vscode.boot.app.BootJavaConfig; import org.springframework.ide.vscode.boot.java.utils.CompilationUnitCache; import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.java.SpringProjectUtil; +import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver; 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; @@ -51,16 +53,28 @@ public class JdtReconciler implements JavaReconciler { private final JdtAstReconciler[] reconcilers; private BootJavaConfig config; + private final ConcurrentHashMap> applicableReconcilersCache; + private long stats_timer; private long stats_counter; - public JdtReconciler(CompilationUnitCache compilationUnitCache, BootJavaConfig config, JdtAstReconciler[] reconcilers) { + public JdtReconciler(CompilationUnitCache compilationUnitCache, BootJavaConfig config, JdtAstReconciler[] reconcilers, ProjectObserver projectObserver) { this.compilationUnitCache = compilationUnitCache; this.config = config; this.reconcilers = reconcilers; this.stats_timer = 0; this.stats_counter = 0; + + this.applicableReconcilersCache = new ConcurrentHashMap<>(); + + projectObserver.addListener(ProjectObserver.onAny(project -> { + invalidateApplicableReconcilersCache(project); + })); + + config.addListener(event -> { + invalidateApplicableReconcilersCache(null); + }); } @Override @@ -128,7 +142,28 @@ public class JdtReconciler implements JavaReconciler { } } + @Override + public Map> reconcile(IJavaProject project, List docs, + Runnable incrementProgress) { + return Collections.emptyMap(); + } + private List getApplicableReconcilers(IJavaProject project) { + return this.applicableReconcilersCache.computeIfAbsent(project.getElementName(), (name) -> { + return computeApplicableReconcilers(project); + }); + } + + private void invalidateApplicableReconcilersCache(IJavaProject project) { + if (project != null) { + this.applicableReconcilersCache.remove(project.getElementName()); + } + else { + this.applicableReconcilersCache.clear(); + } + } + + private List computeApplicableReconcilers(IJavaProject project) { List applicableReconcilers = new ArrayList<>(reconcilers.length); for (JdtAstReconciler r : reconcilers) { switch (config.getProblemApplicability(r.getProblemType())) { @@ -147,13 +182,6 @@ public class JdtReconciler implements JavaReconciler { } return applicableReconcilers; } - - - @Override - public Map> reconcile(IJavaProject project, List docs, - Runnable incrementProgress) { - return Collections.emptyMap(); - } public long getStatsTimer() { return stats_timer; diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/value/test/ValueSpelExpressionValidationTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/value/test/ValueSpelExpressionValidationTest.java index 470a9e7f4..08eaf2395 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/value/test/ValueSpelExpressionValidationTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/value/test/ValueSpelExpressionValidationTest.java @@ -50,6 +50,7 @@ import org.springframework.ide.vscode.boot.java.reconcilers.JavaReconciler; import org.springframework.ide.vscode.boot.java.reconcilers.JdtAstReconciler; import org.springframework.ide.vscode.boot.java.reconcilers.JdtReconciler; import org.springframework.ide.vscode.boot.java.utils.CompilationUnitCache; +import org.springframework.ide.vscode.boot.java.utils.test.MockProjectObserver; import org.springframework.ide.vscode.boot.metadata.ValueProviderRegistry; import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder; @@ -160,7 +161,7 @@ public class ValueSpelExpressionValidationTest { reconcileEngine = new BootJavaReconcileEngine(projectFinder, new JavaReconciler[] { new JdtReconciler(compilationUnitCache, config, new JdtAstReconciler[] { new AnnotationNodeReconciler(config) - }) + }, new MockProjectObserver()) }); }