avoid PsiVFSListener and pushers nesting (EA-56525 - assert: PsiManagerImpl.fireEvent)
authorpeter <peter@jetbrains.com>
Wed, 2 Sep 2015 16:19:51 +0000 (18:19 +0200)
committerpeter <peter@jetbrains.com>
Wed, 2 Sep 2015 16:28:13 +0000 (18:28 +0200)
platform/lang-impl/src/com/intellij/openapi/roots/impl/PushedFilePropertiesUpdaterImpl.java
platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java
platform/projectModel-api/src/com/intellij/openapi/roots/impl/PushedFilePropertiesUpdater.java

index 804bf10d41eaa88eabbee01b0cc2af2f339ee99c..f99cb308423aed6ace2f421d0480ef816d735dd0 100644 (file)
@@ -37,8 +37,6 @@ import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.EmptyRunnable;
 import com.intellij.openapi.util.registry.Registry;
 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.events.VFileCreateEvent;
 import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
 import com.intellij.openapi.vfs.newvfs.events.VFileMoveEvent;
@@ -48,7 +46,6 @@ import com.intellij.psi.impl.file.impl.FileManagerImpl;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.indexing.FileBasedIndex;
 import com.intellij.util.indexing.FileBasedIndexProjectHandler;
-import com.intellij.util.messages.MessageBusConnection;
 import com.intellij.util.ui.UIUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -68,7 +65,6 @@ public class PushedFilePropertiesUpdaterImpl extends PushedFilePropertiesUpdater
   private final FilePropertyPusher[] myPushers;
   private final FilePropertyPusher[] myFilePushers;
   private final Queue<Runnable> myTasks = new ConcurrentLinkedQueue<Runnable>();
-  private final MessageBusConnection myConnection;
 
   public PushedFilePropertiesUpdaterImpl(final Project project) {
     myProject = project;
@@ -80,12 +76,10 @@ public class PushedFilePropertiesUpdaterImpl extends PushedFilePropertiesUpdater
       }
     });
 
-    myConnection = project.getMessageBus().connect();
-
     StartupManager.getInstance(project).registerPreStartupActivity(new Runnable() {
       @Override
       public void run() {
-        myConnection.subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootAdapter() {
+        project.getMessageBus().connect().subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootAdapter() {
           @Override
           public void rootsChanged(final ModuleRootEvent event) {
             for (FilePropertyPusher pusher : myPushers) {
@@ -93,44 +87,41 @@ public class PushedFilePropertiesUpdaterImpl extends PushedFilePropertiesUpdater
             }
           }
         });
-
-        myConnection.subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener.Adapter() {
-          @Override
-          public void after(@NotNull List<? extends VFileEvent> events) {
-            List<Runnable> delayedTasks = ContainerUtil.newArrayList();
-            for (VFileEvent event : events) {
-              final VirtualFile file = event.getFile();
-              if (file == null) continue;
-
-              final FilePropertyPusher[] pushers = file.isDirectory() ? myPushers : myFilePushers;
-              if (pushers.length == 0) continue;
-
-              if (event instanceof VFileCreateEvent) {
-                if (!event.isFromRefresh() || !file.isDirectory()) {
-                  // push synchronously to avoid entering dumb mode in the middle of a meaningful write action
-                  // avoid dumb mode for just one file
-                  doPushRecursively(file, pushers, ProjectRootManager.getInstance(myProject).getFileIndex());
-                }
-                else if (!ProjectCoreUtil.isProjectOrWorkspaceFile(file)) {
-                  ContainerUtil.addIfNotNull(delayedTasks, createRecursivePushTask(file, pushers));
-                }
-              } else if (event instanceof VFileMoveEvent) {
-                for (FilePropertyPusher pusher : pushers) {
-                  file.putUserData(pusher.getFileDataKey(), null);
-                }
-                // push synchronously to avoid entering dumb mode in the middle of a meaningful write action
-                doPushRecursively(file, pushers, ProjectRootManager.getInstance(myProject).getFileIndex());
-              }
-            }
-            if (!delayedTasks.isEmpty()) {
-              queueTasks(delayedTasks);
-            }
-          }
-        });
       }
     });
   }
 
