예제 #1
0
        private static void ValidateArguments(IEnumerable <CommandLineArgument> arguments)
        {
            List <string> knownAliases = new List <string>();

            foreach (var argument in arguments)
            {
                foreach (var alias in argument.Aliases)
                {
                    if (knownAliases.Contains(alias, new CaseAwareStringComparer(argument.IgnoreCase)))
                    {
                        throw new InvalidArgDefinitionException("Duplicate alias '" + alias + "' on argument '" + argument.Aliases.First() + "'");
                    }
                    knownAliases.Add(alias);
                }
            }

            foreach (var argument in arguments)
            {
                if (argument.ArgumentType == null)
                {
                    throw new InvalidArgDefinitionException("Argument '" + argument.DefaultAlias + "' has a null ArgumentType");
                }

                if (argument.MustBeRevivable && ArgRevivers.CanRevive(argument.ArgumentType) == false)
                {
                    throw new InvalidArgDefinitionException("There is no reviver for type '" + argument.ArgumentType.Name + '"');
                }

                if (argument.ArgumentType.IsEnum)
                {
                    argument.ArgumentType.ValidateNoDuplicateEnumShortcuts(argument.IgnoreCase);
                }
            }
        }
        internal static CommandLineAction Create(MethodInfo actionMethod, List <string> knownAliases)
        {
            var ret = PropertyInitializer.CreateInstance <CommandLineAction>();

            ret.ActionMethod = actionMethod;

            ret.Source = actionMethod;
            ret.Aliases.Add(actionMethod.Name);

            ret.Metadata.AddRange(actionMethod.Attrs <IArgMetadata>().AssertAreAllInstanceOf <ICommandLineActionMetadata>());

            ret.IgnoreCase = true;

            if (actionMethod.DeclaringType.HasAttr <ArgIgnoreCase>() && actionMethod.DeclaringType.Attr <ArgIgnoreCase>().IgnoreCase == false)
            {
                ret.IgnoreCase = false;
            }

            if (actionMethod.HasAttr <ArgIgnoreCase>() && actionMethod.Attr <ArgIgnoreCase>().IgnoreCase == false)
            {
                ret.IgnoreCase = false;
            }

            var directPipelineTarget = (from p in actionMethod.GetParameters() where p.HasAttr <ArgPipelineTarget>() select p).SingleOrDefault();

            if (directPipelineTarget != null)
            {
                if (directPipelineTarget.Attr <ArgPipelineTarget>().PipelineOnly == false && ArgRevivers.CanRevive(directPipelineTarget.ParameterType) == false)
                {
                    throw new InvalidArgDefinitionException("Method " + actionMethod.DeclaringType.FullName + "." + actionMethod.Name + " has parameter " + directPipelineTarget.Name + " of type " + directPipelineTarget.ParameterType.FullName + " which has set PipelineOnly to false, but has no reviver");
                }

                ret.Arguments.AddRange(actionMethod.GetParameters().Where(p => CommandLineArgument.IsArgument(p)).Select(p => CommandLineArgument.Create(p)));
                foreach (var arg in (ret.Arguments).Where(a => a.Position >= 0))
                {
                    arg.Position++; // Since position 0 is reserved for the action specifier
                }
            }
            else
            {
                if (actionMethod.GetParameters().Length == 1 && ArgRevivers.CanRevive(actionMethod.GetParameters()[0].ParameterType) == false)
                {
                    ret.Arguments.AddRange(actionMethod.GetParameters()[0].ParameterType.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(p => CommandLineArgument.IsArgument(p)).Select(p => CommandLineArgument.Create(p, knownAliases)));
                }
                else if (actionMethod.GetParameters().Length > 0 && actionMethod.GetParameters().Where(p => ArgRevivers.CanRevive(p.ParameterType) == false).Count() == 0)
                {
                    ret.Arguments.AddRange(actionMethod.GetParameters().Where(p => CommandLineArgument.IsArgument(p)).Select(p => CommandLineArgument.Create(p)));
                    foreach (var arg in (ret.Arguments).Where(a => a.Position >= 0))
                    {
                        arg.Position++; // Since position 0 is reserved for the action specifier
                    }
                }
                else if (actionMethod.GetParameters().Length > 0)
                {
                    throw new InvalidArgDefinitionException("Your action method contains a parameter that cannot be revived on its own.  That is only valid if the non-revivable parameter is the only parameter.  In that case, the properties of that parameter type will be used.");
                }
            }
            return(ret);
        }
