private static void inferMethodCallArgumentTypes(final @NotNull PsiExpression argument,
                                                     final boolean forCompletion,
                                                     final PsiExpression @NotNull [] args,
                                                     final int index,
                                                     final @NotNull PsiMethod method,
                                                     final @NotNull PsiSubstitutor substitutor,
                                                     final @NotNull Set<? super ExpectedTypeInfo> array) {
      LOG.assertTrue(substitutor.isValid());
      PsiParameter[] parameters = method.getParameterList().getParameters();
      if (!forCompletion && parameters.length != args.length && !method.isVarArgs()) return;
      if (parameters.length <= index && !method.isVarArgs()) return;

      for (int j = 0; j < index; j++) {
        PsiType paramType = getParameterType(parameters[Math.min(parameters.length - 1, j)],
                                             substitutor);
        PsiType argType = args[j].getType();
        if (argType != null && !paramType.isAssignableFrom(argType)) return;
      }
      PsiParameter parameter = parameters[Math.min(parameters.length - 1, index)];
      PsiType parameterType = getParameterType(parameter, substitutor);

      TailType tailType = getMethodArgumentTailType(argument, index, method, substitutor, parameters);
      PsiType defaultType = getDefaultType(method, substitutor, parameterType, argument, args, index);

      NullableComputable<String> propertyName = getPropertyName(parameter);
      ExpectedTypeInfoImpl info = createInfoImpl(parameterType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, defaultType, tailType, method,
                                                 propertyName);
      array.add(info);

      if (index == parameters.length - 1 && parameter.isVarArgs()) {
        //Then we may still want to call with array argument
        final PsiArrayType arrayType = parameterType.createArrayType();
        ExpectedTypeInfoImpl info1 = createInfoImpl(arrayType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, arrayType, tailType, method, propertyName);
        array.add(info1);
      }
    }
private static void inferMethodCallArgumentTypes(final @NotNull PsiExpression argument,
                                                     final boolean forCompletion,
                                                     final PsiExpression @NotNull [] args,
                                                     final int index,
                                                     final @NotNull PsiMethod method,
                                                     final @NotNull PsiSubstitutor substitutor,
                                                     final @NotNull Set<? super ExpectedTypeInfo> array)