Improve project reconcile scheduling and classpath change notification

This commit is contained in:
aboyko
2023-06-12 10:16:24 -04:00
parent fae634b778
commit 5ef3c4dfd0
2 changed files with 49 additions and 36 deletions

View File

@@ -17,6 +17,7 @@ import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.runtime.IPath;
@@ -119,20 +120,35 @@ public class ClasspathListenerManager {
Collection<IPath> outputFolders = getOutputFolders(jp);
if (delta.getResourceDeltas() != null && (delta.getFlags() & (IJavaElementDelta.F_CONTENT | IJavaElementDelta.F_CHILDREN)) != 0) {
for (IResourceDelta resourceDelta : delta.getResourceDeltas()) {
if (outputFolders.contains(resourceDelta.getResource().getFullPath())) {
return true;
} else if (outputFolders.stream().anyMatch(of -> resourceDelta.getFullPath().isPrefixOf(of))) {
for (IResourceDelta rd : resourceDelta.getAffectedChildren()) {
if (outputFolders.contains(rd.getResource().getFullPath())) {
return true;
}
}
if (outputFolders.stream().anyMatch(of -> resourceDelta.getFullPath().isPrefixOf(of))) {
return areClassFilesChangedOrAdded(resourceDelta);
}
}
}
return false;
}
private boolean areClassFilesChangedOrAdded(IResourceDelta resourceDelta) {
if (resourceDelta.getResource() instanceof IContainer) {
for (IResourceDelta rd : resourceDelta.getAffectedChildren()) {
if(areClassFilesChangedOrAdded(rd)) {
return true;
}
}
return false;
} else {
if ("class".equals(resourceDelta.getResource().getFileExtension())) {
switch (resourceDelta.getKind()) {
case IResourceDelta.ADDED:
return true;
case IResourceDelta.CHANGED:
return (resourceDelta.getFlags() & IResourceDelta.CONTENT) != 0;
}
}
return false;
}
}
private Collection<IPath> getOutputFolders(IJavaProject jp) {
try {
Set<IPath> outputFolders = new HashSet<>();;
@@ -171,7 +187,12 @@ public class ClasspathListenerManager {
IFile classpathFile = jp.getProject().getFile(IJavaProject.CLASSPATH_FILE_NAME);
for (IResourceDelta resourceDelta : delta.getResourceDeltas()) {
if (classpathFile.equals(resourceDelta.getResource())) {
return true;
switch (resourceDelta.getKind()) {
case IResourceDelta.ADDED:
return true;
case IResourceDelta.CHANGED:
return (resourceDelta.getFlags() & IResourceDelta.CONTENT) != 0;
}
}
}
}

View File

@@ -10,30 +10,22 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.handlers;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.app.BootJavaConfig;
import org.springframework.ide.vscode.boot.common.IJavaProjectReconcileEngine;
import org.springframework.ide.vscode.boot.common.ProjectReconcileScheduler;
import org.springframework.ide.vscode.boot.java.rewrite.RewriteRecipeRepository;
import org.springframework.ide.vscode.commons.java.IClasspathUtil;
import org.springframework.ide.vscode.commons.java.IJavaProject;
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.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
public class BootJavaProjectReconcilerScheduler extends ProjectReconcileScheduler {
private static final Logger log = LoggerFactory.getLogger(BootJavaProjectReconcilerScheduler.class);
private static final List<String> FILES_TO_WATCH_GLOB = List.of("**/*.java");
// private static final List<String> FILES_TO_WATCH_GLOB = List.of("**/*.java");
private ProjectObserver projectObserver;
private BootJavaConfig config;
@@ -88,29 +80,29 @@ public class BootJavaProjectReconcilerScheduler extends ProjectReconcileSchedule
}
});
getServer().getWorkspaceService().getFileObserver().onFilesChanged(FILES_TO_WATCH_GLOB, this::handleFiles);
getServer().getWorkspaceService().getFileObserver().onFilesCreated(FILES_TO_WATCH_GLOB, this::handleFiles);
// getServer().getWorkspaceService().getFileObserver().onFilesChanged(FILES_TO_WATCH_GLOB, this::handleFiles);
// getServer().getWorkspaceService().getFileObserver().onFilesCreated(FILES_TO_WATCH_GLOB, this::handleFiles);
// TODO: index update even happens on every file save. Very expensive to blindly reconcile all projects.
// Need to figure out a check if spring index has any changes
// springIndexer.onUpdate(v -> reconcile());
}
private void handleFiles(String[] files) {
for (String f : files) {
URI uri = URI.create(f);
TextDocumentIdentifier docId = new TextDocumentIdentifier(uri.toASCIIString());
TextDocument doc = getServer().getTextDocumentService().getLatestSnapshot(docId.getUri());
if (doc == null) {
getProjectFinder().find(docId).ifPresent(project -> {
Path p = Paths.get(uri);
if (IClasspathUtil.getSourceFolders(project.getClasspath())
.filter(folder -> p.startsWith(folder.toPath())).findFirst().isPresent()) {
scheduleValidation(project);
}
});
}
}
}
// private void handleFiles(String[] files) {
// for (String f : files) {
// URI uri = URI.create(f);
// TextDocumentIdentifier docId = new TextDocumentIdentifier(uri.toASCIIString());
// TextDocument doc = getServer().getTextDocumentService().getLatestSnapshot(docId.getUri());
// if (doc == null) {
// getProjectFinder().find(docId).ifPresent(project -> {
// Path p = Paths.get(uri);
// if (IClasspathUtil.getSourceFolders(project.getClasspath())
// .filter(folder -> p.startsWith(folder.toPath())).findFirst().isPresent()) {
// scheduleValidation(project);
// }
// });
// }
// }
// }
}