IDEA-136705 (delay post-execution refresh to allow FS changes to reach the IDE)
authorRoman Shevchenko <roman.shevchenko@jetbrains.com>
Tue, 24 Feb 2015 19:40:08 +0000 (20:40 +0100)
committerRoman Shevchenko <roman.shevchenko@jetbrains.com>
Tue, 24 Feb 2015 19:40:08 +0000 (20:40 +0100)
For this, save-and-sync handler API was extracted and  used throughout the platform - including execution manager.

platform/dvcs-impl/src/com/intellij/dvcs/DvcsPlatformFacadeImpl.java
platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java
platform/platform-api/src/com/intellij/ide/SaveAndSyncHandler.java [new file with mode: 0644]
platform/platform-impl/src/com/intellij/ide/SaveAndSyncHandler.java [deleted file]
platform/platform-impl/src/com/intellij/ide/SaveAndSyncHandlerImpl.java
platform/platform-impl/src/com/intellij/ide/actions/SynchronizeAction.java
platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java
python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyUtils.java
python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyEditInputAction.java
python/educational/src/com/jetbrains/edu/EduUtils.java

index 9f10311f68d3d558294c1c8ba97506447145cb3c..a3e6cdab3d03c56d56fe5082e6f62f43f405e153 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2015 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,7 +16,6 @@
 package com.intellij.dvcs;
 
 import com.intellij.ide.SaveAndSyncHandler;
-import com.intellij.ide.SaveAndSyncHandlerImpl;
 import com.intellij.ide.plugins.IdeaPluginDescriptor;
 import com.intellij.ide.plugins.PluginManager;
 import com.intellij.openapi.application.ApplicationManager;
@@ -133,7 +132,7 @@ public abstract class DvcsPlatformFacadeImpl implements DvcsPlatformFacade {
   @NotNull
   @Override
   public SaveAndSyncHandler getSaveAndSyncHandler() {
-    return SaveAndSyncHandlerImpl.getInstance();
+    return SaveAndSyncHandler.getInstance();
   }
 
   @Override
index 6dca47feed69e41b42f16eab99c87aab84f2665a..2777be242a4ece34f063a25858f64909ff167402 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * Copyright 2000-2015 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@ import com.intellij.execution.runners.ProgramRunner;
 import com.intellij.execution.ui.RunContentDescriptor;
 import com.intellij.execution.ui.RunContentManager;
 import com.intellij.execution.ui.RunContentManagerImpl;
+import com.intellij.ide.SaveAndSyncHandler;
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.openapi.actionSystem.impl.SimpleDataContext;
@@ -45,7 +46,6 @@ import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.util.Key;
 import com.intellij.openapi.util.Trinity;
 import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vfs.VirtualFileManager;
 import com.intellij.ui.docking.DockManager;
 import com.intellij.util.Alarm;
 import com.intellij.util.SmartList;
@@ -548,7 +548,8 @@ public class ExecutionManagerImpl extends ExecutionManager implements Disposable
       if (myProject.isDisposed()) return;
 
       myProject.getMessageBus().syncPublisher(EXECUTION_TOPIC).processTerminated(myProfile, myProcessHandler);
-      VirtualFileManager.getInstance().asyncRefresh(null);
+
+      SaveAndSyncHandler.getInstance().scheduleRefresh();
     }
 
     @Override
