public Task <IArgumentParserResult> ParseAsync(CommandContext context, ICommand command, string rawArgs)
        {
            if (Fails && (string.IsNullOrWhiteSpace(CommandNameToFail) || CommandNameToFail.Equals(command.Name)))
            {
                var mockResult = new Mock <IArgumentParserResult>();

                mockResult.SetupGet(a => a.Success).Returns(false);

                return(Task.FromResult(mockResult.Object as IArgumentParserResult));
            }

            var args = new Dictionary <IParameter, object>();

            foreach (var parameter in command.Parameters)
            {
                args.Add(parameter, new object());
            }

            var result = ArgumentParseSuccessResult.FromArgs(args);

            return(Task.FromResult(result as IArgumentParserResult));
        }
        public async Task <IArgumentParserResult> ParseAsync(CommandContext context, ICommand command, string remainingInput)
        {
            var config = context.CommandServices.GetRequiredService <IOptions <MariCommandsOptions> >().Value;

            var rawArgs = string.IsNullOrWhiteSpace(remainingInput)
                ? new string[0]
                : remainingInput.Split(config.Separator);

            var willFaultParams = rawArgs.Length < command.Parameters.Count;

            var args = new Dictionary <IParameter, object>();

            for (var i = 0; i < rawArgs.Length; i++)
            {
                var arg   = rawArgs[i];
                var param = command.Parameters.ElementAtOrDefault(i);

                if (param.HasNoContent())
                {
                    break;
                }

                var typeParser = GetTypeParser(context, param);

                if (typeParser.HasNoContent())
                {
                    return(MissingTypeParserResult.FromParam(param));
                }

                var isLastParam = IsLastParam(i, command.Parameters);

                if (isLastParam && param.IsParams)
                {
                    var multipleArgs = rawArgs.Skip(i).ToList();

                    var multipleValues = new List <object>();

                    foreach (var multipleArg in multipleArgs)
                    {
                        var result = await typeParser.ParseAsync(arg, param, context);

                        if (!result.Success)
                        {
                            return(ArgumentTypeParserFailResult.FromTypeParserResult(result));
                        }

                        multipleValues.Add(result.Value);
                    }

                    args.Add(param, multipleValues);
                }
                else
                {
                    if (isLastParam && param.IsRemainder)
                    {
                        arg = string.Join(config.Separator, rawArgs.Skip(i).ToList());
                    }

                    var result = await typeParser.ParseAsync(arg, param, context);

                    if (!result.Success)
                    {
                        return(ArgumentTypeParserFailResult.FromTypeParserResult(result));
                    }

                    args.Add(param, result.Value);
                }
            }

            if (willFaultParams)
            {
                var missingParams = GetMissingParams(rawArgs.Length, command.Parameters);

                foreach (var param in missingParams)
                {
                    if (param.IsOptional)
                    {
                        args.Add(param, param.DefaultValue);
                    }
                    else if (ParsingUtils.IsNullable(param))
                    {
                        var typeParser = GetTypeParser(context, param);

                        if (typeParser.HasNoContent())
                        {
                            return(MissingTypeParserResult.FromParam(param));
                        }

                        var result = await typeParser.ParseAsync(null, param, context);

                        if (!result.Success)
                        {
                            return(ArgumentTypeParserFailResult.FromTypeParserResult(result));
                        }

                        args.Add(param, result.Value);
                    }
                    else if (IsNullableClass(param, config))
                    {
                        args.Add(param, null);
                    }
                    else
                    {
                        return(BadArgCountParseResult.FromCommand(command));
                    }
                }
            }

            return(ArgumentParseSuccessResult.FromArgs(args));
        }