@Override
  protected void performRefactoring(UsageInfo @NotNull [] usages) {
    PsiElement[] elementsToMove = myElementsToMove.clone();
    List<RefactoringElementListener> listeners =
      ContainerUtil.map(elementsToMove, psiElement -> getTransaction().getElementListener(psiElement));
    List<@Nullable SmartPsiElementPointer<?>> movedElements = new ArrayList<>(Collections.nCopies(listeners.size(), null));

    List<NonCodeUsageInfo> nonCodeUsages = new ArrayList<>();
    List<UsageInfo> codeUsages = new ArrayList<>();

    for (UsageInfo usage : usages) {
      if (!(usage instanceof MoveRenameUsageInfo)) continue;

      if (usage instanceof NonCodeUsageInfo) {
        nonCodeUsages.add((NonCodeUsageInfo) usage);
      } else {
        codeUsages.add(usage);
      }
    }

    ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
    if (indicator != null) {
      indicator.setIndeterminate(false);
    }
    try {
      Map<PsiClass, Boolean> allClasses = new HashMap<>();
      for (PsiElement element : elementsToMove) {
        if (element instanceof PsiClass psiClass) {
          if (allClasses.containsKey(psiClass)) {
            continue;
          }
          for (MoveAllClassesInFileHandler fileHandler : MoveAllClassesInFileHandler.EP_NAME.getExtensionList()) {
            fileHandler.processMoveAllClassesInFile(allClasses, psiClass, elementsToMove);
          }
        }
      }

      for (PsiElement element : elementsToMove) {
        if (element instanceof PsiClass) {
          MoveClassesOrPackagesUtil.prepareMoveClass((PsiClass)element);
        }
      }

      final Map<PsiElement, PsiElement> oldToNewElementsMapping = new HashMap<>();

      for (int idx = 0; idx < elementsToMove.length; idx++) {
        PsiElement element = elementsToMove[idx];
        if (element instanceof PsiPackage) {
          GlobalSearchScope scope = GlobalSearchScope.projectScope(myProject);
          PsiDirectory[] directories = ((PsiPackage)element).getDirectories(scope);
          PsiPackage newElement = MoveClassesOrPackagesUtil.doMovePackage((PsiPackage)element, scope, myMoveDestination);
          oldToNewElementsMapping.put(element, newElement);
          int i = 0;
          PsiDirectory[] newDirectories = newElement.getDirectories(scope);
          if (newDirectories.length == 1) {//everything is moved in one directory
            for (PsiDirectory directory : directories) {
              oldToNewElementsMapping.put(directory, newDirectories[0]);
            }
          } else {
            for (PsiDirectory directory : directories) {
              if (myMoveDestination.verify(directory) != null) {
                //e.g. directory is excluded so there is no source root for it, hence target directory would be missed from newDirectories
                continue;
              }

              oldToNewElementsMapping.put(directory, newDirectories[i++]);
            }
          }
          element = newElement;
        }
        else if (element instanceof PsiClass psiClass) {
          final PsiClass newElement = MoveClassesOrPackagesUtil.doMoveClass(psiClass, myMoveDestination.getTargetDirectory(element.getContainingFile()), allClasses.get(psiClass));
          oldToNewElementsMapping.put(element, newElement);
          element = newElement;
        }
        else if (element instanceof PsiClassOwner) {
          PsiDirectory directory = myMoveDestination.getTargetDirectory(element.getContainingFile());
          MoveFilesOrDirectoriesUtil.doMoveFile((PsiClassOwner)element, directory);
          PsiFile newElement = directory.findFile(((PsiClassOwner)element).getName());
          LOG.assertTrue(newElement != null);

          DumbService.getInstance(myProject).completeJustSubmittedTasks();

          final PsiPackage newPackage = JavaDirectoryService.getInstance().getPackage(directory);
          if (newPackage != null) {
            String qualifiedName = newPackage.getQualifiedName();
            if (!Comparing.strEqual(qualifiedName, ((PsiClassOwner)newElement).getPackageName()) &&
                (qualifiedName.isEmpty() || PsiNameHelper.getInstance(myProject).isQualifiedName(qualifiedName))) {
              ((PsiClassOwner)newElement).setPackageName(qualifiedName);
            }
          }
          oldToNewElementsMapping.put(element, newElement);
          element = newElement;
        }
        else {
          LOG.error("Unexpected element to move: " + element);
        }
        movedElements.set(idx, SmartPointerManager.createPointer(element));
        elementsToMove[idx] = element;
      }

      DumbService.getInstance(myProject).completeJustSubmittedTasks();

      CommonMoveUtil.retargetUsages(codeUsages.toArray(UsageInfo.EMPTY_ARRAY), oldToNewElementsMapping);
      myNonCodeUsages = nonCodeUsages.toArray(new NonCodeUsageInfo[0]);

      for (PsiElement element : elementsToMove) {
        if (element instanceof PsiClass) {
          MoveClassesOrPackagesUtil.finishMoveClass((PsiClass)element);
        }
      }

      modifyModuleStatementsInDescriptor(usages);

      afterMovement(listeners, movedElements);
    }
    catch (IncorrectOperationException e) {
      myNonCodeUsages = new NonCodeUsageInfo[0];
      RefactoringUIUtil.processIncorrectOperation(myProject, e);
    }
  }
@Override
  protected void performRefactoring(UsageInfo @NotNull [] usages)