diff --git a/platform/platform-api/src/com/intellij/ide/SaveAndSyncHandler.java b/platform/platform-api/src/com/intellij/ide/SaveAndSyncHandler.java
new file mode 100644 (file)
index 0000000..851451c
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2000-2015 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide;
+
+import com.intellij.openapi.application.ApplicationManager;
+
+/**
+ * @author Kirill Likhodedov
+ */
+public abstract class SaveAndSyncHandler {
+  public static SaveAndSyncHandler getInstance() {
+    return ApplicationManager.getApplication().getComponent(SaveAndSyncHandler.class);
+  }
+
+  public abstract void saveProjectsAndDocuments();
+  public abstract void scheduleRefresh();
+  public abstract void refreshOpenFiles();
+
+  public abstract void blockSaveOnFrameDeactivation();
+  public abstract void unblockSaveOnFrameDeactivation();
+
+  public abstract void blockSyncOnFrameActivation();
+  public abstract void unblockSyncOnFrameActivation();
+}
diff --git a/platform/platform-impl/src/com/intellij/ide/SaveAndSyncHandler.java b/platform/platform-impl/src/com/intellij/ide/SaveAndSyncHandler.java
deleted file mode 100644 (file)
index 6f2a983..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2000-2012 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.ide;
-
-/**
- * @author Kirill Likhodedov
- */
-public interface SaveAndSyncHandler {
-
-  void blockSaveOnFrameDeactivation();
-
-  void unblockSaveOnFrameDeactivation();
-
-  void blockSyncOnFrameActivation();
-
-  void unblockSyncOnFrameActivation();
-}
index e42c796ab8bb6d280cdd29c3ea01b3d7ba7d4b4b..8983f14fca723e2a4ea64136032181009ab2f3e3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * Copyright 2000-2015 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -46,47 +46,35 @@ import java.util.concurrent.atomic.AtomicInteger;
  * @author Anton Katilin
  * @author Vladimir Kondratyev
  */