예제 #3
0
        internal static void Revive(this PropertyInfo prop, object toRevive, ArgHook.HookContext context)
        {
            if (ArgRevivers.CanRevive(prop.PropertyType) && context.ArgumentValue != null)
            {
                try
                {
                    if (prop.PropertyType.IsEnum)
                    {
                        bool ignoreCase = true;

                        if (prop.HasAttr <ArgIgnoreCase>() && prop.Attr <ArgIgnoreCase>().IgnoreCase == false)
                        {
                            ignoreCase = true;
                        }

                        context.RevivedProperty = ArgRevivers.ReviveEnum(prop.PropertyType, context.ArgumentValue, ignoreCase);
                    }
                    else
                    {
                        context.RevivedProperty = ArgRevivers.Revive(prop.PropertyType, prop.GetArgumentName(), context.ArgumentValue);
                    }
                    prop.SetValue(toRevive, context.RevivedProperty, null);
                }
                catch (ArgException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    if (ex.InnerException != null && ex.InnerException is ArgException)
                    {
                        throw ex.InnerException;
                    }
                    else
                    {
                        if (prop.PropertyType.IsEnum)
                        {
                            throw new ArgException("'" + context.ArgumentValue + "' is not a valid value for " + prop.GetArgumentName() + ". Available values are [" + string.Join(", ", Enum.GetNames(prop.PropertyType)) + "]", ex);
                        }
                        else
                        {
                            throw new ArgException(ex.Message, ex);
                        }
                    }
                }
            }
            else if (ArgRevivers.CanRevive(prop.PropertyType) && prop.PropertyType == typeof(SecureStringArgument))
            {
                context.RevivedProperty = ArgRevivers.Revive(prop.PropertyType, prop.GetArgumentName(), context.ArgumentValue);
                prop.SetValue(toRevive, context.RevivedProperty, null);
            }
            else if (context.ArgumentValue != null)
            {
                throw new ArgException("Unexpected argument '" + prop.GetArgumentName() + "' with value '" + context.ArgumentValue + "'");
            }
        }
