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))); }
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))); }
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> >(); }); }