public static boolean areTypeArgumentsRedundant(PsiType[] typeArguments,
                                                  PsiExpression context,
                                                  boolean constructorRef,
                                                  @Nullable PsiMethod method,
                                                  PsiTypeParameter[] typeParameters) {
    PsiElement encoded = null;
    try {
      final PsiElement copy;
      final PsiType typeByParent = PsiTypesUtil.getExpectedTypeByParent(context);
      if (typeByParent != null && PsiTypesUtil.isDenotableType(typeByParent, context)) {
        if (isAugmented(context)) {
          return false;
        }
        RecaptureTypeMapper.encode(encoded = context);
        copy = LambdaUtil.copyWithExpectedType(context, typeByParent);
      }
      else {
        final PsiExpressionList argumentList = context instanceof PsiCallExpression ? ((PsiCallExpression)context).getArgumentList() : null;
        final Object marker = new Object();
        PsiTreeUtil.mark(argumentList != null ? argumentList : context, marker);
        final PsiCall call = LambdaUtil.treeWalkUp(context);
        if (call != null) {
          RecaptureTypeMapper.encode(encoded = call);
          final PsiCall callCopy = LambdaUtil.copyTopLevelCall(call);
          copy = callCopy != null ? PsiTreeUtil.releaseMark(callCopy, marker) : null;
        }
        else  {
          final InjectedLanguageManager injectedLanguageManager = InjectedLanguageManager.getInstance(context.getProject());
          if (injectedLanguageManager.getInjectionHost(context) != null) {
            return false;
          }
          final PsiFile containingFile = context.getContainingFile();
          final PsiFile fileCopy = (PsiFile)containingFile.copy();
          copy = PsiTreeUtil.releaseMark(fileCopy, marker);
          if (method != null && method.getContainingFile() == containingFile) {
            final PsiElement startMethodElementInCopy = fileCopy.findElementAt(method.getTextOffset());
            method = PsiTreeUtil.getParentOfType(startMethodElementInCopy, PsiMethod.class);
            if (method == null) {
              //lombok generated builder
              return false;
            }
          }
        }
      }
      final PsiCallExpression exprCopy = PsiTreeUtil.getParentOfType(copy, PsiCallExpression.class, false);
      if (context instanceof PsiMethodReferenceExpression) {
        PsiMethodReferenceExpression methodRefCopy = PsiTreeUtil.getParentOfType(copy, PsiMethodReferenceExpression.class, false);
        if (methodRefCopy != null && !isInferenceEquivalent(typeArguments, typeParameters, method, methodRefCopy)) {
          return false;
        }
      }
      else if (exprCopy != null) {
        final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(exprCopy.getProject());
        if (constructorRef) {
          if (!(exprCopy instanceof PsiNewExpression) ||
              !isInferenceEquivalent(typeArguments, elementFactory, (PsiNewExpression)exprCopy)) {
            return false;
          }
        }
        else {
          LOG.assertTrue(method != null);
          if (!isInferenceEquivalent(typeArguments, elementFactory, exprCopy, method, typeParameters)) {
            return false;
          }
        }
      }

      if (typeByParent != null) {
        return true;
      }

      PsiCallExpression newParentCall = exprCopy != null ? PsiTreeUtil.getParentOfType(exprCopy, PsiCallExpression.class) : null;
      PsiCallExpression oldParentCall = PsiTreeUtil.getParentOfType(context, PsiCallExpression.class);
      if (newParentCall != null && oldParentCall != null) {
        JavaResolveResult newResult = newParentCall.resolveMethodGenerics();
        JavaResolveResult oldResult = oldParentCall.resolveMethodGenerics();
        if (newResult.getElement() == null ||
            !newResult.getElement().isEquivalentTo(oldResult.getElement()) ||
            !new RecaptureTypeMapper().recapture(newResult.getSubstitutor()).equals(oldResult.getSubstitutor())) {
          return false;
        }
      }
    }
    catch (IncorrectOperationException e) {
      LOG.info(e);
      return false;
    }
    finally {
      if (encoded != null) {
        RecaptureTypeMapper.clean(encoded);
      }
    }
    return true;
  }
public static boolean areTypeArgumentsRedundant(PsiType[] typeArguments,
                                                  PsiExpression context,
                                                  boolean constructorRef,
                                                  @Nullable PsiMethod method,
                                                  PsiTypeParameter[] typeParameters)