@Override
  public void beforeFileMovement(@NotNull VirtualFileMoveEvent event) {
    final VirtualFile vFile = event.getFile();

    final PsiDirectory oldParentDir = myFileManager.findDirectory(event.getOldParent());
    final PsiDirectory newParentDir = myFileManager.findDirectory(event.getNewParent());
    if (oldParentDir == null && newParentDir == null) return;
    if (myFileTypeManager.isFileIgnored(vFile)) return;

    ApplicationManager.getApplication()
        .runWriteAction(
            new ExternalChangeAction() {
              @Override
              public void run() {
                PsiTreeChangeEventImpl treeEvent = new PsiTreeChangeEventImpl(myManager);

                boolean isExcluded =
                    vFile.isDirectory()
                        && Registry.is("ide.hide.excluded.files")
                        && myProjectRootManager.getFileIndex().isExcluded(vFile);
                if (oldParentDir != null && !isExcluded) {
                  if (newParentDir != null) {
                    treeEvent.setOldParent(oldParentDir);
                    treeEvent.setNewParent(newParentDir);
                    if (vFile.isDirectory()) {
                      PsiDirectory psiDir = myFileManager.findDirectory(vFile);
                      treeEvent.setChild(psiDir);
                    } else {
                      PsiFile psiFile = myFileManager.findFile(vFile);
                      treeEvent.setChild(psiFile);
                    }
                    myManager.beforeChildMovement(treeEvent);
                  } else {
                    treeEvent.setParent(oldParentDir);
                    if (vFile.isDirectory()) {
                      PsiDirectory psiDir = myFileManager.findDirectory(vFile);
                      treeEvent.setChild(psiDir);
                    } else {
                      PsiFile psiFile = myFileManager.findFile(vFile);
                      treeEvent.setChild(psiFile);
                    }
                    myManager.beforeChildRemoval(treeEvent);
                  }
                } else {
                  LOG.assertTrue(newParentDir != null); // checked above
                  treeEvent.setParent(newParentDir);
                  myManager.beforeChildAddition(treeEvent);
                }
              }
            });
  }
  @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());
    final PsiDirectory newParentDir = myFileManager.findDirectory(event.getNewParent());
    if (oldParentDir == null && newParentDir == null) return;

    final PsiElement oldElement =
        vFile.isDirectory()
            ? myFileManager.getCachedDirectory(vFile)
            : myFileManager.getCachedPsiFileInner(vFile);
    myFileManager.removeInvalidFilesAndDirs(true);
    final PsiElement newElement;
    final FileViewProvider newViewProvider;
    if (!vFile.isDirectory()) {
      newViewProvider = myFileManager.createFileViewProvider(vFile, true);
      newElement = newViewProvider.getPsi(myFileManager.findViewProvider(vFile).getBaseLanguage());
    } else {
      newElement = myFileManager.findDirectory(vFile);
      newViewProvider = null;
    }

    if (oldElement == null && newElement == null) return;

    ApplicationManager.getApplication()
        .runWriteAction(
            new ExternalChangeAction() {
              @Override
              public void run() {
                PsiTreeChangeEventImpl treeEvent = new PsiTreeChangeEventImpl(myManager);
                if (oldElement == null) {
                  myFileManager.setViewProvider(vFile, newViewProvider);
                  treeEvent.setParent(newParentDir);
                  treeEvent.setChild(newElement);
                  myManager.childAdded(treeEvent);
                } else {
                  if (newElement == null) {
                    myFileManager.setViewProvider(vFile, null);
                    treeEvent.setParent(oldParentDir);
                    treeEvent.setChild(oldElement);
                    myManager.childRemoved(treeEvent);
                  } else {
                    if (newElement instanceof PsiDirectory
                        || FileManagerImpl.areViewProvidersEquivalent(
                            newViewProvider, ((PsiFile) oldElement).getViewProvider())) {
                      treeEvent.setOldParent(oldParentDir);
                      treeEvent.setNewParent(newParentDir);
                      treeEvent.setChild(oldElement);
                      myManager.childMoved(treeEvent);
                    } else {
                      myFileManager.setViewProvider(vFile, newViewProvider);
                      PsiTreeChangeEventImpl treeRemoveEvent =
                          new PsiTreeChangeEventImpl(myManager);
                      treeRemoveEvent.setParent(oldParentDir);
                      treeRemoveEvent.setChild(oldElement);
                      myManager.childRemoved(treeRemoveEvent);
                      PsiTreeChangeEventImpl treeAddEvent = new PsiTreeChangeEventImpl(myManager);
                      treeAddEvent.setParent(newParentDir);
                      treeAddEvent.setChild(newElement);
                      myManager.childAdded(treeAddEvent);
                    }
                  }
                }
              }
            });
  }