-public class SaveAndSyncHandlerImpl implements ApplicationComponent, SaveAndSyncHandler {
+public class SaveAndSyncHandlerImpl extends SaveAndSyncHandler implements ApplicationComponent {
   private static final Logger LOG = Logger.getInstance(SaveAndSyncHandler.class);
 
   private final Runnable myIdleListener;
   private final PropertyChangeListener myGeneralSettingsListener;
+  private final GeneralSettings mySettings;
   private final ProgressManager myProgressManager;
+  private final SingleAlarm myRefreshDelayAlarm;
 
   private final AtomicInteger myBlockSaveOnFrameDeactivationCount = new AtomicInteger();
   private final AtomicInteger myBlockSyncOnFrameActivationCount = new AtomicInteger();
-  private final SingleAlarm myRefreshDelayAlarm = new SingleAlarm(new Runnable() {
-    @Override
-    public void run() {
-      if (canSyncOrSave()) {
-        refreshOpenFiles();
-      }
-      maybeRefresh(ModalityState.NON_MODAL);
-    }
-  }, 300);
+  private volatile long myRefreshSessionId = 0;
 
-  private long myRefreshSessionId = 0;
-
-  public static SaveAndSyncHandlerImpl getInstance() {
-    return (SaveAndSyncHandlerImpl)ApplicationManager.getApplication().getComponent(SaveAndSyncHandler.class);
-  }
-
-  public SaveAndSyncHandlerImpl(@NotNull FrameStateManager frameStateManager,
-                                @NotNull final FileDocumentManager fileDocumentManager,
-                                @NotNull final GeneralSettings generalSettings,
-                                @NotNull ProgressManager progressManager) {
+  public SaveAndSyncHandlerImpl(@NotNull GeneralSettings generalSettings,
+                                @NotNull ProgressManager progressManager,
+                                @NotNull FrameStateManager frameStateManager,
+                                @NotNull final FileDocumentManager fileDocumentManager) {
+    mySettings = generalSettings;
     myProgressManager = progressManager;
 
     myIdleListener = new Runnable() {
       @Override
       public void run() {
-        if (generalSettings.isAutoSaveIfInactive() && canSyncOrSave()) {
+        if (mySettings.isAutoSaveIfInactive() && canSyncOrSave()) {
           ((FileDocumentManagerImpl)fileDocumentManager).saveAllDocuments(false);
         }
       }
     };
-
-    IdeEventQueue.getInstance().addIdleListener(myIdleListener, generalSettings.getInactiveTimeout() * 1000);
+    IdeEventQueue.getInstance().addIdleListener(myIdleListener, mySettings.getInactiveTimeout() * 1000);
 
     myGeneralSettingsListener = new PropertyChangeListener() {
       @Override
@@ -99,8 +87,17 @@ public class SaveAndSyncHandlerImpl implements ApplicationComponent, SaveAndSync
         }
       }
     };
+    mySettings.addPropertyChangeListener(myGeneralSettingsListener);
 
-    generalSettings.addPropertyChangeListener(myGeneralSettingsListener);
+    myRefreshDelayAlarm = new SingleAlarm(new Runnable() {
+      @Override
+      public void run() {
+        if (canSyncOrSave()) {
+          refreshOpenFiles();
+        }
+        maybeRefresh(ModalityState.NON_MODAL);
+      }
+    }, 300);
 
     frameStateManager.addListener(new FrameStateListener() {
       @Override
@@ -112,13 +109,9 @@ public class SaveAndSyncHandlerImpl implements ApplicationComponent, SaveAndSync
 
       @Override
       public void onFrameActivated() {
-        if (ApplicationManager.getApplication().isDisposed() || !generalSettings.isSyncOnFrameActivation()) {
-          return;
+        if (!ApplicationManager.getApplication().isDisposed() && mySettings.isSyncOnFrameActivation()) {
+          scheduleRefresh();
         }
-
-        LOG.debug("enter: refreshFiles()");
-        myRefreshDelayAlarm.cancelAndRequest();
-        LOG.debug("exit: refreshFiles()");
       }
     });
   }
@@ -130,12 +123,13 @@ public class SaveAndSyncHandlerImpl implements ApplicationComponent, SaveAndSync
   }
 
   @Override
-  public void initComponent() {
-  }
+  public void initComponent() { }
 
   @Override
   public void disposeComponent() {
-    GeneralSettings.getInstance().removePropertyChangeListener(myGeneralSettingsListener);
+    myRefreshDelayAlarm.cancel();
+    RefreshQueue.getInstance().cancelSession(myRefreshSessionId);
+    mySettings.removePropertyChangeListener(myGeneralSettingsListener);
     IdeEventQueue.getInstance().removeIdleListener(myIdleListener);
   }
 
@@ -143,37 +137,34 @@ public class SaveAndSyncHandlerImpl implements ApplicationComponent, SaveAndSync
     return !LaterInvocator.isInModalContext() && !myProgressManager.hasModalProgressIndicator();
   }
 
-  // made public for tests
+  @Override
   public void saveProjectsAndDocuments() {
-    if (LOG.isDebugEnabled()) {
-      LOG.debug("enter: save()");
-    }
-    if (ApplicationManager.getApplication().isDisposed()) return;
+    LOG.debug("enter: save()");
 
-    if (myBlockSaveOnFrameDeactivationCount.get() == 0 && GeneralSettings.getInstance().isSaveOnFrameDeactivation()) {
+    if (!ApplicationManager.getApplication().isDisposed() &&
+        mySettings.isSaveOnFrameDeactivation() &&
+        myBlockSaveOnFrameDeactivationCount.get() == 0) {
       FileDocumentManager.getInstance().saveAllDocuments();
 
-      Project[] openProjects = ProjectManagerEx.getInstanceEx().getOpenProjects();
-      for (Project project : openProjects) {
-        if (LOG.isDebugEnabled()) {
-          LOG.debug("save project: " + project);
-        }
+      for (Project project : ProjectManagerEx.getInstanceEx().getOpenProjects()) {
+        if (LOG.isDebugEnabled()) LOG.debug("saving project: " + project);
         project.save();
       }
-      if (LOG.isDebugEnabled()) {
-        LOG.debug("save application settings");
-      }
+
+      LOG.debug("saving application settings");
       ApplicationManagerEx.getApplicationEx().saveSettings();
-      if (LOG.isDebugEnabled()) {
-        LOG.debug("exit: save()");
-      }
+
+      LOG.debug("exit: save()");
     }
   }
 
-  public void maybeRefresh(@NotNull ModalityState modalityState) {
-    if (myBlockSyncOnFrameActivationCount.get() == 0 && GeneralSettings.getInstance().isSyncOnFrameActivation()) {
-      LOG.debug("VFS refresh started");
+  @Override
+  public void scheduleRefresh() {
+    myRefreshDelayAlarm.cancelAndRequest();
+  }
 
+  public void maybeRefresh(@NotNull ModalityState modalityState) {
+    if (myBlockSyncOnFrameActivationCount.get() == 0 && mySettings.isSyncOnFrameActivation()) {
       RefreshQueue queue = RefreshQueue.getInstance();
       queue.cancelSession(myRefreshSessionId);
 
@@ -181,16 +172,15 @@ public class SaveAndSyncHandlerImpl implements ApplicationComponent, SaveAndSync
       session.addAllFiles(ManagingFS.getInstance().getLocalRoots());
       myRefreshSessionId = session.getId();
       session.launch();
-
-      LOG.debug("VFS refresh finished");
     }
   }
 
-  public static void refreshOpenFiles() {
+  @Override
+  public void refreshOpenFiles() {
     List<VirtualFile> files = ContainerUtil.newArrayList();
+
     for (Project project : ProjectManager.getInstance().getOpenProjects()) {
-      VirtualFile[] projectFiles = FileEditorManager.getInstance(project).getSelectedFiles();
-      for (VirtualFile file : projectFiles) {
+      for (VirtualFile file : FileEditorManager.getInstance(project).getSelectedFiles()) {
         if (file instanceof NewVirtualFile) {
           files.add(file);
         }
index 942d78a81e612f62938edf0c390fb51cdf95a9c3..525108ae518fdb571ff141d5647dd26b174b0d40 100644 (file)
@@ -15,7 +15,7 @@
  */
 package com.intellij.ide.actions;
 
-import com.intellij.ide.SaveAndSyncHandlerImpl;
+import com.intellij.ide.SaveAndSyncHandler;
 import com.intellij.openapi.actionSystem.AnAction;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
@@ -26,9 +26,7 @@ public class SynchronizeAction extends AnAction implements DumbAware {
   @Override
   public void actionPerformed(AnActionEvent e) {
     FileDocumentManager.getInstance().saveAllDocuments();
-
-    SaveAndSyncHandlerImpl.refreshOpenFiles();
-
+    SaveAndSyncHandler.getInstance().refreshOpenFiles();
     VirtualFileManager.getInstance().refreshWithoutFileWatcher(true);
   }
 }
index db2e8c7a6e84db69e5cdaf43645f78d0077ddc78..7a5d9843d3e69004a60f18531c67413c5562ab56 100644 (file)
@@ -17,6 +17,7 @@ package com.intellij.openapi.fileChooser.ex;
 
 import com.intellij.icons.AllIcons;
 import com.intellij.ide.IdeEventQueue;
+import com.intellij.ide.SaveAndSyncHandler;
 import com.intellij.ide.SaveAndSyncHandlerImpl;
 import com.intellij.ide.util.PropertiesComponent;
 import com.intellij.ide.util.treeView.NodeRenderer;
@@ -356,7 +357,7 @@ public class FileChooserDialogImpl extends DialogWrapper implements FileChooserD
       .subscribe(ApplicationActivationListener.TOPIC, new ApplicationActivationListener.Adapter() {
         @Override
         public void applicationActivated(IdeFrame ideFrame) {
-          SaveAndSyncHandlerImpl.getInstance().maybeRefresh(ModalityState.current());
+          ((SaveAndSyncHandlerImpl)SaveAndSyncHandler.getInstance()).maybeRefresh(ModalityState.current());
         }
       });
 
index 52e83b4990dd930c6d319493993712df3bb2acdb..99e4d058c6d2e94664846ed763c7c88abf1ee0bc 100644 (file)
@@ -3,7 +3,6 @@ package com.jetbrains.edu.learning;
 import com.intellij.execution.RunContentExecutor;
 import com.intellij.execution.configurations.GeneralCommandLine;
 import com.intellij.execution.process.ProcessHandler;
-import com.intellij.ide.SaveAndSyncHandlerImpl;
 import com.intellij.lang.Language;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.Presentation;
@@ -12,7 +11,6 @@ import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.actionSystem.EditorActionManager;
 import com.intellij.openapi.editor.colors.EditorColors;
-import com.intellij.openapi.fileEditor.FileDocumentManager;
 import com.intellij.openapi.fileEditor.FileEditor;
 import com.intellij.openapi.fileEditor.FileEditorManager;
 import com.intellij.openapi.project.Project;
@@ -21,7 +19,6 @@ import com.intellij.openapi.ui.popup.Balloon;
 import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.vfs.VirtualFileManager;
 import com.intellij.openapi.wm.ToolWindowManager;
 import com.intellij.ui.JBColor;
 import com.intellij.util.ui.UIUtil;
@@ -120,12 +117,6 @@ public class StudyUtils {
       getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW));
   }
 
-  public static void synchronize() {
-    FileDocumentManager.getInstance().saveAllDocuments();
-    SaveAndSyncHandlerImpl.refreshOpenFiles();
-    VirtualFileManager.getInstance().refreshWithoutFileWatcher(true);
-  }
-
   public static void deleteFile(@NotNull final VirtualFile file) {
     try {
       file.delete(StudyUtils.class);
index 26c136b480058207da1708188821c7a91505f8d1..24d6e31f3fb69f0375e606dadcc0f255d2c53e59 100644 (file)
@@ -21,6 +21,7 @@ import com.intellij.ui.tabs.TabsListener;
 import com.intellij.ui.tabs.impl.JBEditorTabs;
 import com.intellij.util.PlatformIcons;
 import com.jetbrains.edu.EduNames;
+import com.jetbrains.edu.EduUtils;
 import com.jetbrains.edu.courseFormat.Task;
 import com.jetbrains.edu.courseFormat.TaskFile;
 import com.jetbrains.edu.learning.StudyTaskManager;
@@ -120,7 +121,7 @@ public class StudyEditInputAction extends DumbAwareAction {
     finally {
       StudyUtils.closeSilently(printWriter);
     }
-    StudyUtils.synchronize();
+    EduUtils.synchronize();
   }
 
   private static UserTest createUserTest(@NotNull final VirtualFile testsDir,
@@ -208,7 +209,7 @@ public class StudyEditInputAction extends DumbAwareAction {
       File testInputFile = new File(userTest.getInput());
       File testOutputFile = new File(userTest.getOutput());
       if (testInputFile.delete() && testOutputFile.delete()) {
-        StudyUtils.synchronize();
+        EduUtils.synchronize();
       } else {
         LOG.error("failed to delete user tests");
       }
index ab2114f704312cb9e16f5f491db2a0edf3c3f49d..3fc34c3e52e7d71cc367e2a97b4cfde86e24088e 100644 (file)
@@ -1,6 +1,6 @@
 package com.jetbrains.edu;
 
-import com.intellij.ide.SaveAndSyncHandlerImpl;
+import com.intellij.ide.SaveAndSyncHandler;
 import com.intellij.ide.projectView.actions.MarkRootActionBase;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.Presentation;
@@ -131,7 +131,7 @@ public class EduUtils {
 
   public static void synchronize() {
     FileDocumentManager.getInstance().saveAllDocuments();
-    SaveAndSyncHandlerImpl.refreshOpenFiles();
+    SaveAndSyncHandler.getInstance().refreshOpenFiles();
     VirtualFileManager.getInstance().refreshWithoutFileWatcher(true);
   }