protected void performRefactoring(UsageInfo[] usages) {
    if (!CommonRefactoringUtil.checkReadOnlyStatus(myProject, myTargetClass)) return;

    PsiMethod patternMethod = createMethodToAdd();
    final List<PsiReference> docRefs = new ArrayList<PsiReference>();
    for (UsageInfo usage : usages) {
      if (usage instanceof InheritorUsageInfo) {
        final PsiClass inheritor = ((InheritorUsageInfo) usage).getInheritor();
        addMethodToClass(inheritor, patternMethod, true);
      } else if (usage instanceof MethodCallUsageInfo
          && !((MethodCallUsageInfo) usage).isInternal()) {
        correctMethodCall(((MethodCallUsageInfo) usage).getMethodCallExpression(), false);
      } else if (usage instanceof JavadocUsageInfo) {
        docRefs.add(usage.getElement().getReference());
      }
    }

    try {
      if (myTargetClass.isInterface()) patternMethod.getBody().delete();

      final PsiMethod method = addMethodToClass(myTargetClass, patternMethod, false);
      myMethod.delete();
      for (PsiReference reference : docRefs) {
        reference.bindToElement(method);
      }
      VisibilityUtil.fixVisibility(usages, method, myNewVisibility);
    } catch (IncorrectOperationException e) {
      LOG.error(e);
    }
  }
  @NotNull
  protected UsageInfo[] findUsages() {
    final PsiManager manager = myMethod.getManager();
    final GlobalSearchScope searchScope = GlobalSearchScope.allScope(manager.getProject());
    final List<UsageInfo> usages = new ArrayList<UsageInfo>();
    for (PsiReference ref : ReferencesSearch.search(myMethod, searchScope, false)) {
      final PsiElement element = ref.getElement();
      if (element instanceof PsiReferenceExpression) {
        boolean isInternal = PsiTreeUtil.isAncestor(myMethod, element, true);
        usages.add(new MethodCallUsageInfo((PsiReferenceExpression) element, isInternal));
      } else if (element instanceof PsiDocTagValue) {
        usages.add(new JavadocUsageInfo(((PsiDocTagValue) element)));
      } else {
        throw new UnknownReferenceTypeException(element.getLanguage());
      }
    }

    if (myTargetClass.isInterface()) {
      addInheritorUsages(myTargetClass, searchScope, usages);
    }

    final PsiCodeBlock body = myMethod.getBody();
    if (body != null) {
      body.accept(
          new JavaRecursiveElementWalkingVisitor() {
            @Override
            public void visitNewExpression(PsiNewExpression expression) {
              if (MoveInstanceMembersUtil.getClassReferencedByThis(expression) != null) {
                usages.add(new InternalUsageInfo(expression));
              }
              super.visitNewExpression(expression);
            }

            @Override
            public void visitReferenceExpression(PsiReferenceExpression expression) {
              if (MoveInstanceMembersUtil.getClassReferencedByThis(expression) != null) {
                usages.add(new InternalUsageInfo(expression));
              } else if (!expression.isQualified()) {
                final PsiElement resolved = expression.resolve();
                if (myTargetVariable.equals(resolved)) {
                  usages.add(new InternalUsageInfo(expression));
                }
              }

              super.visitReferenceExpression(expression);
            }
          });
    }

    return usages.toArray(new UsageInfo[usages.size()]);
  }
  public static void doRenameGenericNamedElement(
      @NotNull PsiElement namedElement,
      String newName,
      UsageInfo[] usages,
      @Nullable RefactoringElementListener listener)
      throws IncorrectOperationException {
    PsiWritableMetaData writableMetaData = null;
    if (namedElement instanceof PsiMetaOwner) {
      final PsiMetaData metaData = ((PsiMetaOwner) namedElement).getMetaData();
      if (metaData instanceof PsiWritableMetaData) {
        writableMetaData = (PsiWritableMetaData) metaData;
      }
    }
    if (writableMetaData == null && !(namedElement instanceof PsiNamedElement)) {
      LOG.error("Unknown element type:" + namedElement);
    }

    boolean hasBindables = false;
    for (UsageInfo usage : usages) {
      if (!(usage.getReference() instanceof BindablePsiReference)) {
        rename(usage, newName);
      } else {
        hasBindables = true;
      }
    }

    if (writableMetaData != null) {
      writableMetaData.setName(newName);
    } else {
      PsiElement namedElementAfterRename = ((PsiNamedElement) namedElement).setName(newName);
      if (namedElementAfterRename != null) namedElement = namedElementAfterRename;
    }

    if (hasBindables) {
      for (UsageInfo usage : usages) {
        final PsiReference ref = usage.getReference();
        if (ref instanceof BindablePsiReference) {
          try {
            ref.bindToElement(namedElement);
          } catch (IncorrectOperationException e) { // fall back to old scheme
            ref.handleElementRename(newName);
          }
        }
      }
    }
    if (listener != null) {
      listener.elementRenamed(namedElement);
    }
  }
  @NotNull
  protected UsageInfo[] findUsages() {
    ArrayList<UsageInfo> result = new ArrayList<UsageInfo>();

    PsiMethod[] overridingMethods =
        OverridingMethodsSearch.search(myMethodToSearchFor, true).toArray(PsiMethod.EMPTY_ARRAY);
    for (PsiMethod overridingMethod : overridingMethods) {
      result.add(new UsageInfo(overridingMethod));
    }
    if (!myGenerateDelegate) {
      PsiReference[] refs =
          MethodReferencesSearch.search(
                  myMethodToSearchFor, GlobalSearchScope.projectScope(myProject), true)
              .toArray(PsiReference.EMPTY_ARRAY);

      for (PsiReference ref1 : refs) {
        PsiElement ref = ref1.getElement();
        if (ref instanceof PsiMethod && ((PsiMethod) ref).isConstructor()) {
          DefaultConstructorImplicitUsageInfo implicitUsageInfo =
              new DefaultConstructorImplicitUsageInfo(
                  (PsiMethod) ref, ((PsiMethod) ref).getContainingClass(), myMethodToSearchFor);
          result.add(implicitUsageInfo);
        } else if (ref instanceof PsiClass) {
          result.add(new NoConstructorClassUsageInfo((PsiClass) ref));
        } else if (!IntroduceParameterUtil.insideMethodToBeReplaced(ref, myMethodToReplaceIn)) {
          result.add(new ExternalUsageInfo(ref));
        } else {
          result.add(new ChangedMethodCallInfo(ref));
        }
      }
    }

    if (myReplaceAllOccurences) {
      for (PsiElement expr : getOccurrences()) {
        result.add(new InternalUsageInfo(expr));
      }
    } else {
      if (myExpressionToSearch != null && myExpressionToSearch.isValid()) {
        result.add(new InternalUsageInfo(myExpressionToSearch));
      }
    }

    final UsageInfo[] usageInfos = result.toArray(new UsageInfo[result.size()]);
    return UsageViewUtil.removeDuplicatedUsages(usageInfos);
  }
  protected void performRefactoring(UsageInfo[] usages) {
    if (!CommonRefactoringUtil.checkReadOnlyStatus(myProject, myTargetClass)) return;

    PsiMethod patternMethod = createMethodToAdd();
    final List<PsiReference> docRefs = new ArrayList<PsiReference>();
    for (UsageInfo usage : usages) {
      if (usage instanceof InheritorUsageInfo) {
        final PsiClass inheritor = ((InheritorUsageInfo) usage).getInheritor();
        addMethodToClass(inheritor, patternMethod, true);
      } else if (usage instanceof MethodCallUsageInfo
          && !((MethodCallUsageInfo) usage).isInternal()) {
        final PsiElement expression = ((MethodCallUsageInfo) usage).getMethodCallExpression();
        if (expression instanceof PsiMethodCallExpression) {
          correctMethodCall((PsiMethodCallExpression) expression, false);
        } else if (expression instanceof PsiMethodReferenceExpression) {
          PsiExpression newQualifier =
              JavaPsiFacade.getInstance(myProject)
                  .getElementFactory()
                  .createExpressionFromText(myTargetVariable.getType().getCanonicalText(), null);
          ((PsiMethodReferenceExpression) expression).setQualifierExpression(newQualifier);
        }
      } else if (usage instanceof JavadocUsageInfo) {
        docRefs.add(usage.getElement().getReference());
      }
    }

    try {
      if (myTargetClass.isInterface()) patternMethod.getBody().delete();

      final PsiMethod method = addMethodToClass(myTargetClass, patternMethod, false);
      myMethod.delete();
      for (PsiReference reference : docRefs) {
        reference.bindToElement(method);
      }
      VisibilityUtil.fixVisibility(UsageViewUtil.toElements(usages), method, myNewVisibility);

      if (myOpenInEditor) {
        EditorHelper.openInEditor(method);
      }
    } catch (IncorrectOperationException e) {
      LOG.error(e);
    }
  }
  @NotNull
  public static UsageInfo[] findUsages(
      final PsiElement element,
      final String newName,
      boolean searchInStringsAndComments,
      boolean searchForTextOccurrences,
      Map<? extends PsiElement, String> allRenames) {
    final List<UsageInfo> result = Collections.synchronizedList(new ArrayList<UsageInfo>());

    PsiManager manager = element.getManager();
    GlobalSearchScope projectScope = GlobalSearchScope.projectScope(manager.getProject());
    RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(element);

    Collection<PsiReference> refs = processor.findReferences(element, searchInStringsAndComments);
    for (final PsiReference ref : refs) {
      if (ref == null) {
        LOG.error("null reference from processor " + processor);
        continue;
      }
      PsiElement referenceElement = ref.getElement();
      result.add(
          new MoveRenameUsageInfo(
              referenceElement,
              ref,
              ref.getRangeInElement().getStartOffset(),
              ref.getRangeInElement().getEndOffset(),
              element,
              ref.resolve() == null));
    }

    processor.findCollisions(element, newName, allRenames, result);

    final PsiElement searchForInComments =
        processor.getElementToSearchInStringsAndComments(element);

    if (searchInStringsAndComments && searchForInComments != null) {
      String stringToSearch =
          ElementDescriptionUtil.getElementDescription(
              searchForInComments, NonCodeSearchDescriptionLocation.STRINGS_AND_COMMENTS);
      if (stringToSearch.length() > 0) {
        final String stringToReplace = getStringToReplace(element, newName, false, processor);
        TextOccurrencesUtil.UsageInfoFactory factory =
            new NonCodeUsageInfoFactory(searchForInComments, stringToReplace);
        TextOccurrencesUtil.addUsagesInStringsAndComments(
            searchForInComments, stringToSearch, result, factory);
      }
    }

    if (searchForTextOccurrences && searchForInComments != null) {
      String stringToSearch =
          ElementDescriptionUtil.getElementDescription(
              searchForInComments, NonCodeSearchDescriptionLocation.NON_JAVA);
      if (stringToSearch.length() > 0) {
        final String stringToReplace = getStringToReplace(element, newName, true, processor);
        addTextOccurrence(
            searchForInComments, result, projectScope, stringToSearch, stringToReplace);
      }

      final Pair<String, String> additionalStringToSearch =
          processor.getTextOccurrenceSearchStrings(searchForInComments, newName);
      if (additionalStringToSearch != null && additionalStringToSearch.first.length() > 0) {
        addTextOccurrence(
            searchForInComments,
            result,
            projectScope,
            additionalStringToSearch.first,
            additionalStringToSearch.second);
      }
    }

    return result.toArray(new UsageInfo[result.size()]);
  }
 public static void rename(UsageInfo info, String newName) throws IncorrectOperationException {
   if (info.getElement() == null) return;
   PsiReference ref = info.getReference();
   if (ref == null) return;
   ref.handleElementRename(newName);
 }
  public boolean processUsage(
      ChangeInfo changeInfo, UsageInfo usage, boolean beforeMethodChange, UsageInfo[] usages) {
    if (!isJavaUsage(usage)) return false;
    if (!(changeInfo instanceof JavaChangeInfo)) return false;

    if (beforeMethodChange) {
      if (usage instanceof CallerUsageInfo) {
        final CallerUsageInfo callerUsageInfo = (CallerUsageInfo) usage;
        processCallerMethod(
            (JavaChangeInfo) changeInfo,
            callerUsageInfo.getMethod(),
            null,
            callerUsageInfo.isToInsertParameter(),
            callerUsageInfo.isToInsertException());
        return true;
      } else if (usage instanceof OverriderUsageInfo) {
        OverriderUsageInfo info = (OverriderUsageInfo) usage;
        final PsiMethod method = info.getElement();
        final PsiMethod baseMethod = info.getBaseMethod();
        if (info.isOriginalOverrider()) {
          processPrimaryMethod((JavaChangeInfo) changeInfo, method, baseMethod, false);
        } else {
          processCallerMethod(
              (JavaChangeInfo) changeInfo,
              method,
              baseMethod,
              info.isToInsertArgs(),
              info.isToCatchExceptions());
        }
        return true;
      }

    } else {
      PsiElement element = usage.getElement();
      LOG.assertTrue(element != null);

      if (usage instanceof DefaultConstructorImplicitUsageInfo) {
        final DefaultConstructorImplicitUsageInfo defConstructorUsage =
            (DefaultConstructorImplicitUsageInfo) usage;
        PsiMethod constructor = defConstructorUsage.getConstructor();
        if (!constructor.isPhysical()) {
          final boolean toPropagate =
              changeInfo instanceof JavaChangeInfoImpl
                  && ((JavaChangeInfoImpl) changeInfo)
                      .propagateParametersMethods.remove(constructor);
          final PsiClass containingClass = defConstructorUsage.getContainingClass();
          constructor = (PsiMethod) containingClass.add(constructor);
          PsiUtil.setModifierProperty(
              constructor,
              VisibilityUtil.getVisibilityModifier(containingClass.getModifierList()),
              true);
          if (toPropagate) {
            ((JavaChangeInfoImpl) changeInfo).propagateParametersMethods.add(constructor);
          }
        }
        addSuperCall(
            (JavaChangeInfo) changeInfo,
            constructor,
            defConstructorUsage.getBaseConstructor(),
            usages);
        return true;
      } else if (usage instanceof NoConstructorClassUsageInfo) {
        addDefaultConstructor(
            ((JavaChangeInfo) changeInfo),
            ((NoConstructorClassUsageInfo) usage).getPsiClass(),
            usages);
        return true;
      } else if (usage instanceof MethodCallUsageInfo) {
        final MethodCallUsageInfo methodCallInfo = (MethodCallUsageInfo) usage;
        processMethodUsage(
            methodCallInfo.getElement(),
            (JavaChangeInfo) changeInfo,
            methodCallInfo.isToChangeArguments(),
            methodCallInfo.isToCatchExceptions(),
            methodCallInfo.getReferencedMethod(),
            methodCallInfo.getSubstitutor(),
            usages);
        return true;
      } else if (usage instanceof ChangeSignatureParameterUsageInfo) {
        String newName = ((ChangeSignatureParameterUsageInfo) usage).newParameterName;
        String oldName = ((ChangeSignatureParameterUsageInfo) usage).oldParameterName;
        processParameterUsage((PsiReferenceExpression) element, oldName, newName);
        return true;
      } else if (usage instanceof CallReferenceUsageInfo) {
        ((CallReferenceUsageInfo) usage).getReference().handleChangeSignature(changeInfo);
        return true;
      } else if (element instanceof PsiEnumConstant) {
        fixActualArgumentsList(
            ((PsiEnumConstant) element).getArgumentList(),
            (JavaChangeInfo) changeInfo,
            true,
            PsiSubstitutor.EMPTY);
        return true;
      } else if (!(usage instanceof OverriderUsageInfo)) {
        PsiReference reference =
            usage instanceof MoveRenameUsageInfo ? usage.getReference() : element.getReference();
        if (reference != null) {
          PsiElement target = changeInfo.getMethod();
          if (target != null) {
            reference.bindToElement(target);
          }
        }
      }
    }
    return false;
  }