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 void removeParametersFromCall(final PsiExpressionList argList) {
   final PsiExpression[] exprs = argList.getExpressions();
   myParametersToRemove.forEachDescending(
       new TIntProcedure() {
         public boolean execute(final int paramNum) {
           try {
             exprs[paramNum].delete();
           } catch (IncorrectOperationException e) {
             LOG.error(e);
           }
           return true;
         }
       });
 }
 @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());
      }
    }
  }
 public List<PsiExpression> getChildren(PsiExpressionList psiExpressionList) {
   return Arrays.asList(psiExpressionList.getExpressions());
 }