void (UsageInfo @NotNull [] _usages) { try { List<PsiElement> toChange = new ArrayList<>(); Collections.addAll(toChange, myElementsToMove); PsiDirectory newParent = myNewParent; List<UsageInfo> codeUsages = new ArrayList<>(); List<NonCodeUsageInfo> nonCodeUsages = new ArrayList<>(); for (UsageInfo usage : _usages) { if (usage instanceof NonCodeUsageInfo) { nonCodeUsages.add((NonCodeUsageInfo)usage); } else { codeUsages.add(usage); } } //keep hard references to PSI and AST to prevent collecting the object between saving references and restoring Map<PsiFile, FileASTNode> movingFiles = new HashMap<>(); final Map<PsiElement, PsiElement> oldToNewMap = new HashMap<>(); if (mySearchForReferences) { for (PsiElement element : toChange) { if (element instanceof PsiDirectory) { encodeDirectoryFiles(element, movingFiles); } else if (element instanceof PsiFile) { movingFiles.put((PsiFile)element, ((PsiFile)element).getNode()); FileReferenceContextUtil.encodeFileReferences(element); } } } List<RefactoringElementListener> listeners = ContainerUtil.map(myElementsToMove, item -> getTransaction().getElementListener(item)); List<Runnable> notifyListeners = new ArrayList<>(); List<SmartPsiElementPointer<PsiFile>> movedFiles = new ArrayList<>(); for (int i = 0; i < myElementsToMove.length; i++) { PsiElement element = toChange.get(i); if (element instanceof PsiDirectory) { MoveFilesOrDirectoriesUtil.doMoveDirectory((PsiDirectory)element, newParent); for (PsiElement psiElement : element.getChildren()) { processDirectoryFiles(movedFiles, oldToNewMap, psiElement); } } else if (element instanceof PsiFile movedFile) { MoveFileHandler.forElement(movedFile).prepareMovedFile(movedFile, newParent, oldToNewMap); PsiFile moving = newParent.findFile(movedFile.getName()); if (moving == null) { MoveFilesOrDirectoriesUtil.doMoveFile(movedFile, newParent); } moving = newParent.findFile(movedFile.getName()); if (moving != null) { movedFiles.add(SmartPointerManager.createPointer(moving)); } } if (element.isValid()) { RefactoringElementListener listener = listeners.get(i); SmartPsiElementPointer<PsiElement> pointer = SmartPointerManager.createPointer(element); notifyListeners.add(() -> { PsiElement restored = pointer.getElement(); if (restored != null) { listener.elementMoved(restored); } }); } } // sort by offset descending to process correctly several usages in one PsiElement [IDEADEV-33013] UsageInfo[] usages = codeUsages.toArray(UsageInfo.EMPTY_ARRAY); CommonRefactoringUtil.sortDepthFirstRightLeftOrder(usages); DumbService.getInstance(myProject).completeJustSubmittedTasks(); // fix references in moved files to outer files for (SmartPsiElementPointer<PsiFile> pointer : movedFiles) { PsiFile movedFile = pointer.getElement(); if (movedFile != null) { MoveFileHandler.forElement(movedFile).updateMovedFile(movedFile); if (mySearchForReferences) FileReferenceContextUtil.decodeFileReferences(movedFile); } } retargetUsages(usages, oldToNewMap); for (Map.Entry<PsiFile, List<UsageInfo>> entry : myFoundUsages.entrySet()) { MoveFileHandler.forElement(entry.getKey()).retargetUsages(entry.getValue(), oldToNewMap); } myNonCodeUsages = nonCodeUsages.toArray(new NonCodeUsageInfo[0]); afterMove(movedFiles, notifyListeners); Reference.reachabilityFence(movingFiles); } catch (IncorrectOperationException e) { Throwable cause = e.getCause(); if (cause instanceof IOException) { LOG.info(e); ApplicationManager.getApplication().invokeLater( () -> Messages.showMessageDialog(myProject, cause.getMessage(), RefactoringBundle.message("error.title"), Messages.getErrorIcon())); } else { LOG.error(e); } } }