Ejemplo n.º 1
0
        private static ArgumentDefinition CreateArgumentDescriptor(
            IMutableMemberInfo member,
            ArgumentBaseAttribute attribute,
            object defaultValues,
            ArgumentSetDefinition argSet,
            object fixedDestination,
            ArgumentDefinition containingArgument,
            ServiceConfigurer serviceConfigurer)
        {
            if (!member.IsReadable || !member.IsWritable)
            {
                var declaringType = member.MemberInfo.DeclaringType;

                throw new InvalidArgumentSetException(member, string.Format(
                                                          CultureInfo.CurrentCulture,
                                                          Strings.MemberNotSupported,
                                                          member.MemberInfo.Name,
                                                          declaringType?.Name));
            }

            var defaultFieldValue = (defaultValues != null) ? member.GetValue(defaultValues) : null;

            return(new ArgumentDefinition(member,
                                          attribute,
                                          argSet,
                                          defaultValue: defaultFieldValue,
                                          fixedDestination: fixedDestination,
                                          containingArgument: containingArgument,
                                          serviceConfigurer: serviceConfigurer));
        }
Ejemplo n.º 2
0
        private static ArgumentDefinition CreateArgumentDescriptor(
            IMutableMemberInfo member,
            ArgumentBaseAttribute attribute,
            object defaultValues,
            ArgumentSetAttribute setAttribute,
            CommandLineParserOptions options,
            object fixedDestination)
        {
            if (!member.IsReadable || !member.IsWritable)
            {
                var declaringType = member.MemberInfo.DeclaringType;

                throw new InvalidArgumentSetException(member, string.Format(
                                                          CultureInfo.CurrentCulture,
                                                          Strings.MemberNotSupported,
                                                          member.MemberInfo.Name,
                                                          declaringType?.Name));
            }

            var defaultFieldValue = (defaultValues != null) ? member.GetValue(defaultValues) : null;

            return(new ArgumentDefinition(member,
                                          attribute,
                                          setAttribute,
                                          options,
                                          defaultFieldValue,
                                          fixedDestination: fixedDestination));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Primary constructor.
        /// </summary>
        /// <param name="member">Field to describe.</param>
        /// <param name="attribute">Argument attribute on the field.</param>
        /// <param name="setAttribute">Attribute on the containing argument set.</param>
        /// <param name="options">Provides parser options.</param>
        /// <param name="defaultFieldValue">Default value for the field.</param>
        /// <param name="parentMember">Parent member under which this field sits.</param>
        /// <param name="fixedDestination">Optionally provides fixed parse destination object.</param>
        public ArgumentDefinition(IMutableMemberInfo member,
                                  ArgumentBaseAttribute attribute,
                                  ArgumentSetAttribute setAttribute,
                                  CommandLineParserOptions options,
                                  object defaultFieldValue        = null,
                                  IMutableMemberInfo parentMember = null,
                                  object fixedDestination         = null)
        {
            Debug.Assert(attribute != null);
            Debug.Assert(member != null);

            Member                = member;
            ParentMember          = parentMember;
            Attribute             = attribute;
            _setAttribute         = setAttribute;
            FixedDestination      = fixedDestination;
            _isPositional         = attribute is PositionalArgumentAttribute;
            _reporter             = options?.Reporter ?? (s => { });
            ArgumentType          = Attribute.GetArgumentType(member.MemberType);
            _collectionArgType    = AsCollectionType(ArgumentType);
            HasDefaultValue       = attribute.ExplicitDefaultValue || attribute.DynamicDefaultValue;
            _validationAttributes = GetValidationAttributes(ArgumentType, Member);
            _argumentParseContext = CreateParseContext(attribute, _setAttribute, options);

            LongName          = GetLongName(attribute, setAttribute, member.MemberInfo);
            ExplicitShortName = HasExplicitShortName(attribute);
            ShortName         = GetShortName(attribute, setAttribute, member.MemberInfo);
            DefaultValue      = GetDefaultValue(attribute, member, defaultFieldValue);

            var nullableBase = Nullable.GetUnderlyingType(member.MemberType);

            if (_collectionArgType != null)
            {
                _collectionValues = new ArrayList();
                _valueType        = _collectionArgType.ElementType;
            }
            else if (nullableBase != null)
            {
                // For nullable arguments, we use the wrapped type (T in
                // Nullable<T>) as the value type. Parsing an enum or int is the
                // same as parsing an enum? or int?, for example, since null can
                // only arise if the value was not provided at all.
                _valueType = Attribute.GetArgumentType(nullableBase);
            }
            else
            {
                _valueType = ArgumentType;
            }

            Debug.Assert(_valueType != null);

            if (Unique && !IsCollection)
            {
                throw new InvalidArgumentSetException(member, Strings.UniqueUsedOnNonCollectionArgument);
            }

            Debug.Assert(!string.IsNullOrEmpty(LongName));
        }
Ejemplo n.º 4
0
 public ArgumentDefinition(MemberInfo member,
                           ArgumentBaseAttribute attribute,
                           ArgumentSetDefinition argSet,
                           object defaultValue = null,
                           ArgumentDefinition containingArgument = null,
                           ServiceConfigurer serviceConfigurer   = null)
     : this(GetMutableMemberInfo(member), attribute, argSet, defaultValue, /*fixedDestination=*/ null, containingArgument, serviceConfigurer)
 {
 }
Ejemplo n.º 5
0
 private static ArgumentParseContext CreateParseContext(ArgumentBaseAttribute attribute, ArgumentSetAttribute setAttribute, CommandLineParserOptions options) =>
 new ArgumentParseContext
 {
     NumberOptions    = attribute.NumberOptions,
     AllowEmpty       = attribute.AllowEmpty,
     FileSystemReader = options.FileSystemReader,
     ParserContext    = options.Context,
     CaseSensitive    = setAttribute.CaseSensitive
 };
Ejemplo n.º 6
0
        /// <summary>
        /// Internal constructor.
        /// </summary>
        /// <param name="member">Field to describe.</param>
        /// <param name="attribute">Argument attribute on the field.</param>
        /// <param name="argSet">Argument set containing this argument.</param>
        /// <param name="defaultValue">Default value for the field.</param>
        /// <param name="fixedDestination">Optionally provides fixed parse destination object.</param>
        /// <param name="containingArgument">Optionally provides a reference
        /// to the definition of the argument that "contains" these arguments.
        /// </param>
        /// <param name="serviceConfigurer">Optionally provides a service configurer.</param>
        internal ArgumentDefinition(IMutableMemberInfo member,
                                    ArgumentBaseAttribute attribute,
                                    ArgumentSetDefinition argSet,
                                    object defaultValue     = null,
                                    object fixedDestination = null,
                                    ArgumentDefinition containingArgument = null,
                                    ServiceConfigurer serviceConfigurer   = null)
        {
            Member                 = member ?? throw new ArgumentNullException(nameof(member));
            Attribute              = attribute ?? throw new ArgumentNullException(nameof(attribute));
            ContainingSet          = argSet ?? throw new ArgumentNullException(nameof(argSet));
            ContainingArgument     = containingArgument;
            FixedDestination       = fixedDestination;
            IsPositional           = attribute is PositionalArgumentAttribute;
            ArgumentType           = GetArgumentType(Attribute, member, member.MemberType, serviceConfigurer);
            CollectionArgumentType = AsCollectionType(ArgumentType);
            HasDefaultValue        = attribute.ExplicitDefaultValue || attribute.DynamicDefaultValue;
            ValidationAttributes   = GetValidationAttributes(ArgumentType, Member);

            LongName          = GetLongName(attribute, argSet.Attribute, member.MemberInfo);
            ExplicitShortName = HasExplicitShortName(attribute);
            ShortName         = GetShortNameOrNull(attribute, argSet.Attribute, member.MemberInfo);
            DefaultValue      = GetDefaultValue(attribute, member, defaultValue);

            var nullableBase = Nullable.GetUnderlyingType(member.MemberType);

            if (CollectionArgumentType != null)
            {
                ValueType = CollectionArgumentType.ElementType;
            }
            else if (nullableBase != null)
            {
                // For nullable arguments, we use the wrapped type (T in
                // Nullable<T>) as the value type. Parsing an enum or int is the
                // same as parsing an enum? or int?, for example, since null can
                // only arise if the value was not provided at all.
                ValueType = GetArgumentType(Attribute, member, nullableBase, serviceConfigurer);
            }
            else
            {
                ValueType = ArgumentType;
            }

            Debug.Assert(ValueType != null);

            if (Unique && !IsCollection)
            {
                throw new InvalidArgumentSetException(member, Strings.UniqueUsedOnNonCollectionArgument);
            }

            Debug.Assert(!string.IsNullOrEmpty(LongName));
        }
Ejemplo n.º 7
0
        private static string GetLongName(ArgumentBaseAttribute attribute, ArgumentSetAttribute argSetAttribute, MemberInfo member)
        {
            if (attribute.LongName != null)
            {
                return(attribute.LongName);
            }

            var longName = member.Name;

            if (argSetAttribute.NameGenerationFlags.HasFlag(ArgumentNameGenerationFlags.GenerateHyphenatedLowerCaseLongNames))
            {
                longName = longName.ToHyphenatedLowerCase();
            }

            return(longName);
        }
Ejemplo n.º 8
0
        private static object GetDefaultValue(ArgumentBaseAttribute attribute, IMutableMemberInfo member, object defaultFieldValue)
        {
            object value;

            if (attribute.DynamicDefaultValue)
            {
                value = defaultFieldValue;
            }
            else if (attribute.ExplicitDefaultValue)
            {
                value = attribute.DefaultValue;
            }
            else
            {
                try
                {
                    // N.B. This will fail if it's a reflection-only type.
                    value = member.MemberType.GetDefaultValue();
                }
                catch (InvalidOperationException)
                {
                    value = null;
                }
            }

            // Validate the value's type.
            if (value != null && !member.MemberType.GetTypeInfo().IsAssignableFrom(value.GetType()))
            {
                // See if it's implicitly convertible.
                if (!member.MemberType.IsImplicitlyConvertibleFrom(value))
                {
                    throw new InvalidArgumentSetException(member, string.Format(
                                                              CultureInfo.CurrentCulture,
                                                              Strings.DefaultValueIsOfWrongType,
                                                              member.MemberInfo.Name,
                                                              value.GetType().Name,
                                                              member.MemberType.Name));
                }
            }

            return(value);
        }
Ejemplo n.º 9
0
        private static string GetShortNameOrNull(ArgumentBaseAttribute attribute, ArgumentSetAttribute argSetAttribute, MemberInfo member)
        {
            if (attribute is PositionalArgumentAttribute)
            {
                return(null);
            }

            if (HasExplicitShortName(attribute))
            {
                var namedAttribute = (NamedArgumentAttribute)attribute;
                return(namedAttribute.ShortName.Length == 0 ? null : namedAttribute.ShortName);
            }

            var longName  = GetLongName(attribute, argSetAttribute, member);
            var shortName = longName.Substring(0, 1);

            if (argSetAttribute.NameGenerationFlags.HasFlag(ArgumentNameGenerationFlags.PreferLowerCaseForShortNames))
            {
                shortName = shortName.ToLower();
            }

            return(shortName);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Retrieves the <see cref="IArgumentType"/> type for the provided type.
        /// </summary>
        /// <param name="attrib">The argument attribute to use.</param>
        /// <param name="memberInfo">Member info for the argument.</param>
        /// <param name="type">The type to look up.</param>
        /// <param name="configurer">Optionally provides service configurer.</param>
        /// <returns>The found type.</returns>
        private static IArgumentType GetArgumentType(ArgumentBaseAttribute attrib, IMutableMemberInfo memberInfo, Type type, ServiceConfigurer configurer)
        {
            // First try to retrieve the default IArgumentType implementation
            // for this type, but don't fail if we can't find one.
            Types.ArgumentType.TryGetType(type, out IArgumentType argType);

            // If we don't have any overrides, then we already have the
            // implementation we'll need (or it doesn't exist).
            if (attrib.ArgumentType == null && attrib.Parser == null && attrib.Formatter == null && attrib.Completer == null)
            {
                if (argType == null)
                {
                    throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, Strings.TypeNotSupported, type.Name));
                }

                return(argType);
            }

            var serviceCollection = new ServiceCollection();

            configurer?.Invoke(serviceCollection);

            serviceCollection.AddSingleton <Type>(type);
            serviceCollection.AddSingleton <IMutableMemberInfo>(memberInfo);

            if (attrib.Parser != null)
            {
                serviceCollection.AddTransient(typeof(IStringParser), attrib.Parser);
            }

            if (attrib.Formatter != null)
            {
                serviceCollection.AddTransient(typeof(IObjectFormatter), attrib.Formatter);
            }

            if (attrib.Completer != null)
            {
                serviceCollection.AddTransient(typeof(IStringCompleter), attrib.Completer);
            }

            if (attrib.ArgumentType != null)
            {
                if (argType != null)
                {
                    serviceCollection.AddSingleton <IArgumentType>(argType);
                }

                serviceCollection.AddTransient(typeof(object), attrib.ArgumentType);

                argType = (IArgumentType)serviceCollection
                          .BuildServiceProvider()
                          .GetService <object>();
            }

            if (argType == null)
            {
                throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, Strings.TypeNotSupported, type.Name));
            }

            serviceCollection.AddSingleton <IArgumentType>(argType);

            if (attrib.Parser == null && attrib.Formatter == null && attrib.Completer == null)
            {
                return(argType);
            }

            var provider = serviceCollection.BuildServiceProvider();

            var parser    = provider.GetService <IStringParser>();
            var formatter = provider.GetService <IObjectFormatter>();
            var completer = provider.GetService <IStringCompleter>();

            return(new ArgumentTypeExtension(argType, parser, formatter, completer));
        }
Ejemplo n.º 11
0
        private static bool HasExplicitShortName(ArgumentBaseAttribute attribute)
        {
            var argAttrib = attribute as NamedArgumentAttribute;

            return(argAttrib?.ShortName != null);
        }
 private ArgumentDefinition DefineArg(ArgumentSetDefinition set, ArgumentBaseAttribute argAttrib) =>
 new ArgumentDefinition(
     typeof(TestArgumentSet).GetProperty(nameof(TestArgumentSet.SomeProperty)),
     argAttrib,
     set);