protected void performRefactoring(final UsageInfo[] usages) {
    new PushDownProcessor(
        mySuperClass.getProject(),
        myMemberInfos,
        mySuperClass,
        new DocCommentPolicy(DocCommentPolicy.ASIS)) {
      // push down conflicts are already collected
      @Override
      protected boolean showConflicts(MultiMap<PsiElement, String> conflicts, UsageInfo[] usages) {
        return true;
      }
    }.run();

    RefactoringUtil.sortDepthFirstRightLeftOrder(usages);
    for (UsageInfo usageInfo : usages) {
      if (!(usageInfo instanceof ReplaceExtendsListUsageInfo)) {
        try {
          ((FixableUsageInfo) usageInfo).fixUsage();
        } catch (IncorrectOperationException e) {
          LOG.info(e);
        }
      }
    }
    replaceInnerTypeUsages();

    // postpone broken hierarchy
    for (UsageInfo usage : usages) {
      if (usage instanceof ReplaceExtendsListUsageInfo) {
        ((ReplaceExtendsListUsageInfo) usage).fixUsage();
      }
    }
    try {
      mySuperClass.delete();
    } catch (IncorrectOperationException e) {
      LOG.error(e);
    }
  }
  protected void findUsages(@NotNull final List<FixableUsageInfo> usages) {
    final JavaPsiFacade facade = JavaPsiFacade.getInstance(myProject);
    final PsiElementFactory elementFactory = facade.getElementFactory();
    final PsiResolveHelper resolveHelper = facade.getResolveHelper();

    ReferencesSearch.search(mySuperClass)
        .forEach(
            new Processor<PsiReference>() {
              public boolean process(final PsiReference reference) {
                final PsiElement element = reference.getElement();
                if (element instanceof PsiJavaCodeReferenceElement) {
                  final PsiImportStaticStatement staticImportStatement =
                      PsiTreeUtil.getParentOfType(element, PsiImportStaticStatement.class);
                  if (staticImportStatement != null) {
                    usages.add(
                        new ReplaceStaticImportUsageInfo(staticImportStatement, myTargetClasses));
                  } else {
                    final PsiImportStatement importStatement =
                        PsiTreeUtil.getParentOfType(element, PsiImportStatement.class);
                    if (importStatement != null) {
                      usages.add(new RemoveImportUsageInfo(importStatement));
                    } else {
                      final PsiElement parent = element.getParent();
                      if (parent instanceof PsiReferenceList) {
                        final PsiElement pparent = parent.getParent();
                        if (pparent instanceof PsiClass) {
                          final PsiClass inheritor = (PsiClass) pparent;
                          if (parent.equals(inheritor.getExtendsList())
                              || parent.equals(inheritor.getImplementsList())) {
                            usages.add(
                                new ReplaceExtendsListUsageInfo(
                                    (PsiJavaCodeReferenceElement) element,
                                    mySuperClass,
                                    inheritor));
                          }
                        }
                      } else {
                        final PsiClass targetClass = myTargetClasses[0];
                        final PsiClassType targetClassType =
                            elementFactory.createType(
                                targetClass,
                                TypeConversionUtil.getSuperClassSubstitutor(
                                    mySuperClass, targetClass, PsiSubstitutor.EMPTY));

                        if (parent instanceof PsiTypeElement) {
                          final PsiType superClassType = ((PsiTypeElement) parent).getType();
                          PsiSubstitutor subst =
                              getSuperClassSubstitutor(
                                  superClassType, targetClassType, resolveHelper, targetClass);
                          usages.add(
                              new ReplaceWithSubtypeUsageInfo(
                                  ((PsiTypeElement) parent),
                                  elementFactory.createType(targetClass, subst),
                                  myTargetClasses));
                        } else if (parent instanceof PsiNewExpression) {
                          final PsiClassType newType =
                              elementFactory.createType(
                                  targetClass,
                                  getSuperClassSubstitutor(
                                      ((PsiNewExpression) parent).getType(),
                                      targetClassType,
                                      resolveHelper,
                                      targetClass));
                          usages.add(
                              new ReplaceConstructorUsageInfo(
                                  ((PsiNewExpression) parent), newType, myTargetClasses));
                        } else if (parent instanceof PsiJavaCodeReferenceElement) {
                          usages.add(
                              new ReplaceReferenceUsageInfo(
                                  ((PsiJavaCodeReferenceElement) parent).getQualifier(),
                                  myTargetClasses));
                        }
                      }
                    }
                  }
                }
                return true;
              }
            });
    for (PsiClass targetClass : myTargetClasses) {
      for (MemberInfo memberInfo : myMemberInfos) {
        final PsiMember member = memberInfo.getMember();
        for (PsiReference reference : ReferencesSearch.search(member, member.getUseScope(), true)) {
          final PsiElement element = reference.getElement();
          if (element instanceof PsiReferenceExpression
              && ((PsiReferenceExpression) element).getQualifierExpression()
                  instanceof PsiSuperExpression
              && PsiTreeUtil.isAncestor(targetClass, element, false)) {
            usages.add(new RemoveQualifierUsageInfo((PsiReferenceExpression) element));
          }
        }
      }

      final PsiMethod[] superConstructors = mySuperClass.getConstructors();
      for (PsiMethod constructor : targetClass.getConstructors()) {
        final PsiCodeBlock constrBody = constructor.getBody();
        LOG.assertTrue(constrBody != null);
        final PsiStatement[] statements = constrBody.getStatements();
        if (statements.length > 0) {
          final PsiStatement firstConstrStatement = statements[0];
          if (firstConstrStatement instanceof PsiExpressionStatement) {
            final PsiExpression expression =
                ((PsiExpressionStatement) firstConstrStatement).getExpression();
            if (expression instanceof PsiMethodCallExpression) {
              final PsiReferenceExpression methodExpression =
                  ((PsiMethodCallExpression) expression).getMethodExpression();
              if (methodExpression.getText().equals(PsiKeyword.SUPER)) {
                final PsiMethod superConstructor =
                    ((PsiMethodCallExpression) expression).resolveMethod();
                if (superConstructor != null && superConstructor.getBody() != null) {
                  usages.add(new InlineSuperCallUsageInfo((PsiMethodCallExpression) expression));
                  continue;
                }
              }
            }
          }
        }

        // insert implicit call to super
        for (PsiMethod superConstructor : superConstructors) {
          if (superConstructor.getParameterList().getParametersCount() == 0) {
            final PsiExpression expression =
                JavaPsiFacade.getElementFactory(myProject)
                    .createExpressionFromText("super()", constructor);
            usages.add(
                new InlineSuperCallUsageInfo((PsiMethodCallExpression) expression, constrBody));
          }
        }
      }

      if (targetClass.getConstructors().length == 0) {
        // copy default constructor
        for (PsiMethod superConstructor : superConstructors) {
          if (superConstructor.getParameterList().getParametersCount() == 0) {
            usages.add(new CopyDefaultConstructorUsageInfo(targetClass, superConstructor));
            break;
          }
        }
      }
    }
  }
  private void replaceInnerTypeUsages() {
    final JavaPsiFacade facade = JavaPsiFacade.getInstance(myProject);
    final PsiElementFactory elementFactory = facade.getElementFactory();
    final PsiResolveHelper resolveHelper = facade.getResolveHelper();
    final Map<UsageInfo, PsiElement> replacementMap = new HashMap<UsageInfo, PsiElement>();
    for (final PsiClass targetClass : myTargetClasses) {
      final PsiSubstitutor superClassSubstitutor =
          TypeConversionUtil.getSuperClassSubstitutor(
              mySuperClass, targetClass, PsiSubstitutor.EMPTY);
      final PsiClassType targetClassType =
          elementFactory.createType(targetClass, superClassSubstitutor);
      targetClass.accept(
          new JavaRecursiveElementWalkingVisitor() {
            @Override
            public void visitTypeElement(final PsiTypeElement typeElement) {
              super.visitTypeElement(typeElement);
              final PsiType superClassType = typeElement.getType();
              if (PsiUtil.resolveClassInType(superClassType) == mySuperClass) {
                PsiSubstitutor subst =
                    getSuperClassSubstitutor(
                        superClassType, targetClassType, resolveHelper, targetClass);
                replacementMap.put(
                    new UsageInfo(typeElement),
                    elementFactory.createTypeElement(
                        elementFactory.createType(targetClass, subst)));
              }
            }

            @Override
            public void visitNewExpression(final PsiNewExpression expression) {
              super.visitNewExpression(expression);
              final PsiType superClassType = expression.getType();
              if (PsiUtil.resolveClassInType(superClassType) == mySuperClass) {
                PsiSubstitutor subst =
                    getSuperClassSubstitutor(
                        superClassType, targetClassType, resolveHelper, targetClass);
                try {
                  replacementMap.put(
                      new UsageInfo(expression),
                      elementFactory.createExpressionFromText(
                          "new "
                              + elementFactory.createType(targetClass, subst).getCanonicalText()
                              + expression.getArgumentList().getText(),
                          expression));
                } catch (IncorrectOperationException e) {
                  LOG.error(e);
                }
              }
            }
          });
    }
    try {
      for (Map.Entry<UsageInfo, PsiElement> elementEntry : replacementMap.entrySet()) {
        final PsiElement element = elementEntry.getKey().getElement();
        if (element != null) {
          element.replace(elementEntry.getValue());
        }
      }
    } catch (IncorrectOperationException e) {
      LOG.error(e);
    }
  }