@Override
  public @Nullable UsageInfo createUsageInfo(@NotNull ChangeInfo changeInfo,
                                             @NotNull PsiReference reference,
                                             @NotNull PsiElement m,
                                             boolean isToModifyArgs,
                                             boolean isToThrowExceptions) {
    JavaChangeInfo javaChangeInfo = JavaChangeInfoConverters.getJavaChangeInfo(changeInfo, new UsageInfo(reference));
    if (javaChangeInfo == null) return null;

    PsiMethod method = javaChangeInfo.getMethod();
    if (m instanceof PsiMethod) {
      //in case of propagation, completely different method
      //todo if it's foreign language override, keep base method and hope it's fine
      method = (PsiMethod)m;
    }

    PsiElement element = reference.getElement();

    boolean isToCatchExceptions = isToThrowExceptions &&
                                  needToCatchExceptions(javaChangeInfo, RefactoringUtil.getEnclosingMethod(element));
    if (!isToCatchExceptions) {
      if (RefactoringUtil.isMethodUsage(element)) {
        PsiExpressionList list = RefactoringUtil.getArgumentListByMethodReference(element);
        if (list == null || !method.isVarArgs() && list.getExpressionCount() != method.getParameterList().getParametersCount()) return null;
        if (method.isVarArgs() &&
            reference instanceof PsiReferenceExpression &&
            !((PsiReferenceExpression)reference).advancedResolve(true).isValidResult()) {
          return null;
        }
      }
    }
    if (RefactoringUtil.isMethodUsage(element)) {
      return new MethodCallUsageInfo(element, isToModifyArgs, isToCatchExceptions);
    }
    else if (element instanceof PsiDocTagValue) {
      return new UsageInfo(element);
    }
    else if (element instanceof PsiMethod && ((PsiMethod)element).isConstructor()) {
      return new DefaultConstructorImplicitUsageInfo((PsiMethod)element, ((PsiMethod)element).getContainingClass(), method);
    }
    else if (element instanceof PsiClass psiClass) {
      LOG.assertTrue(method.isConstructor());
      if (javaChangeInfo instanceof JavaChangeInfoImpl) {
        UsageInfo info = shouldPropagateToNonPhysicalMethod(method, psiClass, ((JavaChangeInfoImpl)javaChangeInfo).propagateParametersMethods);
        if (info != null) {
          return info;
        }
        info = shouldPropagateToNonPhysicalMethod(method, psiClass, ((JavaChangeInfoImpl)javaChangeInfo).propagateExceptionsMethods);
        if (info != null) {
          return info;
        }
      }
      return new NoConstructorClassUsageInfo(psiClass);
    }
    else if (reference instanceof PsiCallReference) {
      return new CallReferenceUsageInfo((PsiCallReference)reference);
    }
    else if (element instanceof PsiMethodReferenceExpression && MethodReferenceUsageInfo.needToExpand(javaChangeInfo)) {
      return new MethodReferenceUsageInfo(element, isToModifyArgs, isToCatchExceptions);
    }
    else if (method.isConstructor() && element.getParent() instanceof PsiTypeElement) {
      return null;
    }
    else {
      return new MoveRenameUsageInfo(element, reference, method);
    }
  }
@Override
  public @Nullable UsageInfo createUsageInfo(@NotNull ChangeInfo changeInfo,
                                             @NotNull PsiReference reference,
                                             @NotNull PsiElement m,
                                             boolean isToModifyArgs,
                                             boolean isToThrowExceptions)