@Override
  public boolean processUsage(ChangeInfo changeInfo, UsageInfo usage, boolean beforeMethodChange, UsageInfo[] usages) {
    if (!isJavaUsage(usage)) return false;
    JavaChangeInfo javaChangeInfo = JavaChangeInfoConverters.getJavaChangeInfo(changeInfo, usage);
    if (javaChangeInfo == null) {
      return false;
    }

    if (beforeMethodChange) {
      if (usage instanceof final CallerUsageInfo callerUsageInfo) {
        processCallerMethod(javaChangeInfo, callerUsageInfo.getMethod(), null, callerUsageInfo.isToInsertParameter(),
                            callerUsageInfo.isToInsertException());
        return true;
      }
      else if (usage instanceof final OverriderUsageInfo info) {
        final PsiMethod method = info.getOverridingMethod();
        final PsiMethod baseMethod = info.getBaseMethod();
        if (info.isOriginalOverrider()) {
          processPrimaryMethod(javaChangeInfo, method, baseMethod, false);
        }
        else {
          processCallerMethod(javaChangeInfo, method, baseMethod, info.isToInsertArgs(), info.isToCatchExceptions());
        }
        return true;
      }
      else if (usage instanceof final DeconstructionUsageInfo info) {
        final PsiDeconstructionPattern deconstruction = info.getDeconstruction();
        final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(usage.getProject());
        var processor = new DeconstructionProcessor(javaChangeInfo, elementFactory, deconstruction.getDeconstructionList());
        processor.run();
        return true;
      }
      else if (usage instanceof MethodReferenceUsageInfo && MethodReferenceUsageInfo.needToExpand(javaChangeInfo)) {
        final PsiElement element = usage.getElement();
        if (element instanceof PsiMethodReferenceExpression) {
          final PsiExpression expression = LambdaRefactoringUtil.convertToMethodCallInLambdaBody((PsiMethodReferenceExpression)element);
          if (expression instanceof PsiCallExpression) {
            ((MethodReferenceUsageInfo)usage).setCallExpression((PsiCallExpression)expression);
            return true;
          }
        }
      }
      else if (usage instanceof FunctionalInterfaceChangedUsageInfo functionalUsage) {
        final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(usage.getProject());
        final PsiElement element = usage.getElement();
        final PsiMethod interfaceMethod = functionalUsage.getMethod();
        if (element instanceof PsiLambdaExpression lambda) {
          MethodParamsProcessor processor =
            new MethodParamsProcessor(javaChangeInfo, interfaceMethod, elementFactory, PsiSubstitutor.EMPTY, lambda.getParameterList(),
                                      lambda.getBody());
          processor.run();
        }
        else if (element instanceof PsiMethodReferenceExpression methodRef) {
          final PsiLambdaExpression lambdaExpression =
            LambdaRefactoringUtil.convertMethodReferenceToLambda(methodRef, false, true);
          if (lambdaExpression != null) {
            MethodParamsProcessor processor =
              new MethodParamsProcessor(javaChangeInfo, interfaceMethod, elementFactory, PsiSubstitutor.EMPTY, lambdaExpression.getParameterList(),
                                        lambdaExpression.getBody());
            processor.run();
          }
        }
        return true;
      }

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

      if (usage instanceof final DefaultConstructorImplicitUsageInfo defConstructorUsage) {
        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, constructor, defConstructorUsage.getBaseConstructor(), usages);
        return true;
      }
      else if (usage instanceof NoConstructorClassUsageInfo) {
        addDefaultConstructor(javaChangeInfo, ((NoConstructorClassUsageInfo)usage).getPsiClass(), usages);
        return true;
      }
      else if (usage instanceof MethodReferenceUsageInfo && MethodReferenceUsageInfo.needToExpand(javaChangeInfo)) {
        final MethodCallUsageInfo methodCallInfo = ((MethodReferenceUsageInfo)usage).createMethodCallInfo();
        if (methodCallInfo != null) {
          processMethodUsage(methodCallInfo.getElement(), javaChangeInfo, methodCallInfo.isToChangeArguments(),
                             methodCallInfo.isToCatchExceptions(), methodCallInfo.isVarArgCall(), 
                             methodCallInfo.getReferencedMethod(), methodCallInfo.getSubstitutor(), usages);
          return true;
        }
      }
      else if (usage instanceof final MethodCallUsageInfo methodCallInfo) {
        processMethodUsage(methodCallInfo.getElement(), javaChangeInfo, methodCallInfo.isToChangeArguments(),
                           methodCallInfo.isToCatchExceptions(), methodCallInfo.isVarArgCall(), 
                           methodCallInfo.getReferencedMethod(), methodCallInfo.getSubstitutor(), usages);
        return true;
      }
      else if (usage instanceof ChangeSignatureParameterUsageInfo) {
        String newName = ((ChangeSignatureParameterUsageInfo)usage).newParameterName;
        String oldName = ((ChangeSignatureParameterUsageInfo)usage).oldParameterName;
        if (element instanceof PsiReferenceExpression) {
          processParameterUsage((PsiReferenceExpression)element, oldName, newName);
        }
        return true;
      }
      else if (usage instanceof RecordGetterDeclarationUsageInfo) {
        processRecordGetter((PsiMethod)element, ((RecordGetterDeclarationUsageInfo)usage).myNewName,
                            ((RecordGetterDeclarationUsageInfo)usage).myNewType);
      }
      else if (usage instanceof CallReferenceUsageInfo callRefUsage) {
        callRefUsage.getReference().handleChangeSignature(changeInfo);
        return true;
      }
      else if (element instanceof PsiEnumConstant enumConstant) {
        fixActualArgumentsList(enumConstant.getArgumentList(), javaChangeInfo, true, PsiSubstitutor.EMPTY, false);
        return true;
      }
      else if (!(usage instanceof OverriderUsageInfo) && !(usage instanceof UnresolvableCollisionUsageInfo)) {
        PsiReference reference = usage instanceof MoveRenameUsageInfo ? usage.getReference() : element.getReference();
        if (element instanceof PsiImportStaticReferenceElement) {
          ((PsiImportStaticReferenceElement)element).handleElementRename(javaChangeInfo.getNewName());
        } else if (reference != null) {
          reference.bindToElement(javaChangeInfo.getMethod());
        }
      }
    }
    return false;
  }
@Override
  public boolean processUsage(ChangeInfo changeInfo, UsageInfo usage, boolean beforeMethodChange, UsageInfo[] usages)