private List <CommandLineAction> FindCommandLineActions(Type t) { var knownAliases = new List <string>(); foreach (var argument in Arguments) { knownAliases.AddRange(argument.Aliases); } BindingFlags flags = BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public; var actions = (from p in t.GetProperties(flags) where CommandLineAction.IsActionImplementation(p) select CommandLineAction.Create(p, knownAliases)).ToList(); if (t.HasAttr <ArgActionType>()) { t = t.Attr <ArgActionType>().ActionType; } foreach (var action in t.GetMethods(flags).Where(m => CommandLineAction.IsActionImplementation(m)).Select(m => CommandLineAction.Create(m, knownAliases.ToList()))) { var matchingPropertyBasedAction = actions.Where(a => a.Aliases.First() == action.Aliases.First()).SingleOrDefault(); if (matchingPropertyBasedAction != null) { continue; } actions.Add(action); } return(actions); }
private List <CommandLineAction> FindCommandLineActions(Type t) { var knownAliases = new List <string>(); foreach (var argument in Arguments) { knownAliases.AddRange(argument.Aliases); } BindingFlags flags = BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public; var actions = (from p in t.GetProperties(flags) where CommandLineAction.IsActionImplementation(p) select CommandLineAction.Create(p, knownAliases)).ToList(); List <Type> typesToSearchForActions = new List <Type>() { t }; if (t.HasAttr <ArgActionResolver>()) { typesToSearchForActions.AddRange(t.Attr <ArgActionResolver>().ResolveActionTypes()); } typesToSearchForActions.AddRange(t.Attrs <ArgActionType>().Select(aat => aat.ActionType)); foreach (var typeToSearch in typesToSearchForActions) { var requireStatic = typeToSearch != t; foreach (var method in typeToSearch.GetMethods(flags).Where(m => CommandLineAction.IsActionImplementation(m))) { if (requireStatic && method.IsStatic == false) { throw new InvalidArgDefinitionException("The method " + method.DeclaringType.FullName + "." + method.Name + " must be static because it has been imported using [ArgActionType] or [ArgActions]"); } var action = CommandLineAction.Create(method, knownAliases.ToList()); var matchingPropertyBasedAction = actions.Where(a => a.Aliases.First() == action.Aliases.First()).SingleOrDefault(); if (matchingPropertyBasedAction != null) { continue; } actions.Add(action); } } return(actions); }
internal static bool IsArgument(PropertyInfo property) { if (property.HasAttr <ArgIgnoreAttribute>()) { return(false); } if (CommandLineAction.IsActionImplementation(property)) { return(false); } if (property.Name == Constants.ActionPropertyConventionName && property.HasAttr <ArgPosition>() && property.Attr <ArgPosition>().Position == 0 && property.HasAttr <ArgRequired>()) { return(false); } return(true); }
internal static List <string> FindDefaultShortcuts(PropertyInfo info, List <string> knownShortcuts, bool ignoreCase) { List <string> ret = new List <string>(); bool excludeName = info.Attrs <ArgShortcut>().Where(s => s.Policy == ArgShortcutPolicy.ShortcutsOnly).Count() > 0; if (excludeName == false) { knownShortcuts.Add(info.Name); if (CommandLineAction.IsActionImplementation(info) && info.Name.EndsWith(Constants.ActionArgConventionSuffix)) { ret.Add(info.Name.Substring(0, info.Name.Length - Constants.ActionArgConventionSuffix.Length)); } else { ret.Add(info.Name); } } var attrs = info.Attrs <ArgShortcut>(); if (attrs.Count == 0) { var shortcut = GenerateShortcutAlias(info.Name, knownShortcuts, ignoreCase); if (shortcut != null) { knownShortcuts.Add(shortcut); ret.Add(shortcut); } return(ret); } else { return(ret); } }
internal static List <string> FindDefaultShortcuts(PropertyInfo info, List <string> knownShortcuts, bool ignoreCase) { List <string> ret = new List <string>(); var argumentName = info.Name; bool excludeName = info.Attrs <ArgShortcut>().Where(s => s.Policy == ArgShortcutPolicy.ShortcutsOnly).Count() > 0; if (excludeName == false) { knownShortcuts.Add(info.Name); if (CommandLineAction.IsActionImplementation(info) && argumentName.EndsWith(Constants.ActionArgConventionSuffix)) { ret.Add(info.Name.Substring(0, argumentName.Length - Constants.ActionArgConventionSuffix.Length)); } else { ret.Add(argumentName); } } var attrs = info.Attrs <ArgShortcut>(); if (attrs.Count == 0) { var longFormShortcut = PascalCaseNameSplitter(info.Name); if (!knownShortcuts.Any(x => x.Equals(longFormShortcut, StringComparison.OrdinalIgnoreCase))) { knownShortcuts.Add(longFormShortcut); ret.Add(longFormShortcut); } } ret.Reverse(); return(ret); }
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; } // This check happens in the CommandLineArgumentsDefinition validation method and should not be repeated here. Leaving the code commented while this bakes, but this code // should be removable in the future. //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); } }