public ParameterArgumentDef( ParameterInfo parameterInfo, CommandNodeType commandNodeType, AppConfig appConfig, object?[] parameterValues) { if (parameterValues == null) { throw new ArgumentNullException(nameof(parameterValues)); } _parameterInfo = parameterInfo ?? throw new ArgumentNullException(nameof(parameterInfo)); CommandNodeType = commandNodeType; Name = parameterInfo.BuildName(commandNodeType, appConfig); IsOptional = _parameterInfo.IsOptional || _parameterInfo.IsNullableParameter(); BooleanMode = this.GetBooleanMode(appConfig.AppSettings.Arguments.BooleanMode); Split = this.GetSplitChar(); ValueProxy = new ValueProxy( () => parameterValues[parameterInfo.Position], value => parameterValues[parameterInfo.Position] = value ); Arity = ArgumentArity.Default(this); }
private void ValidateCommand(CommandResult commandResult) { foreach (var a in commandResult .Command .Arguments) { if (a is Argument argument) { var arityFailure = ArgumentArity.Validate( commandResult, a, a.Arity.MinimumNumberOfValues, a.Arity.MaximumNumberOfValues); if (arityFailure != null) { _errors.Add( new ParseError(arityFailure.ErrorMessage, commandResult)); } foreach (var validator in argument.SymbolValidators) { var errorMessage = validator(commandResult); if (!string.IsNullOrWhiteSpace(errorMessage)) { _errors.Add( new ParseError(errorMessage, commandResult)); } } } } }
public void DefaultNullableBool(BooleanMode booleanMode, bool isOptional, bool hasDefault, int expectedMin, int expectedMax) { var actual = ArgumentArity.Default(typeof(bool?), isOptional, hasDefault, booleanMode); var expected = new ArgumentArity(expectedMin, expectedMax); actual.Should().Be(expected); }
public PropertyArgumentDef( PropertyInfo propertyInfo, CommandNodeType commandNodeType, AppConfig appConfig, object modelInstance) { if (modelInstance == null) { throw new ArgumentNullException(nameof(modelInstance)); } _propertyInfo = propertyInfo ?? throw new ArgumentNullException(nameof(propertyInfo)); CommandNodeType = commandNodeType; Name = propertyInfo.BuildName(commandNodeType, appConfig); IsOptional = propertyInfo.IsNullableProperty(); BooleanMode = this.GetBooleanMode(appConfig.AppSettings.Arguments.BooleanMode); Split = this.GetSplitChar(); ValueProxy = new ValueProxy( () => _propertyInfo.GetValue(modelInstance), value => _propertyInfo.SetValue(modelInstance, value) ); DefaultValue = propertyInfo.GetValue(modelInstance); HasDefaultValue = propertyInfo.PropertyType.IsClass ? !DefaultValue.IsNullValue() : !DefaultValue?.IsDefaultFor(propertyInfo.PropertyType) ?? false; Arity = ArgumentArity.Default(this); }
public void Default(Type type, bool isOptional, bool hasDefault, int expectedMin, int expectedMax) { var actual = ArgumentArity.Default(type, isOptional, hasDefault, BooleanMode.Explicit); var expected = new ArgumentArity(expectedMin, expectedMax); actual.Should().Be(expected); }
private void ValidateArgument(ArgumentResult argumentResult) { var arityFailure = ArgumentArity.Validate(argumentResult); if (arityFailure != null) { _errors.Add(new ParseError(arityFailure.ErrorMessage)); return; } if (argumentResult.Argument is Argument argument) { var parseError = argumentResult.Parent.UnrecognizedArgumentError(argument) ?? argumentResult.Parent.CustomError(argument); if (parseError != null) { _errors.Add(parseError); return; } } if (argumentResult.ArgumentConversionResult is FailedArgumentConversionResult failed) { _errors.Add( new ParseError( failed.ErrorMessage, argumentResult)); } }
private IEnumerable <Option> GenerateTestOptions(int count, ArgumentArity arity) => Enumerable.Range(0, count) .Select(i => new Option($"-option{i}", arity: arity) { Description = $"Description for -option {i} ...." } );
public void DefaultNullableBool(BooleanMode booleanMode, bool hasDefaultValue, int expectedMin, int expectedMax) { var actual = ArgumentArity.Default(typeof(bool?), hasDefaultValue, booleanMode); var expected = new ArgumentArity(expectedMin, expectedMax); expected.Should().Be(actual); }
public void Default(Type type, bool hasDefaultValue, int expectedMin, int expectedMax) { var actual = ArgumentArity.Default(type, hasDefaultValue, BooleanMode.Explicit); var expected = new ArgumentArity(expectedMin, expectedMax); expected.Should().Be(actual); }
public void Verify_option_configuration(string alias, ArgumentArity arity, int elementIndex) { var computeHistoryCommand = new ComputeHistoryCommand(); var option = computeHistoryCommand.Options.ElementAt(elementIndex); option.Name.Should().Be(alias); option.Arity.Should().BeEquivalentTo(arity); }
public void Verify_argument_configuration(string alias, ArgumentArity arity, int elementIndex) { var checkoutHistoryCommand = new CheckoutHistoryCommand(); var argument = checkoutHistoryCommand.Arguments.ElementAt(elementIndex); argument.Name.Should().Be(alias); argument.Arity.Should().BeEquivalentTo(arity); }
internal static Option <string[]> CreateAddSourceOption() { return(new(new[] { "--add-source", "--nuget-source" }) { Arity = new ArgumentArity(1, 99), Description = SymbolStrings.Option_AddSource, AllowMultipleArgumentsPerToken = true, });
private static IArgument BuildArgument(IArgumentDef argumentDef, Command parent, AppConfig appConfig, TypeInfo typeInfo, bool isInterceptorOption) { var defaultValue = argumentDef.HasDefaultValue ? argumentDef.DefaultValue : null; if (argumentDef.CommandNodeType == CommandNodeType.Operand) { var operandAttr = argumentDef.CustomAttributes.GetCustomAttribute <OperandAttribute>() ?? (INameAndDescription)argumentDef.CustomAttributes.GetCustomAttribute <ArgumentAttribute>(); return(new Operand( argumentDef.Name, parent, typeInfo, ArgumentArity.Default(argumentDef.Type, argumentDef.HasDefaultValue, BooleanMode.Explicit), argumentDef.SourcePath, customAttributes: argumentDef.CustomAttributes, argumentDef.ValueProxy) { Description = operandAttr?.Description, DefaultValue = defaultValue }); } if (argumentDef.CommandNodeType == CommandNodeType.Option) { var optionAttr = argumentDef.CustomAttributes.GetCustomAttribute <OptionAttribute>(); var booleanMode = GetOptionBooleanMode(argumentDef, appConfig.AppSettings.BooleanMode, optionAttr); var argumentArity = ArgumentArity.Default(argumentDef.Type, argumentDef.HasDefaultValue, booleanMode); var assignOnlyToExecutableSubcommands = optionAttr?.AssignToExecutableSubcommands ?? false; isInterceptorOption = isInterceptorOption && !assignOnlyToExecutableSubcommands; var longName = optionAttr?.ShortName != null ? optionAttr?.LongName : (optionAttr?.LongName ?? argumentDef.Name); return(new Option( longName, ParseShortName(argumentDef, optionAttr?.ShortName), parent, typeInfo, argumentArity, definitionSource: argumentDef.SourcePath, customAttributes: argumentDef.CustomAttributes, isInterceptorOption: isInterceptorOption, assignToExecutableSubcommands: assignOnlyToExecutableSubcommands, valueProxy: argumentDef.ValueProxy) { Description = optionAttr?.Description, DefaultValue = defaultValue }); } throw new ArgumentOutOfRangeException($"Unknown argument type: {argumentDef.CommandNodeType}"); }
public static void VerifyAlias <T>(string alias, ArgumentArity arity, bool allowMultipleArgumentsPerToken) where T : Command, new() { var command = new T(); var option = command.Options.FirstOrDefault(x => x.Aliases.Contains(alias)); option.Should().NotBeNull(); option !.AllowMultipleArgumentsPerToken.Should().Be(allowMultipleArgumentsPerToken); option.Arity.Should().BeEquivalentTo(arity); }
protected override void Stop(SyntaxNode node) { ValidateCommandHandler(_innermostCommandResult); foreach (var commandResult in _innermostCommandResult.RecurseWhileNotNull(c => c.ParentCommandResult)) { foreach (var symbol in commandResult.Command.Children) { PopulateDefaultValues(commandResult, symbol); } ValidateCommand(commandResult); foreach (var result in commandResult.Children) { switch (result) { case ArgumentResult argumentResult: ValidateArgument(argumentResult); break; case OptionResult optionResult: var argument = optionResult.Option.Argument; var arityFailure = ArgumentArity.Validate( optionResult, argument, argument.Arity.MinimumNumberOfValues, argument.Arity.MaximumNumberOfValues); if (arityFailure != null) { _errors.Add( new ParseError(arityFailure.ErrorMessage, optionResult)); } var results = optionResult.Children .OfType <ArgumentResult>() .ToArray(); foreach (var a in results) { ValidateArgument(a); } break; } } } }
private void ValidateCommandResult() { if (_innermostCommandResult !.Command is Command command) { for (var i = 0; i < command.Validators.Count; i++) { var validator = command.Validators[i]; var errorMessage = validator(_innermostCommandResult); if (!string.IsNullOrWhiteSpace(errorMessage)) { _errors.Add( new ParseError(errorMessage !, _innermostCommandResult)); } } } foreach (var option in _innermostCommandResult .Command .Options) { if (option is Option o && o.IsRequired && _rootCommandResult !.FindResultFor(o) is null) { _errors.Add( new ParseError($"Option '{o.Aliases.First()}' is required.", _innermostCommandResult)); } } foreach (var symbol in _innermostCommandResult .Command .Arguments) { var arityFailure = ArgumentArity.Validate( _innermostCommandResult, symbol, symbol.Arity.MinimumNumberOfValues, symbol.Arity.MaximumNumberOfValues); if (arityFailure != null) { _errors.Add( new ParseError(arityFailure.ErrorMessage !, _innermostCommandResult)); } } }
private void ValidateCommandResult(CommandResult commandResult) { if (commandResult.Command is Command command) { foreach (var validator in command.Validators) { var errorMessage = validator(commandResult); if (!string.IsNullOrWhiteSpace(errorMessage)) { _errors.Add( new ParseError(errorMessage, commandResult)); } } } foreach (var option in commandResult .Command .Options) { if (option is Option o && o.Required && _rootCommandResult.FindResultFor(o) == null) { _errors.Add( new ParseError($"Option '{o.RawAliases.First()}' is required.", commandResult)); } } foreach (var symbol in commandResult .Command .Arguments) { var arityFailure = ArgumentArity.Validate( commandResult, symbol, symbol.Arity.MinimumNumberOfValues, symbol.Arity.MaximumNumberOfValues); if (arityFailure != null) { _errors.Add( new ParseError(arityFailure.ErrorMessage, commandResult)); } } }
private void ValidateOptionResult(OptionResult optionResult) { var argument = optionResult.Option.Argument; var arityFailure = ArgumentArity.Validate( optionResult, argument, argument.Arity.MinimumNumberOfValues, argument.Arity.MaximumNumberOfValues); if (arityFailure != null) { _errors.Add( new ParseError(arityFailure.ErrorMessage !, optionResult)); } if (optionResult.Option is Option option) { for (var i = 0; i < option.Validators.Count; i++) { var validate = option.Validators[i]; var message = validate(optionResult); if (!string.IsNullOrWhiteSpace(message)) { _errors.Add(new ParseError(message !, optionResult)); } } } for (var i = 0; i < optionResult.Children.Count; i++) { var result = optionResult.Children[i]; if (result is ArgumentResult argumentResult) { ValidateArgumentResult(argumentResult); } } }
private void ValidateOptionResult(OptionResult optionResult) { var argument = optionResult.Option.Argument; var arityFailure = ArgumentArity.Validate( optionResult, argument, argument.Arity.MinimumNumberOfValues, argument.Arity.MaximumNumberOfValues); if (arityFailure != null) { _errors.Add( new ParseError(arityFailure.ErrorMessage !, optionResult)); } if (optionResult.Option is Option option) { foreach (var validate in option.Validators) { var message = validate(optionResult); if (!string.IsNullOrWhiteSpace(message)) { _errors.Add(new ParseError(message !, optionResult)); } } } foreach (var argumentResult in optionResult .Children .OfType <ArgumentResult>()) { ValidateArgumentResult(argumentResult); } }
public void VerifyOptionConfigurations(string alias, ArgumentArity arity, bool allowsMultiples) => TestHelpers.VerifyAlias <ScanCommand>(alias, arity, allowsMultiples);
public static Command RootCommand() { // For some reason, arity caps at 255 by default ArgumentArity arbitraryArity = new ArgumentArity(0, 100000); return(new Command("Crossgen2Compilation") { new Argument <FileInfo[]>() { Name = "input-file-paths", Description = SR.InputFilesToCompile, Arity = arbitraryArity, }, new Option(new[] { "--unrooted-input-file-paths", "-u" }, SR.UnrootedInputFilesToCompile) { Argument = new Argument <FileInfo[]>() { Arity = arbitraryArity } }, new Option(new[] { "--reference", "-r" }, SR.ReferenceFiles) { Argument = new Argument <string[]>() { Arity = arbitraryArity } }, new Option(new[] { "--instruction-set" }, SR.InstructionSets) { Argument = new Argument <string>() }, new Option(new[] { "--mibc", "-m" }, SR.MibcFiles) { Argument = new Argument <string[]>() { Arity = arbitraryArity } }, new Option(new[] { "--outputfilepath", "--out", "-o" }, SR.OutputFilePath) { Argument = new Argument <FileInfo>() }, new Option(new[] { "--optimize", "-O" }, SR.EnableOptimizationsOption) { Argument = new Argument <bool>() }, new Option(new[] { "--optimize-space", "--Os" }, SR.OptimizeSpaceOption) { Argument = new Argument <bool>() }, new Option(new[] { "--optimize-time", "--Ot" }, SR.OptimizeSpeedOption), new Option(new[] { "--inputbubble" }, SR.InputBubbleOption), new Option(new[] { "--composite" }, SR.CompositeBuildMode), new Option(new[] { "--tuning" }, SR.TuningImageOption) { Argument = new Argument <bool>() }, new Option(new[] { "--partial" }, SR.PartialImageOption) { Argument = new Argument <bool>() }, new Option(new[] { "--compilebubblegenerics" }, SR.BubbleGenericsOption) { Argument = new Argument <bool>() }, new Option(new[] { "--dgml-log-file-name", "--dmgllog" }, SR.SaveDependencyLogOption) { Argument = new Argument <FileInfo>() }, new Option(new[] { "--generate-full-dmgl-log", "--fulllog" }, SR.SaveDetailedLogOption) { Argument = new Argument <bool>() }, new Option(new[] { "--verbose" }, SR.VerboseLoggingOption) { Argument = new Argument <bool>() }, new Option(new[] { "--systemmodule" }, SR.SystemModuleOverrideOption) { Argument = new Argument <string>() }, new Option(new[] { "--waitfordebugger" }, SR.WaitForDebuggerOption) { Argument = new Argument <bool>() }, new Option(new[] { "--codegen-options", "--codegenopt" }, SR.CodeGenOptions) { Argument = new Argument <string[]>() { Arity = arbitraryArity } }, new Option(new[] { "--resilient" }, SR.ResilientOption) { Argument = new Argument <bool>() }, new Option(new[] { "--targetarch" }, SR.TargetArchOption) { Argument = new Argument <string>() }, new Option(new[] { "--targetos" }, SR.TargetOSOption) { Argument = new Argument <string>() }, new Option(new[] { "--jitpath" }, SR.JitPathOption) { Argument = new Argument <FileInfo>() }, new Option(new[] { "--singlemethodtypename" }, SR.SingleMethodTypeName) { Argument = new Argument <string>() }, new Option(new[] { "--singlemethodname" }, SR.SingleMethodMethodName) { Argument = new Argument <string>() }, new Option(new[] { "--singlemethodgenericarg" }, SR.SingleMethodGenericArgs) { // We don't need to override arity here as 255 is the maximum number of generic arguments Argument = new Argument <string[]>() }, new Option(new[] { "--parallelism" }, SR.ParalellismOption) { Argument = new Argument <int>(() => Environment.ProcessorCount) }, new Option(new[] { "--map" }, SR.MapFileOption) { Argument = new Argument <bool>() }, }); }
public void DefaultBooleanModeCannotBeUnknown() { Assert.Throws <ArgumentException>( () => ArgumentArity.Default(typeof(bool), NoDefault, BooleanMode.Unknown)) .Message.Should().Be("booleanMode cannot be Unknown"); }
public Argument() { Arity = ArgumentArity.DefaultForType(typeof(T)); ArgumentType = typeof(T); }
public static Command RootCommand() { // For some reason, arity caps at 255 by default ArgumentArity arbitraryArity = new ArgumentArity(0, 100000); return(new Command("Crossgen2Compilation") { new Argument <FileInfo[]>() { Name = "input-file-paths", Description = "Input file(s) to compile", Arity = arbitraryArity, }, new Option(new[] { "--reference", "-r" }, "Reference file(s) for compilation") { Argument = new Argument <string[]>() { Arity = arbitraryArity } }, new Option(new[] { "--outputfilepath", "--out", "-o" }, "Output file path") { Argument = new Argument <FileInfo>() }, new Option(new[] { "--optimize", "-O" }, "Enable optimizations") { Argument = new Argument <bool>() }, new Option(new[] { "--optimize-space", "--Os" }, "Enable optimizations, favor code space") { Argument = new Argument <bool>() }, new Option(new[] { "--optimize-time", "--Ot" }, "Enable optimizations, favor code speed"), new Option(new[] { "--inputbubble" }, "True when the entire input forms a version bubble (default = per-assembly bubble)"), new Option(new[] { "--tuning" }, "Generate IBC tuning image") { Argument = new Argument <bool>() }, new Option(new[] { "--partial" }, "Generate partial image driven by profile") { Argument = new Argument <bool>() }, new Option(new[] { "--compilebubblegenerics" }, "Compile instantiations from reference modules used in the current module") { Argument = new Argument <bool>() }, new Option(new[] { "--dgml-log-file-name", "--dmgllog" }, "Save result of dependency analysis as DGML") { Argument = new Argument <FileInfo>() }, new Option(new[] { "--generate-full-dmgl-log", "--fulllog" }, "Save detailed log of dependency analysis") { Argument = new Argument <bool>() }, new Option(new[] { "--verbose" }, "Enable verbose logging") { Argument = new Argument <bool>() }, new Option(new[] { "--systemmodule" }, "System module name (default: System.Private.CoreLib)") { Argument = new Argument <string>() }, new Option(new[] { "--waitfordebugger" }, "Pause to give opportunity to attach debugger") { Argument = new Argument <bool>() }, new Option(new[] { "--codegen-options", "--codegenopt" }, "Define a codegen option") { Argument = new Argument <string[]>() { Arity = arbitraryArity } }, new Option(new[] { "--resilient" }, "Disable behavior where unexpected compilation failures cause overall compilation failure") { Argument = new Argument <bool>() }, new Option(new[] { "--targetarch" }, "Target architecture for cross compilation") { Argument = new Argument <string>() }, new Option(new[] { "--targetos" }, "Target OS for cross compilation") { Argument = new Argument <string>() }, new Option(new[] { "--jitpath" }, "Path to JIT compiler library") { Argument = new Argument <string>() }, new Option(new[] { "--singlemethodtypename" }, "Single method compilation: name of the owning type") { Argument = new Argument <string>() }, new Option(new[] { "--singlemethodname" }, "Single method compilation: generic arguments to the method") { Argument = new Argument <string>() }, new Option(new[] { "--singlemethodgenericarg" }, "Single method compilation: generic arguments to the method") { // We don't need to override arity here as 255 is the maximum number of generic arguments Argument = new Argument <string[]>() }, new Option(new[] { "--parallelism" }, "Maximum number of threads to use during compilation") { Argument = new Argument <int>(() => Environment.ProcessorCount) }, new Option(new[] { "--map" }, "Generate the map file") { Argument = new Argument <bool>() }, }); }
internal virtual ArgumentConversionResult Convert( IArgument argument) { var parentResult = Parent; if (ShouldCheckArity() && ArgumentArity.Validate(parentResult, argument, argument.Arity.MinimumNumberOfValues, argument.Arity.MaximumNumberOfValues) is FailedArgumentConversionResult failedResult) { return(failedResult); } if (parentResult.UseDefaultValueFor(argument)) { var defaultValueFor = parentResult.GetDefaultValueFor(argument); return(ArgumentConversionResult.Success(argument, defaultValueFor)); } if (argument is Argument a && a.ConvertArguments != null) { if (ConversionResult != null) { return(ConversionResult); } var success = a.ConvertArguments(this, out var value); if (value is ArgumentConversionResult conversionResult) { return(conversionResult); } else if (success) { return(ArgumentConversionResult.Success(argument, value)); } else { return(ArgumentConversionResult.Failure(argument, ErrorMessage ?? $"Invalid: {parentResult.Token()} {string.Join(" ", parentResult.Tokens.Select(t => t.Value))}")); } } switch (argument.Arity.MaximumNumberOfValues) { case 0: return(ArgumentConversionResult.Success(argument, null)); case 1: return(ArgumentConversionResult.Success(argument, parentResult.Tokens.Select(t => t.Value).SingleOrDefault())); default: return(ArgumentConversionResult.Success(argument, parentResult.Tokens.Select(t => t.Value).ToArray())); } bool ShouldCheckArity() { return(!(parentResult is OptionResult optionResult && optionResult.IsImplicit)); } }