async Task <ArgsParseResult <object> > IArgumentParser.Parse(IImmutableList <string> args, Type[] genericTypes)
        {
            ArgsParseResult <T> parseResult = await Parse(args, genericTypes);

            return(parseResult.SuccessResult != null
                ? ArgsParseResult <object> .Success(parseResult.Failures,
                                                    parseResult.SuccessResult.Value.Result !, parseResult.SuccessResult.Value.RemainingArgs)
                : ArgsParseResult <object> .Failure(parseResult.Failures));
        }
Пример #2
0
        /// <summary>
        /// For a list of strings, tries to parse those strings into instance of the supplied types.
        /// </summary>
        /// <param name="args">The input to be parsed, supplied as a list of string arguments</param>
        /// <param name="types">The types of which instances will be attempted to be created from the input.</param>
        /// <param name="errorOnRemainingArgs">Whether it is an error if the arguments weren't fully consumed.</param>
        /// <returns>A parsing result object. On success that will contain a list of objects with the same length
        /// and same types as supplied in <paramref name="types"/></returns>
        /// <exception cref="MissingParserException">If there was no parser found for one of the supplied types.
        /// You must register a parser using <see cref="AddArgumentParser{T}"/> for each type.</exception>
        /// <exception cref="InvalidOperationException">If the requested types cannot be parsed,
        /// because their types or respective parsers are not implemented correctly.</exception>
        public async Task <ArgsParseResult <List <object> > > ParseRaw(
            IImmutableList <string> args,
            IEnumerable <Type> types,
            bool errorOnRemainingArgs = false)
        {
            IImmutableList <string> allRemainingArgs = args;
            var  results  = new List <object>();
            bool success  = true;
            var  failures = new List <Failure>();

            foreach (var type in types)
            {
                Type?queryType = type.IsGenericType ? type.BaseType : type;
                if (queryType == null || queryType.IsGenericType)
                {
                    throw new InvalidOperationException($"generic type {type} need a non-generic base type");
                }
                if (!_parsers.TryGetValue(queryType, out IArgumentParser? parser))
                {
                    throw new MissingParserException(typeWithoutParser: type);
                }
                Debug.Assert(parser != null, "try-get succeeded and the dictionary does not contain null values");
                Type[] genericTypes = type.IsGenericType ? type.GenericTypeArguments : Array.Empty <Type>();
                ArgsParseResult <object> parseResult;
                try
                {
                    parseResult = await parser.Parse(allRemainingArgs, genericTypes);
                }
                catch (ArgumentOutOfRangeException)
                {
                    failures.Add(new Failure(ErrorRelevanceConfidence.Unlikely, "too few arguments"));
                    success = false;
                    break;
                }
                failures.AddRange(parseResult.Failures);
                if (parseResult.SuccessResult != null)
                {
                    Success <object> successResult = parseResult.SuccessResult.Value;
                    results.Add(successResult.Result);
                    allRemainingArgs = successResult.RemainingArgs;
                }
                else
                {
                    success = false;
                    break;
                }
            }
            if (success && errorOnRemainingArgs && allRemainingArgs.Any())
            {
                success = false;
                failures.Add(new Failure(ErrorRelevanceConfidence.Unlikely, "too many arguments"));
            }
            return(success
                ? ArgsParseResult <List <object> > .Success(failures.ToImmutableList(), results, allRemainingArgs)
                : ArgsParseResult <List <object> > .Failure(failures.ToImmutableList()));
        }
Пример #3
0
        /// <summary>
        /// Try to parse arguments into <typeparamref name="T1"/>
        /// and get the respective <see cref="ArgsParseResult{T}"/>.
        /// This is a type-safe wrapper around <see cref="ArgsParser.ParseRaw"/>.
        /// </summary>
        /// <param name="argsParser">args parser used for parsing</param>
        /// <param name="args">List of string arguments to parse from.</param>
        /// <typeparam name="T1">Type to attempt to create an instance of.</typeparam>
        /// <returns>The respective parse result,
        /// containing an instance of <c>T1</c> on success.</returns>
        public static async Task <ArgsParseResult <T1> > TryParse <T1>(
            this ArgsParser argsParser, IImmutableList <string> args)
        {
            IEnumerable <Type> types = new[] { typeof(T1) };
            ArgsParseResult <List <object> > parseResult = await argsParser.ParseRaw(args, types, errorOnRemainingArgs : true);

            if (parseResult.SuccessResult == null)
            {
                return(ArgsParseResult <T1> .Failure(parseResult.Failures));
            }
            Success <List <object> > success = parseResult.SuccessResult.Value;

            return(ArgsParseResult <T1> .Success(parseResult.Failures,
                                                 (T1)success.Result[0],
                                                 success.RemainingArgs));
        }