private void doMoveClass(PsiSubstitutor substitutor, MemberInfo info) {
   PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject);
   PsiClass aClass = (PsiClass) info.getMember();
   if (Boolean.FALSE.equals(info.getOverrides())) {
     final PsiReferenceList sourceReferenceList = info.getSourceReferenceList();
     LOG.assertTrue(sourceReferenceList != null);
     PsiJavaCodeReferenceElement ref =
         mySourceClass.equals(sourceReferenceList.getParent())
             ? RefactoringUtil.removeFromReferenceList(sourceReferenceList, aClass)
             : RefactoringUtil.findReferenceToClass(sourceReferenceList, aClass);
     if (ref != null && !myTargetSuperClass.isInheritor(aClass, false)) {
       RefactoringUtil.replaceMovedMemberTypeParameters(
           ref, PsiUtil.typeParametersIterable(mySourceClass), substitutor, elementFactory);
       final PsiReferenceList referenceList =
           myIsTargetInterface
               ? myTargetSuperClass.getExtendsList()
               : myTargetSuperClass.getImplementsList();
       assert referenceList != null;
       referenceList.add(ref);
     }
   } else {
     RefactoringUtil.replaceMovedMemberTypeParameters(
         aClass, PsiUtil.typeParametersIterable(mySourceClass), substitutor, elementFactory);
     fixReferencesToStatic(aClass);
     final PsiMember movedElement =
         (PsiMember)
             myTargetSuperClass.add(
                 convertClassToLanguage(aClass, myTargetSuperClass.getLanguage()));
     myMembersAfterMove.add(movedElement);
     aClass.delete();
   }
 }
  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);
    }
  }
  @Nullable
  public static PsiElement doCopyClasses(
      final Map<PsiFile, PsiClass[]> fileToClasses,
      @Nullable HashMap<PsiFile, String> map,
      final String copyClassName,
      final PsiDirectory targetDirectory,
      final Project project)
      throws IncorrectOperationException {
    PsiElement newElement = null;
    final Map<PsiClass, PsiElement> oldToNewMap = new HashMap<PsiClass, PsiElement>();
    for (final PsiClass[] psiClasses : fileToClasses.values()) {
      if (psiClasses != null) {
        for (PsiClass aClass : psiClasses) {
          if (aClass instanceof SyntheticElement) {
            continue;
          }
          oldToNewMap.put(aClass, null);
        }
      }
    }
    final List<PsiFile> createdFiles = new ArrayList<PsiFile>(fileToClasses.size());
    int[] choice = fileToClasses.size() > 1 ? new int[] {-1} : null;
    List<PsiFile> files = new ArrayList<PsiFile>();
    for (final Map.Entry<PsiFile, PsiClass[]> entry : fileToClasses.entrySet()) {
      final PsiFile psiFile = entry.getKey();
      final PsiClass[] sources = entry.getValue();
      if (psiFile instanceof PsiClassOwner && sources != null) {
        final PsiFile createdFile =
            copy(
                psiFile,
                targetDirectory,
                copyClassName,
                map == null ? null : map.get(psiFile),
                choice);
        if (createdFile == null) return null;
        for (final PsiClass destination : ((PsiClassOwner) createdFile).getClasses()) {
          if (destination instanceof SyntheticElement) {
            continue;
          }
          PsiClass source = findByName(sources, destination.getName());
          if (source != null) {
            final PsiClass copy = copy(source, copyClassName);
            newElement = destination.replace(copy);
            oldToNewMap.put(source, newElement);
          } else {
            destination.delete();
          }
        }
        createdFiles.add(createdFile);
      } else {
        files.add(psiFile);
      }
    }

    for (PsiFile file : files) {
      try {
        PsiDirectory finalTarget = targetDirectory;
        final String relativePath = map != null ? map.get(file) : null;
        if (relativePath != null && !relativePath.isEmpty()) {
          finalTarget =
              buildRelativeDir(targetDirectory, relativePath).findOrCreateTargetDirectory();
        }
        final PsiFile fileCopy =
            CopyFilesOrDirectoriesHandler.copyToDirectory(
                file, getNewFileName(file, copyClassName), finalTarget, choice);
        if (fileCopy != null) {
          createdFiles.add(fileCopy);
        }
      } catch (IOException e) {
        throw new IncorrectOperationException(e.getMessage());
      }
    }

    final Set<PsiElement> rebindExpressions = new HashSet<PsiElement>();
    for (PsiElement element : oldToNewMap.values()) {
      if (element == null) {
        LOG.error(oldToNewMap.keySet());
        continue;
      }
      decodeRefs(element, oldToNewMap, rebindExpressions);
    }

    final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
    for (PsiFile psiFile : createdFiles) {
      if (psiFile instanceof PsiJavaFile) {
        codeStyleManager.removeRedundantImports((PsiJavaFile) psiFile);
      }
    }
    for (PsiElement expression : rebindExpressions) {
      codeStyleManager.shortenClassReferences(expression);
    }
    new OptimizeImportsProcessor(
            project, createdFiles.toArray(new PsiFile[createdFiles.size()]), null)
        .run();
    return newElement != null ? newElement : createdFiles.size() > 0 ? createdFiles.get(0) : null;
  }