DocumentReferenceManagerImpl: traverse deleted directories recursively out of EDT, and only the in-memory parts (IDEA-227209)

GitOrigin-RevId: 2ff47a3a83caf5832075d699e584c703286ff951
This commit is contained in:
Peter Gromov
2019-11-21 21:01:25 +00:00
committed by intellij-monorepo-bot
parent 2b44936e45
commit 0b019644cd
@@ -6,10 +6,11 @@ import com.intellij.openapi.command.undo.DocumentReference;
import com.intellij.openapi.command.undo.DocumentReferenceManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.AsyncFileListener;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
import com.intellij.openapi.vfs.newvfs.events.VFileCreateEvent;
import com.intellij.openapi.vfs.newvfs.events.VFileDeleteEvent;
@@ -17,7 +18,6 @@ import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
import com.intellij.reference.SoftReference;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.NotNullList;
import com.intellij.util.messages.MessageBus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;
@@ -27,54 +27,44 @@ import java.util.List;
import java.util.Map;
public final class DocumentReferenceManagerImpl extends DocumentReferenceManager {
private static final Key<List<VirtualFile>> DELETED_FILES = Key.create(DocumentReferenceManagerImpl.class.getName() + ".DELETED_FILES");
private final Map<Document, DocumentReference> myDocToRef = ContainerUtil.createWeakKeyWeakValueMap();
private static final Key<Reference<DocumentReference>> FILE_TO_REF_KEY = Key.create("FILE_TO_REF_KEY");
private static final Key<DocumentReference> FILE_TO_STRONG_REF_KEY = Key.create("FILE_TO_STRONG_REF_KEY");
private final Map<FilePath, DocumentReference> myDeletedFilePathToRef = ContainerUtil.createWeakValueMap();
DocumentReferenceManagerImpl(@NotNull MessageBus messageBus) {
messageBus.connect().subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() {
DocumentReferenceManagerImpl() {
VirtualFileManager.getInstance().addAsyncFileListener(new AsyncFileListener() {
@Override
public void before(@NotNull List<? extends VFileEvent> events) {
public ChangeApplier prepareChange(@NotNull List<? extends VFileEvent> events) {
List<VirtualFile> deletedFiles = new NotNullList<>();
for (VFileEvent event : events) {
if (event instanceof VFileDeleteEvent) {
beforeFileDeletion((VFileDeleteEvent)event);
collectDeletedFiles(((VFileDeleteEvent)event).getFile(), deletedFiles);
}
}
return new ChangeApplier() {
@Override
public void afterVfsChange() {
for (VirtualFile each : deletedFiles) {
fileDeleted(each);
}
for (VFileEvent event : events) {
if (event instanceof VFileCreateEvent) {
fileCreated((VFileCreateEvent)event);
}
}
}
};
}
@Override
public void after(@NotNull List<? extends VFileEvent> events) {
for (VFileEvent event : events) {
if (event instanceof VFileCreateEvent) {
fileCreated((VFileCreateEvent)event);
}
else if (event instanceof VFileDeleteEvent) {
fileDeleted((VFileDeleteEvent)event);
}
}
}
private void beforeFileDeletion(@NotNull VFileDeleteEvent event) {
VirtualFile f = event.getFile();
f.putUserData(DELETED_FILES, collectDeletedFiles(f, new NotNullList<>()));
}
private void fileDeleted(@NotNull VFileDeleteEvent event) {
VirtualFile f = event.getFile();
List<VirtualFile> files = f.getUserData(DELETED_FILES);
f.putUserData(DELETED_FILES, null);
assert files != null : f;
for (VirtualFile each : files) {
DocumentReference ref = SoftReference.dereference(each.getUserData(FILE_TO_REF_KEY));
each.putUserData(FILE_TO_REF_KEY, null);
if (ref != null) {
myDeletedFilePathToRef.put(new FilePath(each.getUrl()), ref);
}
private void fileDeleted(VirtualFile each) {
DocumentReference ref = SoftReference.dereference(each.getUserData(FILE_TO_REF_KEY));
each.putUserData(FILE_TO_REF_KEY, null);
if (ref != null) {
myDeletedFilePathToRef.put(new FilePath(each.getUrl()), ref);
}
}
@@ -86,22 +76,21 @@ public final class DocumentReferenceManagerImpl extends DocumentReferenceManager
((DocumentReferenceByVirtualFile)ref).update(f);
}
}
});
}, ApplicationManager.getApplication());
}
@NotNull
private static List<VirtualFile> collectDeletedFiles(@NotNull VirtualFile f, @NotNull List<VirtualFile> files) {
if (!(f instanceof NewVirtualFile)) return files;
private static void collectDeletedFiles(@NotNull VirtualFile f, @NotNull List<VirtualFile> files) {
if (!(f instanceof NewVirtualFile)) return;
ProgressManager.checkCanceled();
if (!f.isDirectory()) {
files.add(f);
}
else {
for (VirtualFile each : ((NewVirtualFile)f).iterInDbChildren()) {
for (VirtualFile each : ((NewVirtualFile)f).getCachedChildren()) {
collectDeletedFiles(each, files);
}
}
return files;
}
@NotNull