Resurrected project changed event to optimize project reconciling
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2018, 2022 Pivotal, Inc.
|
||||
* Copyright (c) 2018, 2023 Pivotal, 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
|
||||
@@ -11,9 +11,9 @@
|
||||
package org.springframework.ide.vscode.boot.app;
|
||||
|
||||
import java.net.URI;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@@ -38,6 +38,7 @@ import org.springframework.ide.vscode.boot.java.utils.SymbolCache;
|
||||
import org.springframework.ide.vscode.boot.metadata.ProjectBasedPropertyIndexProvider;
|
||||
import org.springframework.ide.vscode.boot.properties.BootPropertiesLanguageServerComponents;
|
||||
import org.springframework.ide.vscode.boot.xml.SpringXMLLanguageServerComponents;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspathUtil;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.CompositeCompletionEngine;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionEngine;
|
||||
@@ -262,26 +263,19 @@ public class BootLanguageServerInitializer implements InitializingBean {
|
||||
}
|
||||
|
||||
components.getReconcileEngine().ifPresent(reconcileEngine -> {
|
||||
Map<IJavaProject, List<TextDocumentIdentifier>> projectsToDocs = new HashMap<>();
|
||||
for (String f : files) {
|
||||
URI uri = URI.create(f);
|
||||
TextDocumentIdentifier docId = new TextDocumentIdentifier(uri.toString());
|
||||
TextDocument doc = server.getTextDocumentService().getLatestSnapshot(docId.getUri());
|
||||
if (doc == null) {
|
||||
projectFinder.find(docId).ifPresent(project -> {
|
||||
List<TextDocumentIdentifier> docIds = projectsToDocs.get(project);
|
||||
if (docIds == null) {
|
||||
docIds = new ArrayList<>();
|
||||
projectsToDocs.put(project, docIds);
|
||||
Path p = Paths.get(uri);
|
||||
if (IClasspathUtil.getSourceFolders(project.getClasspath()).filter(folder -> p.startsWith(folder.toPath())).findFirst().isPresent()) {
|
||||
validateProject(project, reconcileEngine);
|
||||
}
|
||||
docIds.add(docId);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (IJavaProject p : projectsToDocs.keySet()) {
|
||||
validateProject(p, reconcileEngine);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2022 VMware, Inc.
|
||||
* 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
|
||||
@@ -41,7 +41,7 @@ public class BootVersionValidationEngine {
|
||||
|
||||
@Override
|
||||
public void changed(IJavaProject project) {
|
||||
|
||||
validate(project);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016, 2022 Pivotal, Inc.
|
||||
* Copyright (c) 2016, 2023 Pivotal, 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
|
||||
@@ -188,7 +188,7 @@ public class BootJavaLanguageServerComponents implements LanguageServerComponent
|
||||
highlightsEngine = createDocumentHighlightEngine(indexer);
|
||||
documents.onDocumentHighlight(highlightsEngine);
|
||||
|
||||
JdtReconciler jdtReconciler = new JdtReconciler(cuCache);
|
||||
JdtReconciler jdtReconciler = new JdtReconciler(cuCache, config);
|
||||
|
||||
RewriteCompilationUnitCache orCompilationUnitCache = appContext.getBean(RewriteCompilationUnitCache.class);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2022 VMware, Inc.
|
||||
* 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
|
||||
@@ -26,6 +26,7 @@ import org.eclipse.jdt.core.dom.NormalAnnotation;
|
||||
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.boot.app.BootJavaConfig;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.SpelExpressionReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.utils.CompilationUnitCache;
|
||||
import org.springframework.ide.vscode.boot.java.value.Constants;
|
||||
@@ -55,9 +56,12 @@ public class JdtReconciler implements JavaReconciler {
|
||||
private final CompilationUnitCache compilationUnitCache;
|
||||
private final AnnotationReconciler[] reconcilers;
|
||||
private final SpelExpressionReconciler spelExpressionReconciler;
|
||||
|
||||
private BootJavaConfig config;
|
||||
|
||||
public JdtReconciler(CompilationUnitCache compilationUnitCache) {
|
||||
this.compilationUnitCache = compilationUnitCache;
|
||||
public JdtReconciler(CompilationUnitCache compilationUnitCache, BootJavaConfig config) {
|
||||
this.compilationUnitCache = compilationUnitCache;
|
||||
this.config = config;
|
||||
this.spelExpressionReconciler = new SpelExpressionReconciler();
|
||||
|
||||
this.reconcilers = new AnnotationReconciler[] {
|
||||
@@ -95,7 +99,6 @@ public class JdtReconciler implements JavaReconciler {
|
||||
@Override
|
||||
public void reconcile(IJavaProject project, final IDocument doc, final IProblemCollector problemCollector) {
|
||||
|
||||
log.info("reconciling (JDT): " + project.getElementName() + " - " + doc.getUri());
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
URI uri = URI.create(doc.getUri());
|
||||
@@ -107,7 +110,7 @@ public class JdtReconciler implements JavaReconciler {
|
||||
});
|
||||
|
||||
long end = System.currentTimeMillis();
|
||||
log.info("reconciling (JDT): " + project.getElementName() + " done in " + (end - start) + "ms");
|
||||
log.info("reconciling (JDT): " + doc.getUri() + " done in " + (end - start) + "ms");
|
||||
}
|
||||
|
||||
private void reconcileAST(IJavaProject project, IDocument doc, CompilationUnit cu, IProblemCollector problemCollector) {
|
||||
@@ -159,7 +162,15 @@ public class JdtReconciler implements JavaReconciler {
|
||||
@Override
|
||||
public Map<IDocument, Collection<ReconcileProblem>> reconcile(IJavaProject project, List<TextDocument> docs,
|
||||
Function<TextDocument, IProblemCollector> problemCollectorFactory) {
|
||||
log.info("reconciling (JDT, multiple docs): " + project.getElementName() + " - " + docs.size());
|
||||
|
||||
if (config.isRewriteReconcileEnabled()) {
|
||||
// long start = System.currentTimeMillis();
|
||||
//
|
||||
//
|
||||
//
|
||||
// long end = System.currentTimeMillis();
|
||||
// log.info("reconciling project (JDT): " + project.getElementName() + " - " + docs.size() + " done in " + (end - start) + "ms");
|
||||
}
|
||||
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@@ -61,8 +61,8 @@ public class RewriteCompilationUnitCache implements DocumentContentProvider, Dis
|
||||
private final SimpleTextDocumentService documentService;
|
||||
|
||||
private final Cache<URI, CompletableFuture<CompilationUnit>> uriToCu;
|
||||
private final Cache<IJavaProject, Set<URI>> projectToDocs;
|
||||
private final Cache<IJavaProject, JavaParser> javaParsers;
|
||||
private final Cache<URI, Set<URI>> projectToDocs;
|
||||
private final Cache<URI, JavaParser> javaParsers;
|
||||
|
||||
public RewriteCompilationUnitCache(JavaProjectFinder projectFinder, SimpleLanguageServer server, ProjectObserver projectObserver) {
|
||||
// this.projectFinder = projectFinder;
|
||||
@@ -87,11 +87,10 @@ public class RewriteCompilationUnitCache implements DocumentContentProvider, Dis
|
||||
Optional<IJavaProject> project = projectFinder.find(new TextDocumentIdentifier(uri.toString()));
|
||||
if (project.isPresent()) {
|
||||
|
||||
JavaParser parser = javaParsers.getIfPresent(project.get());
|
||||
JavaParser parser = javaParsers.getIfPresent(project.get().getLocationUri());
|
||||
if (parser != null) {
|
||||
parser.reset();
|
||||
}
|
||||
// javaParsers.invalidate(project.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -155,7 +154,7 @@ public class RewriteCompilationUnitCache implements DocumentContentProvider, Dis
|
||||
|
||||
private JavaParser loadJavaParser(IJavaProject project) {
|
||||
try {
|
||||
return javaParsers.get(project, () -> ORAstUtils.createJavaParser(project));
|
||||
return javaParsers.get(project.getLocationUri(), () -> ORAstUtils.createJavaParser(project));
|
||||
} catch (ExecutionException e) {
|
||||
logger.error("{}", e);
|
||||
return null;
|
||||
@@ -170,12 +169,12 @@ public class RewriteCompilationUnitCache implements DocumentContentProvider, Dis
|
||||
private void invalidateProject(IJavaProject project) {
|
||||
logger.info("CU Cache: invalidate project <{}>", project.getElementName());
|
||||
|
||||
Set<URI> docUris = projectToDocs.getIfPresent(project);
|
||||
Set<URI> docUris = projectToDocs.getIfPresent(project.getLocationUri());
|
||||
if (docUris != null) {
|
||||
uriToCu.invalidateAll(docUris);
|
||||
projectToDocs.invalidate(project);
|
||||
projectToDocs.invalidate(project.getLocationUri());
|
||||
}
|
||||
javaParsers.invalidate(project);
|
||||
javaParsers.invalidate(project.getLocationUri());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -240,7 +239,7 @@ public class RewriteCompilationUnitCache implements DocumentContentProvider, Dis
|
||||
CompilationUnit cu = cus.get(0);
|
||||
|
||||
if (cu != null) {
|
||||
projectToDocs.get(project, () -> new HashSet<>()).add(uri);
|
||||
projectToDocs.get(project.getLocationUri(), () -> new HashSet<>()).add(uri);
|
||||
return cu;
|
||||
} else {
|
||||
throw new IllegalStateException("Failed to parse Java source");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2022 VMware, Inc.
|
||||
* 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
|
||||
@@ -79,7 +79,6 @@ public class RewriteReconciler implements JavaReconciler {
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("reconciling (OpenRewrite): " + project.getElementName() + " - " + doc.getUri());
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
@@ -104,7 +103,7 @@ public class RewriteReconciler implements JavaReconciler {
|
||||
}
|
||||
|
||||
long end = System.currentTimeMillis();
|
||||
log.info("reconciling (OpenRewrite): " + project.getElementName() + " done in " + (end - start) + "ms");
|
||||
log.info("reconciling (OpenRewrite): " + doc.getUri() + " done in " + (end - start) + "ms");
|
||||
}
|
||||
|
||||
private List<ReconcileProblem> createProblems(IDocument doc, FixAssistMarker m, J astNode) {
|
||||
@@ -143,7 +142,10 @@ public class RewriteReconciler implements JavaReconciler {
|
||||
public Map<IDocument, Collection<ReconcileProblem>> reconcile(IJavaProject project, List<TextDocument> docs,
|
||||
Function<TextDocument, IProblemCollector> problemCollectorFactory) {
|
||||
|
||||
log.info("reconciling (OpenRewrite, multiple docs): " + project.getElementName() + " - " + docs.size());
|
||||
if (!config.isRewriteReconcileEnabled()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
Map<IDocument, Collection<ReconcileProblem>> allProblems = new HashMap<>();
|
||||
@@ -165,7 +167,7 @@ public class RewriteReconciler implements JavaReconciler {
|
||||
allProblems.putAll(doReconcile(project, testSources, problemCollectorFactory, javaParser));
|
||||
|
||||
long end = System.currentTimeMillis();
|
||||
log.info("reconciling (OpenRewrite, multiple docs): " + project.getElementName() + " - " + docs.size() + " done in " + (end - start) + "ms");
|
||||
log.info("reconciling project (OpenRewrite): " + project.getElementName() + " - " + docs.size() + " done in " + (end - start) + "ms");
|
||||
|
||||
return allProblems;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017, 2022 Pivotal, Inc.
|
||||
* Copyright (c) 2017, 2023 Pivotal, 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
|
||||
@@ -68,8 +68,8 @@ public final class CompilationUnitCache implements DocumentContentProvider {
|
||||
private final SimpleTextDocumentService documentService;
|
||||
|
||||
private final Cache<URI, CompletableFuture<CompilationUnit>> uriToCu;
|
||||
private final Cache<IJavaProject, Set<URI>> projectToDocs;
|
||||
private final Cache<IJavaProject, Tuple2<List<Classpath>, INameEnvironmentWithProgress>> lookupEnvCache;
|
||||
private final Cache<URI, Set<URI>> projectToDocs;
|
||||
private final Cache<URI, Tuple2<List<Classpath>, INameEnvironmentWithProgress>> lookupEnvCache;
|
||||
|
||||
public CompilationUnitCache(JavaProjectFinder projectFinder, SimpleLanguageServer server, ProjectObserver projectObserver) {
|
||||
this.projectFinder = projectFinder;
|
||||
@@ -224,7 +224,7 @@ public final class CompilationUnitCache implements DocumentContentProvider {
|
||||
|
||||
if (cu != null) {
|
||||
try {
|
||||
projectToDocs.get(project, () -> new HashSet<>()).add(uri);
|
||||
projectToDocs.get(project.getLocationUri(), () -> new HashSet<>()).add(uri);
|
||||
|
||||
logger.debug("CU Cache: start work on AST for {}", uri.toString());
|
||||
return requestor.apply(cu);
|
||||
@@ -287,7 +287,7 @@ public final class CompilationUnitCache implements DocumentContentProvider {
|
||||
|
||||
private Tuple2<List<Classpath>, INameEnvironmentWithProgress> loadLookupEnvTuple(IJavaProject project) {
|
||||
try {
|
||||
return lookupEnvCache.get(project, () -> {
|
||||
return lookupEnvCache.get(project.getLocationUri(), () -> {
|
||||
List<Classpath> classpaths = createClasspath(getClasspathEntries(project));
|
||||
INameEnvironmentWithProgress environment = CUResolver.createLookupEnvironment(classpaths.toArray(new Classpath[classpaths.size()]));
|
||||
return Tuples.of(classpaths, environment);
|
||||
@@ -320,12 +320,12 @@ public final class CompilationUnitCache implements DocumentContentProvider {
|
||||
private void invalidateProject(IJavaProject project) {
|
||||
logger.debug("CU Cache: invalidate project <{}>", project.getElementName());
|
||||
|
||||
Set<URI> docUris = projectToDocs.getIfPresent(project);
|
||||
Set<URI> docUris = projectToDocs.getIfPresent(project.getLocationUri());
|
||||
if (docUris != null) {
|
||||
uriToCu.invalidateAll(docUris);
|
||||
projectToDocs.invalidate(project);
|
||||
projectToDocs.invalidate(project.getLocationUri());
|
||||
}
|
||||
lookupEnvCache.invalidate(project);
|
||||
lookupEnvCache.invalidate(project.getLocationUri());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2018, 2019 Pivotal, Inc.
|
||||
* Copyright (c) 2018, 2023 Pivotal, 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
|
||||
@@ -10,6 +10,7 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.utils;
|
||||
|
||||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
@@ -41,7 +42,7 @@ public class SpringLiveChangeDetectionWatchdog {
|
||||
private final SourceLinks sourceLinks;
|
||||
|
||||
private final ChangeDetectionHistory changeHistory;
|
||||
private final Set<IJavaProject> observedProjects;
|
||||
private final Set<URI> observedProjects;
|
||||
|
||||
private boolean changeDetectionEnabled = false;
|
||||
private ScheduledThreadPoolExecutor timer;
|
||||
@@ -54,7 +55,7 @@ public class SpringLiveChangeDetectionWatchdog {
|
||||
Duration pollingInterval,
|
||||
SourceLinks sourceLinks
|
||||
) {
|
||||
this.observedProjects = new HashSet<>();
|
||||
this.observedProjects = new HashSet<URI>();
|
||||
|
||||
this.server = server;
|
||||
|
||||
@@ -68,12 +69,12 @@ public class SpringLiveChangeDetectionWatchdog {
|
||||
|
||||
@Override
|
||||
public void deleted(IJavaProject project) {
|
||||
observedProjects.remove(project);
|
||||
observedProjects.remove(project.getLocationUri());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void created(IJavaProject project) {
|
||||
observedProjects.add(project);
|
||||
observedProjects.add(project.getLocationUri());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -350,15 +350,19 @@ public class JdtLsProjectCache implements InitializableJavaProjectsService, Serv
|
||||
log.debug("deleted = false");
|
||||
URI projectUri = new URI(uri);
|
||||
ClasspathData classpath = new ClasspathData(event.name, event.classpath.getEntries());
|
||||
IProjectBuild projectBuild = from(event.projectBuild);
|
||||
IJavaProject oldProject = table.get(uri);
|
||||
if (oldProject != null && classpath.equals(oldProject.getClasspath())) {
|
||||
// nothing has changed
|
||||
return;
|
||||
}
|
||||
IProjectBuild projectBuild = from(event.projectBuild);
|
||||
IJavaProject newProject = IS_JANDEX_INDEX
|
||||
? new JavaProject(getFileObserver(), projectUri, classpath,
|
||||
JdtLsProjectCache.this, projectBuild)
|
||||
: new JdtLsJavaProject(server.getClient(), projectUri, classpath, JdtLsProjectCache.this, projectBuild);
|
||||
IJavaProject oldProject = table.put(uri, newProject);
|
||||
table.put(uri, newProject);
|
||||
if (oldProject != null) {
|
||||
notifyDelete(oldProject);
|
||||
notifyCreated(newProject);
|
||||
notifyChanged(newProject);
|
||||
} else {
|
||||
notifyCreated(newProject);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2020, 2022 Pivotal, Inc.
|
||||
* Copyright (c) 2020, 2023 Pivotal, 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
|
||||
@@ -35,6 +35,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.ide.vscode.boot.app.BootJavaConfig;
|
||||
import org.springframework.ide.vscode.boot.app.BootLanguageServerParams;
|
||||
import org.springframework.ide.vscode.boot.bootiful.AdHocPropertyHarnessTestConf;
|
||||
import org.springframework.ide.vscode.boot.bootiful.BootLanguageServerTest;
|
||||
@@ -75,6 +76,7 @@ public class ValueSpelExpressionValidationTest {
|
||||
@Autowired private JavaProjectFinder projectFinder;
|
||||
@Autowired private CompilationUnitCache compilationUnitCache;
|
||||
@Autowired private SimpleLanguageServer server;
|
||||
@Autowired private BootJavaConfig config;
|
||||
|
||||
private File directory;
|
||||
private String docUri;
|
||||
@@ -146,7 +148,7 @@ public class ValueSpelExpressionValidationTest {
|
||||
|
||||
problemCollector = new TestProblemCollector();
|
||||
reconcileEngine = new BootJavaReconcileEngine(projectFinder, new JavaReconciler[] {
|
||||
new JdtReconciler(compilationUnitCache)
|
||||
new JdtReconciler(compilationUnitCache, config)
|
||||
}, server.getTextDocumentService(), null);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user