public ClassFile GenerateClass( GeneratorSettings settings, ParsedDefinitionList definitionList, string nameSpace, string className, bool addVerbToClassName, ParsedVerb verb, List <ParsedItem> items) { Clear(); TabSpaces = settings.TabSpaces; className = className + (addVerbToClassName ? verb.Name.Titleize() : ""); WriteLines(definitionList.Lines); WriteLine(); WriteNamespace(nameSpace); WriteSummaryComment(definitionList.Description); if (verb != null) { WriteAttribute("Verb", (null, verb.Name), ("HelpText", verb.DefinitionItem.HelpText ?? "")); } WriteClass(className); GenerateProperties(items); ClosingBracket(); ClosingBracket(); return(new ClassFile() { Namespace = nameSpace, ClassName = className, FileName = className + ".cs", Code = Code }); }
public void If_Every_Thing_Passed_Properly_Zero_Return_Code_Returns() { var args = new[] { "--name", "tarik" }; var testVerbInfo = new ParsedVerb() { VerbName = "default", Options = new Dictionary <string, List <string> >() { { "name", new List <string> { "tarik" } } } }; _commandParseMock.Setup(a => a.ParseCommand(It.IsAny <string[]>())) .Returns(testVerbInfo); _verbTypeFinder.Setup(a => a.FindByName(It.IsAny <string>())) .Returns(typeof(TestVerb)); _optionsParser.Setup(a => a.CreatePopulatedOptionsObject(typeof(TestVerb), testVerbInfo)) .Returns(new TestOptions() { Name = "tarik" }); var runner = new CommandCoreVerbRunner(_commandParseMock.Object, _verbTypeFinder.Object, _optionsParser.Object, _helpGeneratorMock.Object, _serviceProviderMock); Assert.Equal(0, runner.Run(args)); }
public ParsedVerb ParseCommand(string[] arguments) { if (arguments == null) { return(new ParsedVerb() { VerbName = "default" }); } var argumentsClone = (string[])arguments.Clone(); var parsedVerb = new ParsedVerb(); var firstArgIsVerb = argumentsClone.Length > 0 && !argumentsClone[0].StartsWith("-"); var startingPoint = 0; if (firstArgIsVerb) { startingPoint = 1; parsedVerb.VerbName = arguments[0]; } else { // If there is no verb defined, we need a default verb that handles all of the coming requests. parsedVerb.VerbName = "default"; } if (argumentsClone.Length <= 1) { return(parsedVerb); } var options = new Dictionary <string, List <string> >(); for (int i = startingPoint; i < arguments.Length; i++) { var arg = arguments[i]; if (arg.StartsWith("-") || arg.StartsWith("--")) { options.Add(arg.Trim('-'), new List <string>()); } else { options[options.Keys.Last()].Add(arg); } } parsedVerb.Options = options; return(parsedVerb); }
public VerbOptionsBase CreatePopulatedOptionsObject(Type verbType, ParsedVerb parsedVerb) { var verbOptionsType = verbType.BaseType !.GetGenericArguments()[0]; var options = (VerbOptionsBase)Activator.CreateInstance(verbOptionsType) !; var optionProperties = verbOptionsType.GetProperties(BindingFlags.Public | BindingFlags.Instance); if (parsedVerb.Options == null) { return(options); } foreach (var propertyInfo in optionProperties.Where(a => a.CanRead && a.CanWrite)) { var parameterNameAttributes = propertyInfo.GetCustomAttributes <OptionNameAttribute>().ToList(); string?ParameterNameFunc() => parameterNameAttributes?.FirstOrDefault(a => parsedVerb.Options.ContainsKey(a.Name)) ?.Name; string?ParameterAliasFunc() => parameterNameAttributes.FirstOrDefault(a => !string.IsNullOrWhiteSpace(a.Alias) && parsedVerb.Options.ContainsKey(a.Alias)) ?.Alias; var parameterName = ParameterNameFunc() ?? ParameterAliasFunc() ?? propertyInfo.Name; if (parsedVerb.Options !.ContainsKey(parameterName)) { var argumentValues = parsedVerb.Options[parameterName]; // I am aware of the relative complexity of the following big ass if conditions. I will simplify // it one, hopefully. But the idea is simple: A property type may be an array, a collection, or a scalar type. // And, we are paring them accordingly. var propType = propertyInfo.PropertyType; if (propType == typeof(bool)) { propertyInfo.SetValue(options, argumentValues.Count <= 0 || bool.Parse(argumentValues[0])); } // Zero count means something for the boolean properties since what matters is whether the flag is present or not // But for the other properties, it means nothing, so skipping property set since the user might have // assigned the properties a default value. We would not want to override it with null or default primitive type value. if (argumentValues.Count == 0) { continue; } if (propType.IsArray) { // Creating an instance of a new array using the property's array element type, and setting // the property value with it after filling it with the converted values. var elementType = propType.GetElementType() !; var array = Array.CreateInstance(elementType, argumentValues.Count); for (var i = 0; i < argumentValues.Count; i++) { array.SetValue(Convert.ChangeType(argumentValues[i], elementType), i); } propertyInfo.SetValue(options, array); } else if (propType.IsGenericType && (propType.GetGenericTypeDefinition() == typeof(IList <>) || propType.GetGenericTypeDefinition() == typeof(IReadOnlyList <>) || propType.GetGenericTypeDefinition().GetInterfaces().Any(a => a.IsGenericType && (a.GetGenericTypeDefinition() == typeof(IList <>) || a.GetGenericTypeDefinition() == typeof(IReadOnlyList <>))))) { // Creating an instance of a generic list using the property's generic argument, and setting // the property value with it after filling it with the converted values. var elementType = propType.GetGenericArguments()[0]; var listType = typeof(List <>); var constructedListType = listType.MakeGenericType(elementType); IList instance = (IList)Activator.CreateInstance(constructedListType) !; foreach (var arg in argumentValues) { instance.Add(Convert.ChangeType(arg, elementType)); } propertyInfo.SetValue(options, instance); } else { var converter = TypeDescriptor.GetConverter(propType); propertyInfo.SetValue(options, converter.ConvertFrom(argumentValues[0])); } } } return(options !); }