예제 #1
0
        MapValues(
            IEnumerable <SpecificationProperty> propertyTuples,
            IEnumerable <KeyValuePair <string, IEnumerable <string> > > options,
            Func <IEnumerable <string>, System.Type, bool, Maybe <object> > converter,
            StringComparer comparer)
        {
            var sequencesAndErrors = propertyTuples
                                     .Select(pt =>
                                             options.SingleOrDefault(
                                                 s =>
                                                 s.Key.MatchName(((OptionSpecification)pt.Specification).ShortName, ((OptionSpecification)pt.Specification).LongName, comparer))
                                             .ToMaybe()
                                             .Return(sequence =>
                                                     converter(sequence.Value, pt.Property.PropertyType, pt.Specification.ConversionType.IsScalar())
                                                     .Return(converted =>
                                                             Tuple.Create(
                                                                 pt.WithValue(Maybe.Just(converted)),
                                                                 Maybe.Nothing <Error>()),
                                                             Tuple.Create <SpecificationProperty, Maybe <Error> >(
                                                                 pt,
                                                                 Maybe.Just <Error>(new BadFormatConversionError(NameInfo.FromOptionSpecification((OptionSpecification)pt.Specification))))),
                                                     Tuple.Create(pt, Maybe.Nothing <Error>()))
                                             );

            return(StatePair.Create(
                       sequencesAndErrors.Select(se => se.Item1),
                       sequencesAndErrors.Select(se => se.Item2).OfType <Just <Error> >().Select(se => se.Value)));
        }
예제 #2
0
        public static ParserResult <T> Build <T>(
            Func <T> factory,
            Func <IEnumerable <string>, IEnumerable <OptionSpecification>, StatePair <IEnumerable <Token> > > tokenizer,
            IEnumerable <string> arguments,
            StringComparer nameComparer,
            CultureInfo parsingCulture)
        {
            var instance = factory();

            if (arguments.Any() && nameComparer.Equals("--help", arguments.First()))
            {
                return(ParserResult.Create(
                           ParserResultType.Options,
                           instance,
                           new[] { new HelpRequestedError() }));
            }

            var specProps = instance.GetType().GetSpecifications(pi => SpecificationProperty.Create(
                                                                     Specification.FromProperty(pi), pi, Maybe.Nothing <object>()));

            var optionSpecs = (from pt in specProps select pt.Specification)
                              .ThrowingValidate(SpecificationGuards.Lookup)
                              .OfType <OptionSpecification>();

            var tokenizerResult = tokenizer(arguments, optionSpecs);

            var tokens = tokenizerResult.Value;

            var partitions = TokenPartitioner.Partition(
                tokens,
                name => TypeLookup.GetDescriptorInfo(name, optionSpecs, nameComparer));

            var optionSpecProps = OptionMapper.MapValues(
                (from pt in specProps where pt.Specification.IsOption() select pt),
                partitions.Item1,
                (vals, type, isScalar) => TypeConverter.ChangeType(vals, type, isScalar, parsingCulture),
                nameComparer);

            var valueSpecProps = ValueMapper.MapValues(
                (from pt in specProps where pt.Specification.IsValue() select pt),
                partitions.Item2,
                (vals, type, isScalar) => TypeConverter.ChangeType(vals, type, isScalar, parsingCulture));

            var missingValueErrors = from token in partitions.Item3
                                     select new MissingValueOptionError(
                NameInfo.FromOptionSpecification(optionSpecs.Single(o => token.Text.MatchName(o.ShortName, o.LongName, nameComparer))));

            var specPropsWithValue = optionSpecProps.Value.Concat(valueSpecProps.Value);

            instance = instance
                       .SetProperties(specPropsWithValue,
                                      sp => sp.Value.IsJust(),
                                      sp => sp.Value.FromJust())
                       .SetProperties(specPropsWithValue,
                                      sp => sp.Value.IsNothing() && sp.Specification.DefaultValue.IsJust(),
                                      sp => sp.Specification.DefaultValue.FromJust())
                       .SetProperties(specPropsWithValue,
                                      sp => sp.Value.IsNothing() &&
                                      sp.Specification.ConversionType.ToDescriptor() == DescriptorType.Sequence &&
                                      sp.Specification.DefaultValue.MatchNothing(),
                                      sp => sp.Property.PropertyType.GetGenericArguments().Single().CreateEmptyArray());

            var validationErrors = specPropsWithValue.Validate(SpecificationPropertyRules.Lookup)
                                   .OfType <Just <Error> >().Select(e => e.Value);

            return(ParserResult.Create(
                       ParserResultType.Options,
                       instance,
                       tokenizerResult.Errors
                       .Concat(missingValueErrors)
                       .Concat(optionSpecProps.Errors)
                       .Concat(valueSpecProps.Errors)
                       .Concat(validationErrors)));
        }
예제 #3
0
 private static Func <IEnumerable <SpecificationProperty>, IEnumerable <Maybe <Error> > > EnforceMutuallyExclusiveSet()
 {
     return(specProps =>
     {
         var options = specProps.Where(sp => sp.Specification.IsOption() && sp.Value.IsJust());
         var groups = options.GroupBy(g => ((OptionSpecification)g.Specification).SetName);
         if (groups.Count() > 1)
         {
             return options.Select(s => Maybe.Just <Error>(new MutuallyExclusiveSetError(NameInfo.FromOptionSpecification((OptionSpecification)s.Specification))));
         }
         return Enumerable.Empty <Nothing <Error> >();
     });
 }