private void filesMoved(@NotNull List<? extends VFileEvent> events) {
    List<PsiElement> oldElements = new ArrayList<>(events.size());
    List<PsiDirectory> oldParentDirs = new ArrayList<>(events.size());
    List<PsiDirectory> newParentDirs = new ArrayList<>(events.size());

    // find old directories before removing invalid ones
    for (VFileEvent e : events) {
      VFileMoveEvent event = (VFileMoveEvent)e;

      VirtualFile vFile = event.getFile();

      PsiDirectory oldParentDir = myFileManager.findDirectory(event.getOldParent());
      PsiDirectory newParentDir = myFileManager.findDirectory(event.getNewParent());

      PsiElement oldElement = vFile.isDirectory()
                              ? myFileManager.getCachedDirectory(vFile)
                              : myFileManager.getCachedPsiFileInner(vFile);
      Project oldProject = ProjectLocator.getInstance().guessProjectForFile(vFile);
      if (oldProject != null && oldProject != myProject) {
        // file moved between projects, remove all associations to the old project
        myFileManager.removeFilesAndDirsRecursively(vFile);
        // avoiding crashes in filePointer.getElement()
        PsiCopyPasteManager.getInstance().fileMovedOutsideProject(vFile);
        oldElement = null;
        oldParentDir = null;
        newParentDir = null;
      }
      oldElements.add(oldElement);
      oldParentDirs.add(oldParentDir);
      newParentDirs.add(newParentDir);
    }
    myFileManager.removeInvalidFilesAndDirs(true);

    for (int i = 0; i < events.size(); i++) {
      VFileMoveEvent event = (VFileMoveEvent)events.get(i);

      VirtualFile vFile = event.getFile();

      PsiDirectory oldParentDir = oldParentDirs.get(i);
      PsiDirectory newParentDir = newParentDirs.get(i);
      if (oldParentDir == null && newParentDir == null) continue;

      PsiElement oldElement = oldElements.get(i);
      PsiElement newElement;
      FileViewProvider newViewProvider;
      if (vFile.isDirectory()) {
        newElement = myFileManager.findDirectory(vFile);
        newViewProvider = null;
      }
      else {
        newViewProvider = myFileManager.createFileViewProvider(vFile, true);
        newElement = newViewProvider.getPsi(myFileManager.findViewProvider(vFile).getBaseLanguage());
      }

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

      ApplicationManager.getApplication().runWriteAction(
        (ExternalChangeAction)() -> {
          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) {
              clearViewProvider(vFile, "PSI moved");
              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);
              }
            }
          }
        }
      );
    }
  }
private void filesMoved(@NotNull List<? extends VFileEvent> events)