public static boolean isInside(PsiElement place, PsiElement ancestor) {
    if (SafeDeleteProcessor.isInside(place, ancestor)) return true;
    if (PsiTreeUtil.getParentOfType(place, PsiComment.class, false) != null
        && ancestor instanceof PsiClass) {
      final PsiClass aClass = (PsiClass) ancestor;
      if (aClass.getParent() instanceof PsiJavaFile) {
        final PsiJavaFile file = (PsiJavaFile) aClass.getParent();
        if (PsiTreeUtil.isAncestor(file, place, false)) {
          if (file.getClasses().length == 1) { // file will be deleted on class deletion
            return true;
          }
        }
      }
    }

    return false;
  }
  @Nullable
  public UsageInfo[] preprocessUsages(final Project project, final UsageInfo[] usages) {
    final ArrayList<UsageInfo> result = new ArrayList<>();
    final ArrayList<UsageInfo> overridingMethods = new ArrayList<>();
    final ArrayList<SafeDeleteParameterCallHierarchyUsageInfo> delegatingParams = new ArrayList<>();
    final ArrayList<SafeDeleteMethodCalleeUsageInfo> calleesSafeToDelete = new ArrayList<>();
    for (UsageInfo usage : usages) {
      if (usage.isNonCodeUsage) {
        result.add(usage);
      } else if (usage instanceof SafeDeleteMethodCalleeUsageInfo) {
        calleesSafeToDelete.add((SafeDeleteMethodCalleeUsageInfo) 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;
        }
        final ArrayList<UsageInfo> selected = dialog.getSelected();
        final Set<UsageInfo> unselected = new HashSet<>(overridingMethods);
        unselected.removeAll(selected);

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

          for (Iterator<UsageInfo> iterator = result.iterator(); iterator.hasNext(); ) {
            final UsageInfo info = iterator.next();
            if (info instanceof SafeDeleteOverrideAnnotation
                && !allSuperMethodsSelectedToDelete(
                    unselectedMethods, ((SafeDeleteOverrideAnnotation) info).getMethod())) {
              iterator.remove();
            }
          }
        }

        result.addAll(selected);
      }
    }

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

              @Override
              protected int getParameterIdx() {
                return parameterIndex;
              }
            };
        TreeUtil.expand(chooser.getTree(), 2);
        if (!chooser.showAndGet()) {
          return null;
        }
      }
    }

    if (!calleesSafeToDelete.isEmpty()) {
      if (ApplicationManager.getApplication().isUnitTestMode()) {
        result.addAll(calleesSafeToDelete);
      } else {
        final PsiMethod method = calleesSafeToDelete.get(0).getCallerMethod();
        final ArrayList<UsageInfo> list = new ArrayList<>();
        JavaCallerChooser chooser =
            new SafeDeleteJavaCalleeChooser(method, project, list) {
              @Override
              protected ArrayList<SafeDeleteMethodCalleeUsageInfo> getTopLevelItems() {
                return calleesSafeToDelete;
              }
            };
        TreeUtil.expand(chooser.getTree(), 2);
        if (!chooser.showAndGet()) {
          return null;
        }
        result.addAll(list);
        final List<PsiElement> methodsToDelete = new ArrayList<>();
        for (UsageInfo info : list) {
          methodsToDelete.add(info.getElement());
        }
        methodsToDelete.add(method);
        final Condition<PsiElement> insideDeletedCondition =
            getUsageInsideDeletedFilter(
                methodsToDelete.toArray(new PsiElement[methodsToDelete.size()]));
        for (UsageInfo info : list) {
          SafeDeleteProcessor.addNonCodeUsages(
              info.getElement(),
              result,
              insideDeletedCondition,
              JavaRefactoringSettings.getInstance().RENAME_SEARCH_FOR_TEXT_FOR_METHOD,
              JavaRefactoringSettings.getInstance().RENAME_SEARCH_IN_COMMENTS_FOR_METHOD);
        }
      }
    }

    return result.toArray(new UsageInfo[result.size()]);
  }