+  public void processAfterVfsChanges(@NotNull List<? extends VFileEvent> events) {
+    List<Runnable> delayedTasks = ContainerUtil.newArrayList();
+    for (VFileEvent event : events) {
+      final VirtualFile file = event.getFile();
+      if (file == null) continue;
+
+      final FilePropertyPusher[] pushers = file.isDirectory() ? myPushers : myFilePushers;
+      if (pushers.length == 0) continue;
+
+      if (event instanceof VFileCreateEvent) {
+        if (!event.isFromRefresh() || !file.isDirectory()) {
+          // push synchronously to avoid entering dumb mode in the middle of a meaningful write action
+          // avoid dumb mode for just one file
+          doPushRecursively(file, pushers, ProjectRootManager.getInstance(myProject).getFileIndex());
+        }
+        else if (!ProjectCoreUtil.isProjectOrWorkspaceFile(file)) {
+          ContainerUtil.addIfNotNull(delayedTasks, createRecursivePushTask(file, pushers));
+        }
+      } else if (event instanceof VFileMoveEvent) {
+        for (FilePropertyPusher pusher : pushers) {
+          file.putUserData(pusher.getFileDataKey(), null);
+        }
+        // push synchronously to avoid entering dumb mode in the middle of a meaningful write action
+        doPushRecursively(file, pushers, ProjectRootManager.getInstance(myProject).getFileIndex());
+      }
+    }
+    if (!delayedTasks.isEmpty()) {
+      queueTasks(delayedTasks);
+    }
+  }
+
   @Override
   public void initializeProperties() {
     for (final FilePropertyPusher pusher : myPushers) {
@@ -411,9 +402,4 @@ public class PushedFilePropertiesUpdaterImpl extends PushedFilePropertiesUpdater
       });
     }
   }
-
-  @Override
-  public void processPendingEvents() {
-    myConnection.deliverImmediately();
-  }
 }
index dfd37eae7b9c20987c6235f7069e39f4451f1df6..3f13fa015525e1c25b47bc02a806b3d1f5bbb80c 100644 (file)
@@ -32,6 +32,7 @@ import com.intellij.openapi.project.Project;
 import com.intellij.openapi.project.ProjectManager;
 import com.intellij.openapi.roots.*;
 import com.intellij.openapi.roots.impl.PushedFilePropertiesUpdater;
+import com.intellij.openapi.roots.impl.PushedFilePropertiesUpdaterImpl;
 import com.intellij.openapi.startup.StartupManager;
 import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.vfs.*;
@@ -73,7 +74,13 @@ public class PsiVFSListener extends VirtualFileAdapter {
 
       @Override
       public void after(@NotNull List<? extends VFileEvent> events) {
-        for (Project project : ProjectManager.getInstance().getOpenProjects()) {
+        Project[] projects = ProjectManager.getInstance().getOpenProjects();
+
+        // let PushedFilePropertiesUpdater process all pending vfs events and update file properties before we issue PSI events
+        for (Project project : projects) {
+          ((PushedFilePropertiesUpdaterImpl)PushedFilePropertiesUpdater.getInstance(project)).processAfterVfsChanges(events);
+        }
+        for (Project project : projects) {
           PsiVFSListener listener = project.getComponent(PsiVFSListener.class);
           assert listener != null;
           listener.myReportedUnloadedPsiChange = false;
@@ -523,9 +530,6 @@ public class PsiVFSListener extends VirtualFileAdapter {
 
   @Override
   public void fileMoved(@NotNull VirtualFileMoveEvent event) {
-    // let PushedFilePropertiesUpdater process all pending vfs events and update file properties before we issue PSI events
-    PushedFilePropertiesUpdater.getInstance(myProject).processPendingEvents();
-
     final VirtualFile vFile = event.getFile();
 
     final PsiDirectory oldParentDir = myFileManager.findDirectory(event.getOldParent());
index a5764eee0a4b4eec5b176a55ef3396c293d26ca7..3b8a92297d6b6dd091a647d45d5b5e546f0ae298 100644 (file)
@@ -28,7 +28,6 @@ public abstract class PushedFilePropertiesUpdater {
   public abstract void initializeProperties();
   public abstract void pushAll(final FilePropertyPusher... pushers);
   public abstract void filePropertiesChanged(@NotNull final VirtualFile file);
-  public abstract void processPendingEvents();
   public abstract void pushAllPropertiesNow();
   public abstract <T> void findAndUpdateValue(final VirtualFile fileOrDir, final FilePropertyPusher<T> pusher, final T moduleValue);
 }