@Override
  public UsageInfo @Nullable [] preprocessUsages(@NotNull Project project, UsageInfo @NotNull [] usages) {
    List<UsageInfo> result = new ArrayList<>();
    List<UsageInfo> overridingMethods = new ArrayList<>();
    List<SafeDeleteParameterCallHierarchyUsageInfo> delegatingParams = new ArrayList<>();
    List<SafeDeleteMemberCalleeUsageInfo> calleesSafeToDelete = new ArrayList<>();
    for (UsageInfo usage : usages) {
      if (usage.isNonCodeUsage) {
        if (usage instanceof SafeDeleteUsageInfo) {
          PsiElement element = ((SafeDeleteUsageInfo)usage).getReferencedElement();
          if (element instanceof PsiModifierListOwner) {
            ExternalAnnotationsManager annotationsManager = ExternalAnnotationsManager.getInstance(element.getProject());
            List<PsiFile> annotationsFiles = annotationsManager.findExternalAnnotationsFiles((PsiModifierListOwner)element);
            if (annotationsFiles != null && annotationsFiles.contains(usage.getFile())) {
              result.add(new SafeDeleteExternalAnnotationsUsageInfo(element, usage.getElement()));
              continue;
            }
          }
        }
        result.add(usage);
      }
      else if (usage instanceof SafeDeleteMemberCalleeUsageInfo) {
        calleesSafeToDelete.add((SafeDeleteMemberCalleeUsageInfo)usage);
      }
      else if (usage instanceof SafeDeleteOverridingMethodUsageInfo) {
        overridingMethods.add(usage);
      }
      else if (usage instanceof SafeDeleteParameterCallHierarchyUsageInfo) {
        delegatingParams.add((SafeDeleteParameterCallHierarchyUsageInfo)usage);
      }
      else if (usage instanceof SafeDeleteAnnotation) {
        result.add(new SafeDeleteAnnotation((PsiAnnotation)usage.getElement(), ((SafeDeleteAnnotation)usage).getReferencedElement(), true));
      }
      else {
        result.add(usage);
      }
    }

    if(!overridingMethods.isEmpty()) {
      if (ApplicationManager.getApplication().isUnitTestMode()) {
        result.addAll(overridingMethods);
      }
      else {
        OverridingMethodsDialog dialog = new OverridingMethodsDialog(project, overridingMethods);
        if (!dialog.showAndGet()) {
          return null;
        }
        ArrayList<UsageInfo> selected = dialog.getSelected();
        Set<UsageInfo> unselected = new HashSet<>(overridingMethods);
        for (UsageInfo usageInfo : selected) {
          unselected.remove(usageInfo);
        }

        if (!unselected.isEmpty()) {
          List<PsiElement> unselectedMethods = ContainerUtil.map(unselected, info -> ((SafeDeleteOverridingMethodUsageInfo)info).getOverridingMethod());

          result.removeIf(info -> info instanceof SafeDeleteOverrideAnnotation &&
                                  !allSuperMethodsSelectedToDelete(unselectedMethods, ((SafeDeleteOverrideAnnotation)info).getMethod()));
        }

        result.addAll(selected);
      }
    }

    if (!delegatingParams.isEmpty()) {
      SafeDeleteParameterCallHierarchyUsageInfo parameterHierarchyUsageInfo = delegatingParams.get(0);
      if (ApplicationManager.getApplication().isUnitTestMode()) {
        result.addAll(delegatingParams);
      } else {
        PsiMethod method = parameterHierarchyUsageInfo.getCalledMethod();
        PsiParameter parameter = parameterHierarchyUsageInfo.getReferencedElement();
        int parameterIndex = method.getParameterList().getParameterIndex(parameter);
        AbstractJavaMemberCallerChooser<?> chooser = new SafeDeleteJavaCallerChooser(method, project, result) {
          @Override
          protected @NotNull List<SafeDeleteParameterCallHierarchyUsageInfo> getTopLevelItems() {
            return delegatingParams;
          }

          @Override
          protected int getParameterIdx() {
            return parameterIndex;
          }

          @Override
          protected PsiParameter getParameterInCaller(PsiMethod called, int paramIdx, PsiMethod caller) {
            return delegatingParams.stream()
              .filter(usage -> caller.equals(usage.getCallerMethod()))
              .map(usage -> usage.getParameterInCaller())
              .findFirst()
              .orElse(super.getParameterInCaller(called, paramIdx, caller));
          }
        };
        TreeUtil.expand(chooser.getTree(), 2);
        if (!chooser.showAndGet()) {
          return null;
        }
      }
    }

    if (!calleesSafeToDelete.isEmpty()) {
      if (ApplicationManager.getApplication().isUnitTestMode()) {
        result.addAll(calleesSafeToDelete);
      }
      else {
        PsiMember member = calleesSafeToDelete.get(0).getCallerMember();
        List<UsageInfo> list = new ArrayList<>();
        SafeDeleteJavaCalleeChooser chooser = new SafeDeleteJavaCalleeChooser(member, project, list) {
          @Override
          protected @NotNull List<SafeDeleteMemberCalleeUsageInfo> getTopLevelItems() {
            return calleesSafeToDelete;
          }
        };
        TreeUtil.expand(chooser.getTree(), 2);
        if (!chooser.showAndGet()) {
          return null;
        }
        result.addAll(list);
        List<PsiElement> methodsToDelete = new ArrayList<>();
        for (UsageInfo info : list) {
          methodsToDelete.add(info.getElement());
        }
        methodsToDelete.add(member);
        Condition<PsiElement> insideDeletedCondition = getUsageInsideDeletedFilter(methodsToDelete.toArray(PsiElement.EMPTY_ARRAY));
        for (UsageInfo info : list) {
          PsiElement psi = info.getElement();
          JavaRefactoringSettings refactoringSettings = JavaRefactoringSettings.getInstance();
          SafeDeleteProcessor.addNonCodeUsages(psi, GlobalSearchScope.projectScope(project), result, insideDeletedCondition,
                                               psi instanceof PsiMethod ? refactoringSettings.RENAME_SEARCH_FOR_TEXT_FOR_METHOD : refactoringSettings.RENAME_SEARCH_FOR_TEXT_FOR_FIELD,
                                               psi instanceof PsiMethod ? refactoringSettings.RENAME_SEARCH_IN_COMMENTS_FOR_METHOD : refactoringSettings.RENAME_SEARCH_IN_COMMENTS_FOR_FIELD );
        }
      }
    }

    return result.toArray(UsageInfo.EMPTY_ARRAY);
  }
@Override
  public UsageInfo @Nullable [] preprocessUsages(@NotNull Project project, UsageInfo @NotNull [] usages)