private static void processMethodUsage(
      PsiElement ref,
      JavaChangeInfo changeInfo,
      boolean toChangeArguments,
      boolean toCatchExceptions,
      PsiMethod callee,
      PsiSubstitutor subsitutor,
      final UsageInfo[] usages)
      throws IncorrectOperationException {
    if (changeInfo.isNameChanged()) {
      if (ref instanceof PsiJavaCodeReferenceElement) {
        PsiElement last = ((PsiJavaCodeReferenceElement) ref).getReferenceNameElement();
        if (last instanceof PsiIdentifier && last.getText().equals(changeInfo.getOldName())) {
          last.replace(changeInfo.getNewNameIdentifier());
        }
      }
    }

    final PsiMethod caller = RefactoringUtil.getEnclosingMethod(ref);
    if (toChangeArguments) {
      final PsiExpressionList list = RefactoringUtil.getArgumentListByMethodReference(ref);
      LOG.assertTrue(list != null);
      boolean toInsertDefaultValue = needDefaultValue(changeInfo, caller);
      if (toInsertDefaultValue && ref instanceof PsiReferenceExpression) {
        final PsiExpression qualifierExpression =
            ((PsiReferenceExpression) ref).getQualifierExpression();
        if (qualifierExpression instanceof PsiSuperExpression
            && callerSignatureIsAboutToChangeToo(caller, usages)) {
          toInsertDefaultValue = false;
        }
      }

      fixActualArgumentsList(list, changeInfo, toInsertDefaultValue, subsitutor);
    }

    if (toCatchExceptions) {
      if (!(ref instanceof PsiReferenceExpression
          && ((PsiReferenceExpression) ref).getQualifierExpression()
              instanceof PsiSuperExpression)) {
        if (needToCatchExceptions(changeInfo, caller)) {
          PsiClassType[] newExceptions =
              callee != null
                  ? getCalleeChangedExceptionInfo(callee)
                  : getPrimaryChangedExceptionInfo(changeInfo);
          fixExceptions(ref, newExceptions);
        }
      }
    }
  }
  protected boolean preprocessUsages(Ref<UsageInfo[]> refUsages) {
    final UsageInfo[] usages = refUsages.get();
    MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();
    final Set<PsiMember> members = new HashSet<PsiMember>();
    members.add(myMethod);
    if (myTargetVariable instanceof PsiField) members.add((PsiMember) myTargetVariable);
    if (!myTargetClass.isInterface()) {
      RefactoringConflictsUtil.analyzeAccessibilityConflicts(
          members, myTargetClass, conflicts, myNewVisibility);
    } else {
      for (final UsageInfo usage : usages) {
        if (usage instanceof InheritorUsageInfo) {
          RefactoringConflictsUtil.analyzeAccessibilityConflicts(
              members, ((InheritorUsageInfo) usage).getInheritor(), conflicts, myNewVisibility);
        }
      }
    }

    if (myTargetVariable instanceof PsiParameter) {
      PsiParameter parameter = (PsiParameter) myTargetVariable;
      for (final UsageInfo usageInfo : usages) {
        if (usageInfo instanceof MethodCallUsageInfo) {
          final PsiElement methodCall = ((MethodCallUsageInfo) usageInfo).getMethodCallExpression();
          if (methodCall instanceof PsiMethodCallExpression) {
            final PsiExpression[] expressions =
                ((PsiMethodCallExpression) methodCall).getArgumentList().getExpressions();
            final int index = myMethod.getParameterList().getParameterIndex(parameter);
            if (index < expressions.length) {
              PsiExpression instanceValue = expressions[index];
              instanceValue = RefactoringUtil.unparenthesizeExpression(instanceValue);
              if (instanceValue instanceof PsiLiteralExpression
                  && ((PsiLiteralExpression) instanceValue).getValue() == null) {
                String message =
                    RefactoringBundle.message(
                        "0.contains.call.with.null.argument.for.parameter.1",
                        RefactoringUIUtil.getDescription(
                            ConflictsUtil.getContainer(methodCall), true),
                        CommonRefactoringUtil.htmlEmphasize(parameter.getName()));
                conflicts.putValue(instanceValue, message);
              }
            }
          } else if (methodCall instanceof PsiMethodReferenceExpression) {
            conflicts.putValue(methodCall, "Method reference would be broken after move");
          }
        }
      }
    }

    try {
      ConflictsUtil.checkMethodConflicts(myTargetClass, myMethod, getPatternMethod(), conflicts);
    } catch (IncorrectOperationException e) {
    }

    return showConflicts(conflicts, usages);
  }
 @Override
 public boolean setupDefaultValues(
     ChangeInfo changeInfo, Ref<UsageInfo[]> refUsages, Project project) {
   if (!(changeInfo instanceof JavaChangeInfo)) return true;
   for (UsageInfo usageInfo : refUsages.get()) {
     if (usageInfo instanceof MethodCallUsageInfo) {
       MethodCallUsageInfo methodCallUsageInfo = (MethodCallUsageInfo) usageInfo;
       if (methodCallUsageInfo.isToChangeArguments()) {
         final PsiElement element = methodCallUsageInfo.getElement();
         if (element == null) continue;
         final PsiMethod caller = RefactoringUtil.getEnclosingMethod(element);
         final boolean needDefaultValue = needDefaultValue(changeInfo, caller);
         if (needDefaultValue
             && (caller == null
                 || !MethodSignatureUtil.isSuperMethod(
                     methodCallUsageInfo.getReferencedMethod(), caller))) {
           final ParameterInfo[] parameters = changeInfo.getNewParameters();
           for (ParameterInfo parameter : parameters) {
             final String defaultValue = parameter.getDefaultValue();
             if (defaultValue == null && parameter.getOldIndex() == -1) {
               ((ParameterInfoImpl) parameter).setDefaultValue("");
               if (!ApplicationManager.getApplication().isUnitTestMode()) {
                 final PsiType type =
                     ((ParameterInfoImpl) parameter)
                         .getTypeWrapper()
                         .getType(element, element.getManager());
                 final DefaultValueChooser chooser =
                     new DefaultValueChooser(
                         project, parameter.getName(), PsiTypesUtil.getDefaultValueOfType(type));
                 chooser.show();
                 if (chooser.isOK()) {
                   if (chooser.feelLucky()) {
                     parameter.setUseAnySingleVariable(true);
                   } else {
                     ((ParameterInfoImpl) parameter).setDefaultValue(chooser.getDefaultValue());
                   }
                 } else {
                   return false;
                 }
               }
             }
           }
         }
       }
     }
   }
   return true;
 }
 private static void fixJavadocsForChangedMethod(
     PsiMethod method, JavaChangeInfo changeInfo, int newParamsLength)
     throws IncorrectOperationException {
   final PsiParameter[] parameters = method.getParameterList().getParameters();
   final JavaParameterInfo[] newParms = changeInfo.getNewParameters();
   LOG.assertTrue(parameters.length <= newParamsLength);
   final Set<PsiParameter> newParameters = new HashSet<PsiParameter>();
   final String[] oldParameterNames = changeInfo.getOldParameterNames();
   for (int i = 0; i < newParamsLength; i++) {
     JavaParameterInfo newParm = newParms[i];
     if (newParm.getOldIndex() < 0
         || !newParm.getName().equals(oldParameterNames[newParm.getOldIndex()])) {
       newParameters.add(parameters[i]);
     }
   }
   RefactoringUtil.fixJavadocsForParams(method, newParameters);
 }
 static PsiType getInitializerType(
     PsiType forcedType, PsiExpression parameterInitializer, PsiLocalVariable localVariable) {
   final PsiType initializerType;
   if (forcedType == null) {
     if (parameterInitializer == null) {
       if (localVariable != null) {
         initializerType = localVariable.getType();
       } else {
         LOG.assertTrue(false);
         initializerType = null;
       }
     } else {
       if (localVariable == null) {
         initializerType =
             RefactoringUtil.getTypeByExpressionWithExpectedType(parameterInitializer);
       } else {
         initializerType = localVariable.getType();
       }
     }
   } else {
     initializerType = forcedType;
   }
   return initializerType;
 }
  private static void processPrimaryMethod(
      JavaChangeInfo changeInfo, PsiMethod method, PsiMethod baseMethod, boolean isOriginal)
      throws IncorrectOperationException {
    PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory();

    if (changeInfo.isVisibilityChanged()) {
      PsiModifierList modifierList = method.getModifierList();
      final String highestVisibility =
          isOriginal
              ? changeInfo.getNewVisibility()
              : VisibilityUtil.getHighestVisibility(
                  changeInfo.getNewVisibility(),
                  VisibilityUtil.getVisibilityModifier(modifierList));
      VisibilityUtil.setVisibility(modifierList, highestVisibility);
    }

    if (changeInfo.isNameChanged()) {
      String newName =
          baseMethod == null
              ? changeInfo.getNewName()
              : RefactoringUtil.suggestNewOverriderName(
                  method.getName(), baseMethod.getName(), changeInfo.getNewName());

      if (newName != null && !newName.equals(method.getName())) {
        final PsiIdentifier nameId = method.getNameIdentifier();
        assert nameId != null;
        nameId.replace(
            JavaPsiFacade.getInstance(method.getProject())
                .getElementFactory()
                .createIdentifier(newName));
      }
    }

    final PsiSubstitutor substitutor =
        baseMethod == null
            ? PsiSubstitutor.EMPTY
            : ChangeSignatureProcessor.calculateSubstitutor(method, baseMethod);

    if (changeInfo.isReturnTypeChanged()) {
      PsiType newTypeElement =
          changeInfo
              .getNewReturnType()
              .getType(changeInfo.getMethod().getParameterList(), method.getManager());
      final PsiType returnType = substitutor.substitute(newTypeElement);
      // don't modify return type for non-Java overriders (EJB)
      if (method.getName().equals(changeInfo.getNewName())) {
        final PsiTypeElement typeElement = method.getReturnTypeElement();
        if (typeElement != null) {
          typeElement.replace(factory.createTypeElement(returnType));
        }
      }
    }

    PsiParameterList list = method.getParameterList();
    PsiParameter[] parameters = list.getParameters();

    final JavaParameterInfo[] parameterInfos = changeInfo.getNewParameters();
    final int delta =
        baseMethod != null
            ? baseMethod.getParameterList().getParametersCount()
                - method.getParameterList().getParametersCount()
            : 0;
    PsiParameter[] newParms = new PsiParameter[Math.max(parameterInfos.length - delta, 0)];
    final String[] oldParameterNames = changeInfo.getOldParameterNames();
    final String[] oldParameterTypes = changeInfo.getOldParameterTypes();
    for (int i = 0; i < newParms.length; i++) {
      JavaParameterInfo info = parameterInfos[i];
      int index = info.getOldIndex();
      if (index >= 0) {
        PsiParameter parameter = parameters[index];
        newParms[i] = parameter;

        String oldName = oldParameterNames[index];
        if (!oldName.equals(info.getName()) && oldName.equals(parameter.getName())) {
          PsiIdentifier newIdentifier = factory.createIdentifier(info.getName());
          parameter.getNameIdentifier().replace(newIdentifier);
        }

        String oldType = oldParameterTypes[index];
        if (!oldType.equals(info.getTypeText())) {
          parameter.normalizeDeclaration();
          PsiType newType =
              substitutor.substitute(
                  info.createType(changeInfo.getMethod().getParameterList(), method.getManager()));

          parameter.getTypeElement().replace(factory.createTypeElement(newType));
        }
      } else {
        newParms[i] = createNewParameter(changeInfo, info, substitutor);
      }
    }

    resolveParameterVsFieldsConflicts(newParms, method, list, changeInfo.toRemoveParm());
    fixJavadocsForChangedMethod(method, changeInfo, newParms.length);
    if (changeInfo.isExceptionSetOrOrderChanged()) {
      final PsiClassType[] newExceptions = getPrimaryChangedExceptionInfo(changeInfo);
      fixPrimaryThrowsLists(method, newExceptions);
    }
  }
  @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;
  }
  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);
    }
  }
  private PsiMethod createMethodToAdd() {
    ChangeContextUtil.encodeContextInfo(myMethod, true);
    try {
      final PsiManager manager = myMethod.getManager();
      final PsiElementFactory factory =
          JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();

      // correct internal references
      final PsiCodeBlock body = myMethod.getBody();
      if (body != null) {
        final Map<PsiElement, PsiElement> replaceMap = new HashMap<PsiElement, PsiElement>();
        body.accept(
            new JavaRecursiveElementVisitor() {
              @Override
              public void visitThisExpression(PsiThisExpression expression) {
                final PsiClass classReferencedByThis =
                    MoveInstanceMembersUtil.getClassReferencedByThis(expression);
                if (classReferencedByThis != null
                    && !PsiTreeUtil.isAncestor(myMethod, classReferencedByThis, false)) {
                  final PsiElementFactory factory =
                      JavaPsiFacade.getInstance(myProject).getElementFactory();
                  String paramName = getParameterNameToCreate(classReferencedByThis);
                  try {
                    final PsiExpression refExpression =
                        factory.createExpressionFromText(paramName, null);
                    replaceMap.put(expression, refExpression);
                  } catch (IncorrectOperationException e) {
                    LOG.error(e);
                  }
                }
              }

              @Override
              public void visitReferenceExpression(PsiReferenceExpression expression) {
                try {
                  final PsiExpression qualifier = expression.getQualifierExpression();
                  final PsiElement resolved = expression.resolve();
                  if (qualifier instanceof PsiReferenceExpression
                      && ((PsiReferenceExpression) qualifier).isReferenceTo(myTargetVariable)) {
                    if (resolved instanceof PsiField) {
                      for (PsiParameter parameter : myMethod.getParameterList().getParameters()) {
                        if (Comparing.strEqual(
                            parameter.getName(), ((PsiField) resolved).getName())) {
                          qualifier.replace(factory.createExpressionFromText("this", null));
                          return;
                        }
                      }
                    }
                    // Target is a field, replace target.m -> m
                    qualifier.delete();
                    return;
                  }
                  if (myTargetVariable.equals(resolved)) {
                    PsiThisExpression thisExpression =
                        RefactoringChangeUtil.createThisExpression(
                            manager,
                            PsiTreeUtil.isAncestor(
                                    myMethod,
                                    PsiTreeUtil.getParentOfType(expression, PsiClass.class),
                                    true)
                                ? myTargetClass
                                : null);
                    replaceMap.put(expression, thisExpression);
                    return;
                  } else if (myMethod.equals(resolved)) {
                  } else {
                    PsiClass classReferencedByThis =
                        MoveInstanceMembersUtil.getClassReferencedByThis(expression);
                    if (classReferencedByThis != null) {
                      final String paramName = getParameterNameToCreate(classReferencedByThis);
                      if (paramName != null) {
                        PsiReferenceExpression newQualifier =
                            (PsiReferenceExpression)
                                factory.createExpressionFromText(paramName, null);
                        expression.setQualifierExpression(newQualifier);
                        return;
                      }
                    }
                  }
                  super.visitReferenceExpression(expression);
                } catch (IncorrectOperationException e) {
                  LOG.error(e);
                }
              }

              @Override
              public void visitNewExpression(PsiNewExpression expression) {
                try {
                  final PsiExpression qualifier = expression.getQualifier();
                  if (qualifier instanceof PsiReferenceExpression
                      && ((PsiReferenceExpression) qualifier).isReferenceTo(myTargetVariable)) {
                    // Target is a field, replace target.new A() -> new A()
                    qualifier.delete();
                  } else {
                    final PsiClass classReferencedByThis =
                        MoveInstanceMembersUtil.getClassReferencedByThis(expression);
                    if (classReferencedByThis != null) {
                      if (qualifier != null) qualifier.delete();
                      final String paramName = getParameterNameToCreate(classReferencedByThis);
                      final PsiExpression newExpression =
                          factory.createExpressionFromText(
                              paramName + "." + expression.getText(), null);
                      replaceMap.put(expression, newExpression);
                    }
                  }
                  super.visitNewExpression(expression);
                } catch (IncorrectOperationException e) {
                  LOG.error(e);
                }
              }

              @Override
              public void visitMethodCallExpression(PsiMethodCallExpression expression) {
                correctMethodCall(expression, true);
                super.visitMethodCallExpression(expression);
              }
            });
        for (PsiElement element : replaceMap.keySet()) {
          final PsiElement replacement = replaceMap.get(element);
          element.replace(replacement);
        }
      }

      final PsiMethod methodCopy = getPatternMethod();

      final List<PsiParameter> newParameters =
          Arrays.asList(methodCopy.getParameterList().getParameters());
      RefactoringUtil.fixJavadocsForParams(methodCopy, new HashSet<PsiParameter>(newParameters));
      return methodCopy;
    } catch (IncorrectOperationException e) {
      LOG.error(e);
      return myMethod;
    }
  }