@NotNull
  public UsageInfo[] findUsages() {
    myRenamers.clear();
    ArrayList<UsageInfo> result = new ArrayList<UsageInfo>();

    List<PsiElement> elements = new ArrayList<PsiElement>(myAllRenames.keySet());
    //noinspection ForLoopReplaceableByForEach
    for (int i = 0; i < elements.size(); i++) {
      PsiElement element = elements.get(i);
      final String newName = myAllRenames.get(element);
      final UsageInfo[] usages =
          RenameUtil.findUsages(
              element, newName, mySearchInComments, mySearchTextOccurrences, myAllRenames);
      final List<UsageInfo> usagesList = Arrays.asList(usages);
      result.addAll(usagesList);

      for (AutomaticRenamerFactory factory : myRenamerFactories) {
        if (factory.isApplicable(element)) {
          myRenamers.add(factory.createRenamer(element, newName, usagesList));
        }
      }

      for (AutomaticRenamerFactory factory :
          Extensions.getExtensions(AutomaticRenamerFactory.EP_NAME)) {
        if (factory.getOptionName() == null && factory.isApplicable(element)) {
          myRenamers.add(factory.createRenamer(element, newName, usagesList));
        }
      }
    }
    UsageInfo[] usageInfos = result.toArray(new UsageInfo[result.size()]);
    usageInfos = UsageViewUtil.removeDuplicatedUsages(usageInfos);
    return usageInfos;
  }
  protected void refreshElements(PsiElement[] elements) {
    LOG.assertTrue(elements.length > 0);
    if (myPrimaryElement != null) {
      myPrimaryElement = elements[0];
    }

    final Iterator<String> newNames = myAllRenames.values().iterator();
    LinkedHashMap<PsiElement, String> newAllRenames = new LinkedHashMap<PsiElement, String>();
    for (PsiElement resolved : elements) {
      newAllRenames.put(resolved, newNames.next());
    }
    myAllRenames.clear();
    myAllRenames.putAll(newAllRenames);
  }
  private void setNewName(@NotNull String newName) {
    if (myPrimaryElement == null) {
      myCommandName = RefactoringBundle.message("renaming.something");
      return;
    }

    myNewName = newName;
    myAllRenames.put(myPrimaryElement, newName);
    myCommandName =
        RefactoringBundle.message(
            "renaming.0.1.to.2",
            UsageViewUtil.getType(myPrimaryElement),
            UsageViewUtil.getDescriptiveName(myPrimaryElement),
            newName);
  }
 public Collection<String> getNewNames() {
   return myAllRenames.values();
 }
  public void performRefactoring(UsageInfo[] usages) {
    final int[] choice = myAllRenames.size() > 1 ? new int[] {-1} : null;
    String message = null;
    try {
      for (Iterator<Map.Entry<PsiElement, String>> iterator = myAllRenames.entrySet().iterator();
          iterator.hasNext(); ) {
        Map.Entry<PsiElement, String> entry = iterator.next();
        if (entry.getKey() instanceof PsiFile) {
          final PsiFile file = (PsiFile) entry.getKey();
          final PsiDirectory containingDirectory = file.getContainingDirectory();
          if (CopyFilesOrDirectoriesHandler.checkFileExist(
              containingDirectory, choice, file, entry.getValue(), "Rename")) {
            iterator.remove();
            continue;
          }
        }
        RenameUtil.checkRename(entry.getKey(), entry.getValue());
      }
    } catch (IncorrectOperationException e) {
      message = e.getMessage();
    }

    if (message != null) {
      CommonRefactoringUtil.showErrorMessage(
          RefactoringBundle.message("rename.title"), message, getHelpID(), myProject);
      return;
    }

    List<Runnable> postRenameCallbacks = new ArrayList<Runnable>();

    final MultiMap<PsiElement, UsageInfo> classified =
        classifyUsages(myAllRenames.keySet(), usages);
    for (final PsiElement element : myAllRenames.keySet()) {
      String newName = myAllRenames.get(element);

      final RefactoringElementListener elementListener =
          getTransaction().getElementListener(element);
      final RenamePsiElementProcessor renamePsiElementProcessor =
          RenamePsiElementProcessor.forElement(element);
      Runnable postRenameCallback =
          renamePsiElementProcessor.getPostRenameCallback(element, newName, elementListener);
      final Collection<UsageInfo> infos = classified.get(element);
      try {
        RenameUtil.doRename(
            element,
            newName,
            infos.toArray(new UsageInfo[infos.size()]),
            myProject,
            elementListener);
      } catch (final IncorrectOperationException e) {
        RenameUtil.showErrorMessage(e, element, myProject);
        return;
      }
      if (postRenameCallback != null) {
        postRenameCallbacks.add(postRenameCallback);
      }
    }

    for (Runnable runnable : postRenameCallbacks) {
      runnable.run();
    }

    List<NonCodeUsageInfo> nonCodeUsages = new ArrayList<NonCodeUsageInfo>();
    for (UsageInfo usage : usages) {
      if (usage instanceof NonCodeUsageInfo) {
        nonCodeUsages.add((NonCodeUsageInfo) usage);
      }
    }
    myNonCodeUsages = nonCodeUsages.toArray(new NonCodeUsageInfo[nonCodeUsages.size()]);
    if (!mySkippedUsages.isEmpty()) {
      if (!ApplicationManager.getApplication().isUnitTestMode()
          && !ApplicationManager.getApplication().isHeadlessEnvironment()) {
        ApplicationManager.getApplication()
            .invokeLater(
                new Runnable() {
                  public void run() {
                    final IdeFrame ideFrame = WindowManager.getInstance().getIdeFrame(myProject);
                    if (ideFrame != null) {

                      StatusBarEx statusBar = (StatusBarEx) ideFrame.getStatusBar();
                      HyperlinkListener listener =
                          new HyperlinkListener() {
                            public void hyperlinkUpdate(HyperlinkEvent e) {
                              if (e.getEventType() != HyperlinkEvent.EventType.ACTIVATED) return;
                              Messages.showMessageDialog(
                                  "<html>"
                                      + StringUtil.join(
                                          mySkippedUsages,
                                          new Function<UnresolvableCollisionUsageInfo, String>() {
                                            public String fun(
                                                UnresolvableCollisionUsageInfo
                                                    unresolvableCollisionUsageInfo) {
                                              return unresolvableCollisionUsageInfo
                                                  .getDescription();
                                            }
                                          },
                                          "<br>")
                                      + "</html>",
                                  "Don't panic! They are safe to skip",
                                  null);
                            }
                          };
                      statusBar.notifyProgressByBalloon(
                          MessageType.WARNING,
                          "<html><body>Unable to rename certain usages. <a href=\"\">Browse</a></body></html>",
                          null,
                          listener);
                    }
                  }
                },
                ModalityState.NON_MODAL);
      }
    }
  }
 public void addElement(@NotNull PsiElement element, @NotNull String newName) {
   myAllRenames.put(element, newName);
 }
  public boolean preprocessUsages(final Ref<UsageInfo[]> refUsages) {
    UsageInfo[] usagesIn = refUsages.get();
    MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();

    RenameUtil.addConflictDescriptions(usagesIn, conflicts);
    RenamePsiElementProcessor.forElement(myPrimaryElement)
        .findExistingNameConflicts(myPrimaryElement, myNewName, conflicts);
    if (!conflicts.isEmpty()) {
      if (ApplicationManager.getApplication().isUnitTestMode()) {
        throw new ConflictsInTestsException(conflicts.values());
      }
      ConflictsDialog conflictsDialog = prepareConflictsDialog(conflicts, refUsages.get());
      conflictsDialog.show();
      if (!conflictsDialog.isOK()) {
        if (conflictsDialog.isShowConflicts()) prepareSuccessful();
        return false;
      }
    }

    final List<UsageInfo> variableUsages = new ArrayList<UsageInfo>();
    if (!myRenamers.isEmpty()) {
      if (!findRenamedVariables(variableUsages)) return false;
      final LinkedHashMap<PsiElement, String> renames = new LinkedHashMap<PsiElement, String>();
      for (final AutomaticRenamer renamer : myRenamers) {
        final List<? extends PsiNamedElement> variables = renamer.getElements();
        for (final PsiNamedElement variable : variables) {
          final String newName = renamer.getNewName(variable);
          if (newName != null) {
            addElement(variable, newName);
            prepareRenaming(variable, newName, renames);
          }
        }
      }
      if (!renames.isEmpty()) {
        myAllRenames.putAll(renames);
        final Runnable runnable =
            new Runnable() {
              public void run() {
                for (Map.Entry<PsiElement, String> entry : renames.entrySet()) {
                  final UsageInfo[] usages =
                      RenameUtil.findUsages(
                          entry.getKey(),
                          entry.getValue(),
                          mySearchInComments,
                          mySearchTextOccurrences,
                          myAllRenames);
                  Collections.addAll(variableUsages, usages);
                }
              }
            };
        if (!ProgressManager.getInstance()
            .runProcessWithProgressSynchronously(
                runnable, RefactoringBundle.message("searching.for.variables"), true, myProject)) {
          return false;
        }
      }
    }

    final Set<UsageInfo> usagesSet = new HashSet<UsageInfo>(Arrays.asList(usagesIn));
    usagesSet.addAll(variableUsages);
    final List<UnresolvableCollisionUsageInfo> conflictUsages =
        RenameUtil.removeConflictUsages(usagesSet);
    if (conflictUsages != null) {
      mySkippedUsages.addAll(conflictUsages);
    }
    refUsages.set(usagesSet.toArray(new UsageInfo[usagesSet.size()]));

    prepareSuccessful();
    return true;
  }
 public Set<PsiElement> getElements() {
   return Collections.unmodifiableSet(myAllRenames.keySet());
 }
  private void tryToMoveInitializers(
      PsiMethod constructor,
      HashSet<PsiMethod> subConstructors,
      LinkedHashSet<PsiField> movedFields)
      throws IncorrectOperationException {
    final LinkedHashMap<PsiField, Initializer> fieldsToInitializers =
        new LinkedHashMap<PsiField, Initializer>();
    boolean anyFound = false;

    for (PsiField field : movedFields) {
      PsiStatement commonInitializer = null;
      final ArrayList<PsiElement> fieldInitializersToRemove = new ArrayList<PsiElement>();
      for (PsiMethod subConstructor : subConstructors) {
        commonInitializer =
            hasCommonInitializer(
                commonInitializer, subConstructor, field, fieldInitializersToRemove);
        if (commonInitializer == null) break;
      }
      if (commonInitializer != null) {
        final ParametersAndMovedFieldsUsedCollector visitor =
            new ParametersAndMovedFieldsUsedCollector(movedFields);
        commonInitializer.accept(visitor);
        fieldsToInitializers.put(
            field,
            new Initializer(
                commonInitializer,
                visitor.getUsedFields(),
                visitor.getUsedParameters(),
                fieldInitializersToRemove));
        anyFound = true;
      }
    }

    if (!anyFound) return;

    {
      final Set<PsiField> initializedFields = fieldsToInitializers.keySet();
      Set<PsiField> unmovable =
          RefactoringUtil.transitiveClosure(
              new RefactoringUtil.Graph<PsiField>() {
                public Set<PsiField> getVertices() {
                  return initializedFields;
                }

                public Set<PsiField> getTargets(PsiField source) {
                  return fieldsToInitializers.get(source).movedFieldsUsed;
                }
              },
              new Condition<PsiField>() {
                public boolean value(PsiField object) {
                  return !initializedFields.contains(object);
                }
              });

      for (PsiField psiField : unmovable) {
        fieldsToInitializers.remove(psiField);
      }
    }

    final PsiElementFactory factory = JavaPsiFacade.getElementFactory(myProject);

    if (constructor == null) {
      constructor = (PsiMethod) myTargetSuperClass.add(factory.createConstructor());
      final String visibilityModifier =
          VisibilityUtil.getVisibilityModifier(myTargetSuperClass.getModifierList());
      PsiUtil.setModifierProperty(constructor, visibilityModifier, true);
    }

    ArrayList<PsiField> initializedFields = new ArrayList<PsiField>(fieldsToInitializers.keySet());

    Collections.sort(
        initializedFields,
        new Comparator<PsiField>() {
          public int compare(PsiField field1, PsiField field2) {
            Initializer i1 = fieldsToInitializers.get(field1);
            Initializer i2 = fieldsToInitializers.get(field2);
            if (i1.movedFieldsUsed.contains(field2)) return 1;
            if (i2.movedFieldsUsed.contains(field1)) return -1;
            return 0;
          }
        });

    for (final PsiField initializedField : initializedFields) {
      Initializer initializer = fieldsToInitializers.get(initializedField);

      // correct constructor parameters and subConstructors super calls
      final PsiParameterList parameterList = constructor.getParameterList();
      for (final PsiParameter parameter : initializer.usedParameters) {
        parameterList.add(parameter);
      }

      for (final PsiMethod subConstructor : subConstructors) {
        modifySuperCall(subConstructor, initializer.usedParameters);
      }

      PsiStatement assignmentStatement =
          (PsiStatement) constructor.getBody().add(initializer.initializer);

      PsiManager manager = PsiManager.getInstance(myProject);
      ChangeContextUtil.decodeContextInfo(
          assignmentStatement,
          myTargetSuperClass,
          RefactoringChangeUtil.createThisExpression(manager, null));
      for (PsiElement psiElement : initializer.statementsToRemove) {
        psiElement.delete();
      }
    }
  }