예제 #4
0
        private static void ValidateArguments(IEnumerable <CommandLineArgument> arguments)
        {
            List <string> knownAliases = new List <string>();

            foreach (var argument in arguments)
            {
                foreach (var alias in argument.Aliases)
                {
                    if (knownAliases.Contains(alias, new CaseAwareStringComparer(argument.IgnoreCase)))
                    {
                        throw new InvalidArgDefinitionException("Duplicate alias '" + alias + "' on argument '" + argument.Aliases.First() + "'");
                    }
                    knownAliases.Add(alias);
                }
            }

            foreach (var argument in arguments)
            {
                if (argument.ArgumentType == null)
                {
                    throw new InvalidArgDefinitionException("Argument '" + argument.DefaultAlias + "' has a null ArgumentType");
                }

                if (argument.MustBeRevivable && ArgRevivers.CanRevive(argument.ArgumentType) == false)
                {
                    throw new InvalidArgDefinitionException("There is no reviver for type '" + argument.ArgumentType.Name + '"');
                }

                if (argument.ArgumentType.IsEnum)
                {
                    argument.ArgumentType.ValidateNoDuplicateEnumShortcuts(argument.IgnoreCase);
                }


                foreach (var property in argument.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
                {
                    // Getting each property will result in all AttrOverrides being validated
                    try
                    {
                        var val = property.GetValue(argument, null);
                    }
                    catch (TargetInvocationException ex)
                    {
                        if (ex.InnerException is InvalidArgDefinitionException)
                        {
                            ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
                        }
                        else
                        {
                            throw;
                        }
                    }
                }
            }
        }
예제 #5
0
 internal void Revive(string commandLineValue)
 {
     if (ArgRevivers.CanRevive(ArgumentType) && commandLineValue != null)
     {
         try
         {
             if (ArgumentType.IsEnum)
             {
                 RevivedValue = ArgRevivers.ReviveEnum(ArgumentType, commandLineValue, IgnoreCase);
             }
             else
             {
                 RevivedValue = ArgRevivers.Revive(ArgumentType, Aliases.First(), commandLineValue);
             }
         }
         catch (ArgException)
         {
             throw;
         }
         catch (Exception ex)
         {
             if (ex.InnerException != null && ex.InnerException is ArgException)
             {
                 throw ex.InnerException;
             }
             else
             {
                 if (ArgumentType.IsEnum)
                 {
                     throw new ArgException("'" + commandLineValue + "' is not a valid value for " + Aliases.First() + ". Available values are [" + string.Join(", ", Enum.GetNames(ArgumentType)) + "]", ex);
                 }
                 else
                 {
                     throw new ArgException(ex.Message, ex);
                 }
             }
         }
     }
     else if (ArgRevivers.CanRevive(ArgumentType) && ArgumentType == typeof(SecureStringArgument))
     {
         RevivedValue = ArgRevivers.Revive(ArgumentType, Aliases.First(), commandLineValue);
     }
     else if (commandLineValue != null && ArgRevivers.CanRevive(ArgumentType))
     {
         throw new ArgException("Unexpected argument '" + Aliases.First() + "' with value '" + commandLineValue + "'");
     }
     else if (commandLineValue != null && ArgRevivers.CanRevive(ArgumentType) == false)
     {
         throw new InvalidArgDefinitionException("There is no reviver for type '" + ArgumentType.Name + '"');
     }
 }
        internal object PopulateArguments(object parent, ref object[] parameters)
        {
            Type actionArgsType = null;

            if (Source is PropertyInfo)
            {
                actionArgsType = (Source as PropertyInfo).PropertyType;
            }
            else if (Source is MethodInfo && (Source as MethodInfo).GetParameters().Length > 0)
            {
                if ((Source as MethodInfo).GetParameters().Length > 1 || ArgRevivers.CanRevive((Source as MethodInfo).GetParameters()[0].ParameterType))
                {
                    parameters = Arguments.Select(a => a.RevivedValue).ToArray();
                    return(null);
                }
                else
                {
                    actionArgsType = (Source as MethodInfo).GetParameters()[0].ParameterType;
                }
            }
            else
            {
                return(null);
            }

            var ret = Activator.CreateInstance(actionArgsType);

            foreach (var argument in Arguments)
            {
                var argumentProperty = argument.Source as PropertyInfo;
                if (argumentProperty != null)
                {
                    argumentProperty.SetValue(ret, argument.RevivedValue, null);
                }
            }

            if (Source is PropertyInfo)
            {
                (Source as PropertyInfo).SetValue(parent, ret, null);
            }

            return(ret);
        }
예제 #7
0
        private void ValidateArgScaffold(Type t, List<string> shortcuts = null, Type parentType = null)
        {
            /*
             * Today, this validates the following:
             * 
             *     - IgnoreCase can't be different on parent and child scaffolds.
             *     - No collisions on shortcut values for properties and enum values
             *     - No reviver for type
             * 
             */

            if (parentType != null)
            {
                if(parentType.HasAttr<ArgIgnoreCase>() ^ t.HasAttr<ArgIgnoreCase>())
                {
                    throw new InvalidArgDefinitionException("If you specify the " + typeof(ArgIgnoreCase).Name + " attribute on your base type then you must also specify it on each action type.");
                }
                else if (parentType.HasAttr<ArgIgnoreCase>() && parentType.Attr<ArgIgnoreCase>().IgnoreCase != t.Attr<ArgIgnoreCase>().IgnoreCase)
                {
                    throw new InvalidArgDefinitionException("If you specify the " + typeof(ArgIgnoreCase).Name + " attribute on your base and acton types then they must be configured to use the same value for IgnoreCase.");
                }
            }

            if (t.Attrs<ArgIgnoreCase>().Count > 1) throw new InvalidArgDefinitionException("An attribute that is or derives from " + typeof(ArgIgnoreCase).Name+" was specified on your type more than once");


            var actionProp = ArgAction.GetActionProperty(t);
            shortcuts = shortcuts ?? new List<string>();
            bool ignoreCase = true;
            if (t.HasAttr<ArgIgnoreCase>() && t.Attr<ArgIgnoreCase>().IgnoreCase == false) ignoreCase = false;

            foreach (PropertyInfo prop in t.GetProperties(BindingFlags.Instance | BindingFlags.Public))
            {
                if (prop.Attr<ArgIgnoreAttribute>() != null) continue;
                if (CommandLineAction.IsActionImplementation(prop)) continue;

                if (ArgRevivers.CanRevive(prop.PropertyType) == false)
                {
                    throw new InvalidArgDefinitionException("There is no reviver for type " + prop.PropertyType.Name + ". Offending Property: " + prop.DeclaringType.Name + "." + prop.Name);
                }

                if (prop.PropertyType.IsEnum)
                {
                    prop.PropertyType.ValidateNoDuplicateEnumShortcuts(ignoreCase);
                }

                var attrs = prop.Attrs<ArgShortcut>();
                var noShortcutsAllowed = attrs.Where(a => a.Policy == ArgShortcutPolicy.NoShortcut).Count() != 0;
                var shortcutsOnly = attrs.Where(a => a.Policy == ArgShortcutPolicy.ShortcutsOnly).Count() != 0;
                var actualShortcutValues = attrs.Where(a => a.Policy == ArgShortcutPolicy.Default && a.Shortcut != null).Count() != 0;

                if (noShortcutsAllowed && shortcutsOnly) throw new InvalidArgDefinitionException("You cannot specify a policy of NoShortcut and another policy of ShortcutsOnly.");
                if (noShortcutsAllowed && actualShortcutValues) throw new InvalidArgDefinitionException("You cannot specify a policy of NoShortcut and then also specify shortcut values via another attribute.");
                if (shortcutsOnly && actualShortcutValues == false) throw new InvalidArgDefinitionException("You specified a policy of ShortcutsOnly, but did not specify any shortcuts by adding another ArgShortcut attrivute.");
            }

            if (actionProp != null)
            {
                foreach (PropertyInfo prop in t.GetProperties(BindingFlags.Instance | BindingFlags.Public))
                {
                    if (CommandLineAction.IsActionImplementation(prop))
                    {
                        ArgAction.ResolveMethod(t,prop);
                        ValidateArgScaffold(prop.PropertyType, shortcuts.ToArray().ToList(), t);
                    }
                }
            }

            foreach (var actionMethod in t.GetActionMethods())
            {
                if(actionMethod.GetParameters().Length == 0)continue;

                ValidateArgScaffold(actionMethod.GetParameters()[0].ParameterType, shortcuts.ToArray().ToList(), t);
            }
        }
예제 #8
0
파일: Args.cs 프로젝트: atruskie/PowerArgs
        private void ValidateArgScaffold(Type t, List <string> shortcuts = null, Type parentType = null)
        {
            if (parentType != null)
            {
                if (parentType.HasAttr <ArgIgnoreCase>() ^ t.HasAttr <ArgIgnoreCase>())
                {
                    throw new InvalidArgDefinitionException("If you specify the " + typeof(ArgIgnoreCase).Name + " attribute on your base type then you must also specify it on each action type.");
                }
                else if (parentType.HasAttr <ArgIgnoreCase>() && parentType.Attr <ArgIgnoreCase>().IgnoreCase != t.Attr <ArgIgnoreCase>().IgnoreCase)
                {
                    throw new InvalidArgDefinitionException("If you specify the " + typeof(ArgIgnoreCase).Name + " attribute on your base and acton types then they must be configured to use the same value for IgnoreCase.");
                }
            }

            if (t.Attrs <ArgIgnoreCase>().Count > 1)
            {
                throw new InvalidArgDefinitionException("An attribute that is or derives from " + typeof(ArgIgnoreCase).Name + " was specified on your type more than once");
            }


            var actionProp = ArgAction.GetActionProperty(t);

            shortcuts = shortcuts ?? new List <string>();
            bool ignoreCase = true;

            if (t.HasAttr <ArgIgnoreCase>() && t.Attr <ArgIgnoreCase>().IgnoreCase == false)
            {
                ignoreCase = false;
            }

            foreach (PropertyInfo prop in t.GetProperties(BindingFlags.Instance | BindingFlags.Public))
            {
                if (prop.Attr <ArgIgnoreAttribute>() != null)
                {
                    continue;
                }
                if (prop.IsActionArgProperty() && actionProp != null)
                {
                    continue;
                }

                if (ArgRevivers.CanRevive(prop.PropertyType) == false)
                {
                    throw new InvalidArgDefinitionException("There is no reviver for type " + prop.PropertyType.Name + ". Offending Property: " + prop.DeclaringType.Name + "." + prop.GetArgumentName());
                }

                var shortcut = ArgShortcut.GetShortcut(prop);

                if (ignoreCase && shortcut != null)
                {
                    shortcut = shortcut.ToLower();
                }

                if (shortcut != null && shortcuts.Contains(shortcut))
                {
                    throw new InvalidArgDefinitionException("Duplicate arg options with shortcut '" + ArgShortcut.GetShortcut(prop) + "'.  Keep in mind that shortcuts are not case sensitive unless you use the [ArgIgnoreCase(false)] attribute.  For example, Without this attribute the shortcuts '-a' and '-A' would cause this exception.");
                }
                else if (shortcut != null)
                {
                    shortcuts.Add(shortcut);
                }
            }

            if (actionProp != null)
            {
                foreach (PropertyInfo prop in t.GetProperties(BindingFlags.Instance | BindingFlags.Public))
                {
                    if (prop.IsActionArgProperty())
                    {
                        ArgAction.ResolveMethod(t, prop);
                        ValidateArgScaffold(prop.PropertyType, shortcuts.ToArray().ToList(), t);
                    }
                }
            }
        }