From 9e94a4253d191abcbdcc23d3b33a6bc2a55e1dae Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 7 Sep 2016 14:10:16 +0300 Subject: [PATCH] make VirtualFilePointerManager more responsive to VFS changes to update virtual file pointers sooner to fix EA-87976 - assert: RootIndex.ensureValid --- .../impl/VirtualFilePointerManagerImpl.java | 8 ++++ .../vfs/impl/VirtualFilePointerTest.java | 45 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java index f3c9556bc864..ab9982938fa0 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java @@ -26,6 +26,7 @@ import com.intellij.openapi.vfs.*; import com.intellij.openapi.vfs.ex.temp.TempFileSystem; import com.intellij.openapi.vfs.newvfs.BulkFileListener; import com.intellij.openapi.vfs.newvfs.events.*; +import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS; import com.intellij.openapi.vfs.pointers.VirtualFilePointer; import com.intellij.openapi.vfs.pointers.VirtualFilePointerContainer; import com.intellij.openapi.vfs.pointers.VirtualFilePointerListener; @@ -529,6 +530,13 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp } } + @Override + public long getModificationCount() { + // depend on PersistentFS.getInstance().getStructureModificationCount() because com.intellij.openapi.vfs.impl.FilePointerPartNode.update is + // depend on its own modcount because we need to change both before and after VFS changes + return super.getModificationCount() + PersistentFS.getInstance().getStructureModificationCount(); + } + private static class DelegatingDisposable implements Disposable { private static final ConcurrentMap ourInstances = ContainerUtil.newConcurrentMap(ContainerUtil.identityStrategy()); diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/impl/VirtualFilePointerTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/impl/VirtualFilePointerTest.java index bd95921a2892..d8b7072ecf93 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/impl/VirtualFilePointerTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/impl/VirtualFilePointerTest.java @@ -23,7 +23,11 @@ import com.intellij.openapi.application.ex.PathManagerEx; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.roots.impl.OrderEntryUtil; +import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.roots.libraries.LibraryTable; +import com.intellij.openapi.roots.libraries.LibraryUtil; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.io.FileUtil; @@ -792,4 +796,45 @@ public class VirtualFilePointerTest extends PlatformTestCase { assertEquals(dir2, p1.getFile()); assertEquals(dir2, p2.getFile()); } + + public void testVirtualPointersMustBeAlreadyUpToDateInVFSChangeListeners() throws IOException { + File tempDirectory = createTempDirectory(); + final VirtualFile root = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(tempDirectory); + + VirtualFile dir1 = createChildDirectory(root, "dir1"); + VirtualFile file = createChildData(dir1, "x.txt"); + setFileText(file, "xxxxxx"); + + PsiTestUtil.addLibrary(getModule(), dir1.getPath()); + + VirtualFileAdapter listener = new VirtualFileAdapter() { + @Override + public void fileDeleted(@NotNull VirtualFileEvent event) { + ProjectRootManager.getInstance(getProject()).getFileIndex().getModuleForFile(dir1); + } + }; + LocalFileSystem.getInstance().addVirtualFileListener(listener); + Disposer.register(disposable, () -> LocalFileSystem.getInstance().removeVirtualFileListener(listener)); + + assertTrue(FileUtil.delete(new File(dir1.getPath()))); + System.out.println("deleted "+dir1); + + try { + while (root.findChild("dir1") != null) { + UIUtil.dispatchAllInvocationEvents(); + LocalFileSystem.getInstance().refresh(false); + } + } + finally { + ApplicationManager.getApplication().runWriteAction(() -> { + Library library = LibraryUtil.findLibrary(getModule(), "dir1"); + LibraryTable.ModifiableModel model = library.getTable().getModifiableModel(); + model.removeLibrary(library); + model.commit(); + }); + + + PsiTestUtil.removeAllRoots(getModule(), null); + } + } }