private PsiMethod generateDelegate(final PsiMethod methodToReplaceIn)
      throws IncorrectOperationException {
    final PsiMethod delegate = (PsiMethod) methodToReplaceIn.copy();
    final PsiElementFactory elementFactory =
        JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory();
    ChangeSignatureProcessor.makeEmptyBody(elementFactory, delegate);
    final PsiCallExpression callExpression =
        ChangeSignatureProcessor.addDelegatingCallTemplate(delegate, delegate.getName());
    final PsiExpressionList argumentList = callExpression.getArgumentList();
    assert argumentList != null;
    final PsiParameter[] psiParameters = methodToReplaceIn.getParameterList().getParameters();

    final PsiParameter anchorParameter = getAnchorParameter(methodToReplaceIn);
    if (psiParameters.length == 0) {
      argumentList.add(myParameterInitializer);
    } else {
      if (anchorParameter == null) {
        argumentList.add(myParameterInitializer);
      }
      for (int i = 0; i < psiParameters.length; i++) {
        PsiParameter psiParameter = psiParameters[i];
        if (!myParametersToRemove.contains(i)) {
          final PsiExpression expression =
              elementFactory.createExpressionFromText(psiParameter.getName(), delegate);
          argumentList.add(expression);
        }
        if (psiParameter == anchorParameter) {
          argumentList.add(myParameterInitializer);
        }
      }
    }

    return (PsiMethod)
        methodToReplaceIn.getContainingClass().addBefore(delegate, methodToReplaceIn);
  }
  private void processChangedMethodCall(PsiElement element) throws IncorrectOperationException {
    if (element.getParent() instanceof PsiMethodCallExpression) {
      PsiMethodCallExpression methodCall = (PsiMethodCallExpression) element.getParent();

      if (myMethodToReplaceIn == myMethodToSearchFor
          && PsiTreeUtil.isAncestor(methodCall, myParameterInitializer, false)) return;

      PsiElementFactory factory =
          JavaPsiFacade.getInstance(methodCall.getProject()).getElementFactory();
      PsiExpression expression = factory.createExpressionFromText(myParameterName, null);
      final PsiExpressionList argList = methodCall.getArgumentList();
      final PsiExpression[] exprs = argList.getExpressions();

      boolean first = false;
      PsiElement anchor = null;
      if (myMethodToSearchFor.isVarArgs()) {
        final int oldParamCount = myMethodToSearchFor.getParameterList().getParametersCount() - 1;
        if (exprs.length >= oldParamCount) {
          if (oldParamCount > 1) {
            anchor = exprs[oldParamCount - 2];
          } else {
            first = true;
            anchor = null;
          }
        } else {
          anchor = exprs[exprs.length - 1];
        }
      } else if (exprs.length > 0) {
        anchor = exprs[exprs.length - 1];
      }

      if (anchor != null) {
        argList.addAfter(expression, anchor);
      } else {
        if (first && exprs.length > 0) {
          argList.addBefore(expression, exprs[0]);
        } else {
          argList.add(expression);
        }
      }

      removeParametersFromCall(argList);
    } else {
      LOG.error(element.getParent());
    }
  }
 private static void addDelegateArguments(
     JavaChangeInfo changeInfo, PsiElementFactory factory, final PsiCallExpression callExpression)
     throws IncorrectOperationException {
   final JavaParameterInfo[] newParms = changeInfo.getNewParameters();
   final String[] oldParameterNames = changeInfo.getOldParameterNames();
   for (int i = 0; i < newParms.length; i++) {
     JavaParameterInfo newParm = newParms[i];
     final PsiExpression actualArg;
     if (newParm.getOldIndex() >= 0) {
       actualArg =
           factory.createExpressionFromText(
               oldParameterNames[newParm.getOldIndex()], callExpression);
     } else {
       actualArg = changeInfo.getValue(i, callExpression);
     }
     JavaCodeStyleManager.getInstance(callExpression.getProject())
         .shortenClassReferences(callExpression.getArgumentList().add(actualArg));
   }
 }
 @Nullable
 private static PsiExpression createActualArgument(
     JavaChangeInfo changeInfo,
     final PsiExpressionList list,
     final JavaParameterInfo info,
     final boolean toInsertDefaultValue,
     final PsiExpression[] args)
     throws IncorrectOperationException {
   final PsiElementFactory factory =
       JavaPsiFacade.getInstance(list.getProject()).getElementFactory();
   final int index = info.getOldIndex();
   if (index >= 0) {
     return args[index];
   } else {
     if (toInsertDefaultValue) {
       return createDefaultValue(changeInfo, factory, info, list);
     } else {
       return factory.createExpressionFromText(info.getName(), list);
     }
   }
 }
  @Nullable
  private static PsiExpression createDefaultValue(
      JavaChangeInfo changeInfo,
      final PsiElementFactory factory,
      final JavaParameterInfo info,
      final PsiExpressionList list)
      throws IncorrectOperationException {
    if (info.isUseAnySingleVariable()) {
      final PsiResolveHelper resolveHelper =
          JavaPsiFacade.getInstance(list.getProject()).getResolveHelper();
      final PsiType type = info.getTypeWrapper().getType(changeInfo.getMethod(), list.getManager());
      final VariablesProcessor processor =
          new VariablesProcessor(false) {
            protected boolean check(PsiVariable var, ResolveState state) {
              if (var instanceof PsiField
                  && !resolveHelper.isAccessible((PsiField) var, list, null)) return false;
              if (var instanceof PsiLocalVariable
                  && list.getTextRange().getStartOffset() <= var.getTextRange().getStartOffset())
                return false;
              if (PsiTreeUtil.isAncestor(var, list, false)) return false;
              final PsiType varType = state.get(PsiSubstitutor.KEY).substitute(var.getType());
              return type.isAssignableFrom(varType);
            }

            public boolean execute(PsiElement pe, ResolveState state) {
              super.execute(pe, state);
              return size() < 2;
            }
          };
      PsiScopesUtil.treeWalkUp(processor, list, null);
      if (processor.size() == 1) {
        final PsiVariable result = processor.getResult(0);
        return factory.createExpressionFromText(result.getName(), list);
      }
      if (processor.size() == 0) {
        final PsiClass parentClass = PsiTreeUtil.getParentOfType(list, PsiClass.class);
        if (parentClass != null) {
          PsiClass containingClass = parentClass;
          final Set<PsiClass> containingClasses = new HashSet<PsiClass>();
          while (containingClass != null) {
            if (type.isAssignableFrom(factory.createType(containingClass, PsiSubstitutor.EMPTY))) {
              containingClasses.add(containingClass);
            }
            containingClass = PsiTreeUtil.getParentOfType(containingClass, PsiClass.class);
          }
          if (containingClasses.size() == 1) {
            return RefactoringUtil.createThisExpression(
                parentClass.getManager(),
                containingClasses.contains(parentClass)
                    ? null
                    : containingClasses.iterator().next());
          }
        }
      }
    }
    final PsiCallExpression callExpression =
        PsiTreeUtil.getParentOfType(list, PsiCallExpression.class);
    final String defaultValue = info.getDefaultValue();
    return callExpression != null
        ? info.getValue(callExpression)
        : defaultValue.length() > 0 ? factory.createExpressionFromText(defaultValue, list) : null;
  }
  // This methods works equally well for primary usages as well as for propagated callers' usages
  private static void fixActualArgumentsList(
      PsiExpressionList list,
      JavaChangeInfo changeInfo,
      boolean toInsertDefaultValue,
      PsiSubstitutor substitutor)
      throws IncorrectOperationException {
    final PsiElementFactory factory =
        JavaPsiFacade.getInstance(list.getProject()).getElementFactory();
    if (changeInfo.isParameterSetOrOrderChanged()) {
      if (changeInfo instanceof JavaChangeInfoImpl
          && ((JavaChangeInfoImpl) changeInfo).isPropagationEnabled) {
        final ParameterInfoImpl[] createdParmsInfo =
            ((JavaChangeInfoImpl) changeInfo).getCreatedParmsInfoWithoutVarargs();
        for (ParameterInfoImpl info : createdParmsInfo) {
          PsiExpression newArg;
          if (toInsertDefaultValue) {
            newArg = createDefaultValue(changeInfo, factory, info, list);
          } else {
            newArg = factory.createExpressionFromText(info.getName(), list);
          }
          JavaCodeStyleManager.getInstance(list.getProject())
              .shortenClassReferences(list.add(newArg));
        }
      } else {
        final PsiExpression[] args = list.getExpressions();
        final int nonVarargCount = getNonVarargCount(changeInfo, args);
        final int varargCount = args.length - nonVarargCount;
        if (varargCount < 0) return;
        PsiExpression[] newVarargInitializers = null;

        final int newArgsLength;
        final int newNonVarargCount;
        final JavaParameterInfo[] newParms = changeInfo.getNewParameters();
        if (changeInfo.isArrayToVarargs()) {
          newNonVarargCount = newParms.length - 1;
          final JavaParameterInfo lastNewParm = newParms[newParms.length - 1];
          final PsiExpression arrayToConvert = args[lastNewParm.getOldIndex()];
          if (arrayToConvert instanceof PsiNewExpression) {
            final PsiNewExpression expression = (PsiNewExpression) arrayToConvert;
            final PsiArrayInitializerExpression arrayInitializer = expression.getArrayInitializer();
            if (arrayInitializer != null) {
              newVarargInitializers = arrayInitializer.getInitializers();
            }
          }
          newArgsLength =
              newVarargInitializers == null
                  ? newParms.length
                  : newNonVarargCount + newVarargInitializers.length;
        } else if (changeInfo.isRetainsVarargs()) {
          newNonVarargCount = newParms.length - 1;
          newArgsLength = newNonVarargCount + varargCount;
        } else if (changeInfo.isObtainsVarags()) {
          newNonVarargCount = newParms.length - 1;
          newArgsLength = newNonVarargCount;
        } else {
          newNonVarargCount = newParms.length;
          newArgsLength = newParms.length;
        }

        String[] oldVarargs = null;
        if (changeInfo.wasVararg() && !changeInfo.isRetainsVarargs()) {
          oldVarargs = new String[varargCount];
          for (int i = nonVarargCount; i < args.length; i++) {
            oldVarargs[i - nonVarargCount] = args[i].getText();
          }
        }

        final PsiExpression[] newArgs = new PsiExpression[newArgsLength];
        for (int i = 0; i < newNonVarargCount; i++) {
          if (newParms[i].getOldIndex() == nonVarargCount && oldVarargs != null) {
            PsiType type = newParms[i].createType(changeInfo.getMethod(), list.getManager());
            if (type instanceof PsiArrayType) {
              type = substitutor.substitute(type);
              type = TypeConversionUtil.erasure(type);
              String typeText = type.getCanonicalText();
              if (type instanceof PsiEllipsisType) {
                typeText = typeText.replace("...", "[]");
              }
              String text = "new " + typeText + "{" + StringUtil.join(oldVarargs, ",") + "}";
              newArgs[i] = factory.createExpressionFromText(text, changeInfo.getMethod());
              continue;
            }
          }
          newArgs[i] =
              createActualArgument(changeInfo, list, newParms[i], toInsertDefaultValue, args);
        }
        if (changeInfo.isArrayToVarargs()) {
          if (newVarargInitializers == null) {
            newArgs[newNonVarargCount] =
                createActualArgument(
                    changeInfo, list, newParms[newNonVarargCount], toInsertDefaultValue, args);
          } else {
            System.arraycopy(
                newVarargInitializers, 0, newArgs, newNonVarargCount, newVarargInitializers.length);
          }
        } else {
          final int newVarargCount = newArgsLength - newNonVarargCount;
          LOG.assertTrue(newVarargCount == 0 || newVarargCount == varargCount);
          for (int i = newNonVarargCount; i < newArgsLength; i++) {
            final int oldIndex = newParms[newNonVarargCount].getOldIndex();
            if (oldIndex >= 0 && oldIndex != nonVarargCount) {
              newArgs[i] =
                  createActualArgument(
                      changeInfo, list, newParms[newNonVarargCount], toInsertDefaultValue, args);
            } else {
              System.arraycopy(args, nonVarargCount, newArgs, newNonVarargCount, newVarargCount);
              break;
            }
          }
        }
        ChangeSignatureUtil.synchronizeList(
            list, Arrays.asList(newArgs), ExpressionList.INSTANCE, changeInfo.toRemoveParm());
      }
    }
  }
  protected void performRefactoring(UsageInfo[] usages) {
    try {
      PsiElementFactory factory =
          JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory();
      PsiType initializerType =
          getInitializerType(myForcedType, myParameterInitializer, myLocalVariable);
      setForcedType(initializerType);

      // Converting myParameterInitializer
      if (myParameterInitializer == null) {
        LOG.assertTrue(myLocalVariable != null);
        myParameterInitializer =
            factory.createExpressionFromText(myLocalVariable.getName(), myLocalVariable);
      } else if (myParameterInitializer instanceof PsiArrayInitializerExpression) {
        final PsiExpression newExprArrayInitializer =
            RefactoringUtil.createNewExpressionFromArrayInitializer(
                (PsiArrayInitializerExpression) myParameterInitializer, initializerType);
        myParameterInitializer =
            (PsiExpression) myParameterInitializer.replace(newExprArrayInitializer);
      }

      myInitializerWrapper = new JavaExpressionWrapper(myParameterInitializer);

      // Changing external occurences (the tricky part)

      IntroduceParameterUtil.processUsages(usages, this);

      if (myGenerateDelegate) {
        generateDelegate(myMethodToReplaceIn);
        if (myMethodToReplaceIn != myMethodToSearchFor) {
          final PsiMethod method = generateDelegate(myMethodToSearchFor);
          if (method.getContainingClass().isInterface()) {
            final PsiCodeBlock block = method.getBody();
            if (block != null) {
              block.delete();
            }
          }
        }
      }

      // Changing signature of initial method
      // (signature of myMethodToReplaceIn will be either changed now or have already been changed)
      LOG.assertTrue(initializerType.isValid());
      final FieldConflictsResolver fieldConflictsResolver =
          new FieldConflictsResolver(myParameterName, myMethodToReplaceIn.getBody());
      IntroduceParameterUtil.changeMethodSignatureAndResolveFieldConflicts(
          new UsageInfo(myMethodToReplaceIn), usages, this);
      if (myMethodToSearchFor != myMethodToReplaceIn) {
        IntroduceParameterUtil.changeMethodSignatureAndResolveFieldConflicts(
            new UsageInfo(myMethodToSearchFor), usages, this);
      }
      ChangeContextUtil.clearContextInfo(myParameterInitializer);

      // Replacing expression occurrences
      for (UsageInfo usage : usages) {
        if (usage instanceof ChangedMethodCallInfo) {
          PsiElement element = usage.getElement();

          processChangedMethodCall(element);
        } else if (usage instanceof InternalUsageInfo) {
          PsiElement element = usage.getElement();
          if (element instanceof PsiExpression) {
            element = RefactoringUtil.outermostParenthesizedExpression((PsiExpression) element);
          }
          if (element != null) {
            if (element.getParent() instanceof PsiExpressionStatement) {
              element.getParent().delete();
            } else {
              PsiExpression newExpr = factory.createExpressionFromText(myParameterName, element);
              IntroduceVariableBase.replace((PsiExpression) element, newExpr, myProject);
            }
          }
        }
      }

      if (myLocalVariable != null && myRemoveLocalVariable) {
        myLocalVariable.normalizeDeclaration();
        myLocalVariable.getParent().delete();
      }
      fieldConflictsResolver.fix();
    } catch (IncorrectOperationException ex) {
      LOG.error(ex);
    }
  }