diff --git a/.editorconfig b/.editorconfig index 8aac2fc..01cb0e2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -22,6 +22,14 @@ dotnet_diagnostic.IDE0057.severity = none [*.cs] dotnet_diagnostic.IDE0290.severity = none +# SYSLIB1045: Use GeneratedRegexAttribute to generate the regular expression implementation at compile time +[*.cs] +dotnet_diagnostic.SYSLIB1045.severity = none + +# CA1019: Define accessors for attribute arguments +[*.cs] +dotnet_diagnostic.CA1019.severity = none + # CA1031: Do not catch general exception types [*.cs] dotnet_diagnostic.CA1031.severity = none @@ -41,3 +49,7 @@ dotnet_diagnostic.CA1707.severity = none # CA1813: Avoid unsealed attributes [*.cs] dotnet_diagnostic.CA1813.severity = none + +# CA2263: Prefer generic overload when type is known +[*.cs] +dotnet_diagnostic.CA2263.severity = none diff --git a/.ruleset b/.ruleset index 3c9087f..2cb73f6 100644 --- a/.ruleset +++ b/.ruleset @@ -35,7 +35,7 @@ - + @@ -55,7 +55,7 @@ - + @@ -77,7 +77,7 @@ - + @@ -135,7 +135,7 @@ - + @@ -159,7 +159,7 @@ - + diff --git a/Core/NetArgumentParser/ArgumentParser.cs b/Core/NetArgumentParser/ArgumentParser.cs index ab99834..b3d9a61 100644 --- a/Core/NetArgumentParser/ArgumentParser.cs +++ b/Core/NetArgumentParser/ArgumentParser.cs @@ -6,7 +6,7 @@ using NetArgumentParser.Options; using NetArgumentParser.Options.Collections; using NetArgumentParser.Options.Utils; -using NetArgumentParser.Options.Utils.Verifiers; +using NetArgumentParser.Options.Verifiers; using NetArgumentParser.Subcommands; using NetArgumentParser.Visitors; @@ -22,7 +22,9 @@ public class ArgumentParser : ParserQuantum public ArgumentParser( IDescriptionGenerator? descriptionGenerator = null, ITextWriter? outputWriter = null, - Func? subcommandDescriptionGeneratorCreator = null) + Func? subcommandDescriptionGeneratorCreator = null, + string name = nameof(ArgumentParser)) + : base(name ?? throw new ArgumentNullException(nameof(name))) { _mutuallyExclusiveOptionGroups = []; _programName = string.Empty; @@ -157,7 +159,8 @@ public virtual ParseArgumentsResult ParseKnownArguments( DynamicOptionInteractor.HandleDefaultValueBySuitableOptions(allOptions); ReuiredOptionVerifier.VerifyRequiredOptionsIsHandled(allOptions); - ResetOptionsHandledState(); + ResetOptionsHandledState(true); + ResetSubcommandsHandledState(true); return new ParseArgumentsResult(handledOptions, handledSubcommands); } diff --git a/Core/NetArgumentParser/Attributes/CannotCreateOptionException.cs b/Core/NetArgumentParser/Attributes/CannotCreateOptionException.cs index 53bb7c2..c0bb649 100644 --- a/Core/NetArgumentParser/Attributes/CannotCreateOptionException.cs +++ b/Core/NetArgumentParser/Attributes/CannotCreateOptionException.cs @@ -8,16 +8,17 @@ namespace NetArgumentParser.Generators; [Serializable] public class CannotCreateOptionException : Exception { - public CannotCreateOptionException() { } + public CannotCreateOptionException() + : this(GetDefaultMessage()) { } public CannotCreateOptionException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public CannotCreateOptionException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } public CannotCreateOptionException(string? message, PropertyInfo optionConfig) - : this(message, optionConfig, null) { } + : this(message ?? GetDefaultMessage(optionConfig), optionConfig, null) { } public CannotCreateOptionException( string? message, @@ -54,9 +55,12 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } - private static string GetDefaultMessage(PropertyInfo optionConfig) + private static string GetDefaultMessage(PropertyInfo? optionConfig = null) { - ExtendedArgumentNullException.ThrowIfNull(optionConfig, nameof(optionConfig)); - return $"Cannot create option using '{optionConfig.Name}' configuration."; + const string message = "Cannot create option"; + + return optionConfig is not null + ? $"{message} using '{optionConfig.Name}' configuration." + : $"{message}."; } } diff --git a/Core/NetArgumentParser/Attributes/EnumValueOptionAttribute.cs b/Core/NetArgumentParser/Attributes/EnumValueOptionAttribute.cs index 65cfe66..fe0cb98 100644 --- a/Core/NetArgumentParser/Attributes/EnumValueOptionAttribute.cs +++ b/Core/NetArgumentParser/Attributes/EnumValueOptionAttribute.cs @@ -14,7 +14,6 @@ namespace NetArgumentParser.Attributes; public class EnumValueOptionAttribute : ValueOptionAttribute where T : struct, Enum { -#pragma warning disable CA1019 // Define accessors for attribute arguments public EnumValueOptionAttribute( T defaultValue, string longName, @@ -53,7 +52,6 @@ public EnumValueOptionAttribute( { UseDefaultChoices = useDefaultChoices; } -#pragma warning restore CA1019 // Define accessors for attribute arguments public EnumValueOptionAttribute( string longName, diff --git a/Core/NetArgumentParser/Attributes/MultipleValueOptionAttribute.cs b/Core/NetArgumentParser/Attributes/MultipleValueOptionAttribute.cs index b8e2e1b..cc388f7 100644 --- a/Core/NetArgumentParser/Attributes/MultipleValueOptionAttribute.cs +++ b/Core/NetArgumentParser/Attributes/MultipleValueOptionAttribute.cs @@ -15,7 +15,6 @@ namespace NetArgumentParser.Attributes; ] public class MultipleValueOptionAttribute : ValueOptionAttribute> { -#pragma warning disable CA1019 // Define accessors for attribute arguments public MultipleValueOptionAttribute( T[] defaultValue, string longName, @@ -85,7 +84,6 @@ public MultipleValueOptionAttribute( ContextCapture = CreateContextCapture(contextCaptureType, numberOfItemsToCapture); ValueRestriction = CreateValueRestriction(valueRestriction); } -#pragma warning restore CA1019 // Define accessors for attribute arguments public bool IgnoreOrderInChoices { get; } public IContextCapture? ContextCapture { get; } diff --git a/Core/NetArgumentParser/Attributes/ValueOptionAttribute.cs b/Core/NetArgumentParser/Attributes/ValueOptionAttribute.cs index c48413d..fd67674 100644 --- a/Core/NetArgumentParser/Attributes/ValueOptionAttribute.cs +++ b/Core/NetArgumentParser/Attributes/ValueOptionAttribute.cs @@ -15,7 +15,6 @@ namespace NetArgumentParser.Attributes; ] public class ValueOptionAttribute : CommonOptionAttribute { -#pragma warning disable CA1019 // Define accessors for attribute arguments public ValueOptionAttribute( T defaultValue, string longName, @@ -52,7 +51,6 @@ public ValueOptionAttribute( { DefaultValue = new DefaultOptionValue(defaultValue); } -#pragma warning restore CA1019 // Define accessors for attribute arguments public ValueOptionAttribute( string longName, diff --git a/Core/NetArgumentParser/Converters/DefaultConverterNotFoundException.cs b/Core/NetArgumentParser/Converters/DefaultConverterNotFoundException.cs index f201d82..4ecdd24 100644 --- a/Core/NetArgumentParser/Converters/DefaultConverterNotFoundException.cs +++ b/Core/NetArgumentParser/Converters/DefaultConverterNotFoundException.cs @@ -7,16 +7,17 @@ namespace NetArgumentParser.Converters; [Serializable] public class DefaultConverterNotFoundException : Exception { - public DefaultConverterNotFoundException() { } + public DefaultConverterNotFoundException() + : this(GetDefaultMessage()) { } public DefaultConverterNotFoundException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public DefaultConverterNotFoundException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } public DefaultConverterNotFoundException(string? message, Type outputType) - : this(message, outputType, null) { } + : this(message ?? GetDefaultMessage(outputType), outputType, null) { } public DefaultConverterNotFoundException( string? message, @@ -53,9 +54,12 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } - private static string GetDefaultMessage(Type outputType) + private static string GetDefaultMessage(Type? outputType = null) { - ExtendedArgumentNullException.ThrowIfNull(outputType, nameof(outputType)); - return $"Default converter for type '{outputType.Name}' not found."; + string outputTypePresenter = outputType is not null + ? $" for type '{outputType.Name}'" + : string.Empty; + + return $"Default converter{outputTypePresenter} not found."; } } diff --git a/Core/NetArgumentParser/Converters/EnumValueConverter.cs b/Core/NetArgumentParser/Converters/EnumValueConverter.cs index c0e2fbe..2b8fd17 100644 --- a/Core/NetArgumentParser/Converters/EnumValueConverter.cs +++ b/Core/NetArgumentParser/Converters/EnumValueConverter.cs @@ -5,8 +5,6 @@ namespace NetArgumentParser.Converters; public class EnumValueConverter : ValueConverter where T : struct, Enum { -#pragma warning disable CA2263 // Prefer generic overload when type is known public EnumValueConverter(bool ignoreCase = true) : base(t => (T)Enum.Parse(typeof(T), t, ignoreCase)) { } -#pragma warning restore CA2263 // Prefer generic overload when type is known } diff --git a/Core/NetArgumentParser/Generators/NullSubcommandConfigException.cs b/Core/NetArgumentParser/Generators/NullSubcommandConfigException.cs index cfaad58..bc649c5 100644 --- a/Core/NetArgumentParser/Generators/NullSubcommandConfigException.cs +++ b/Core/NetArgumentParser/Generators/NullSubcommandConfigException.cs @@ -8,16 +8,17 @@ namespace NetArgumentParser.Generators; [Serializable] public class NullSubcommandConfigException : Exception { - public NullSubcommandConfigException() { } + public NullSubcommandConfigException() + : this(GetDefaultMessage()) { } public NullSubcommandConfigException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public NullSubcommandConfigException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } public NullSubcommandConfigException(string? message, PropertyInfo subcommandConfig) - : this(message, subcommandConfig, null) { } + : this(message ?? GetDefaultMessage(subcommandConfig), subcommandConfig, null) { } public NullSubcommandConfigException( string? message, @@ -57,9 +58,12 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } - private static string GetDefaultMessage(PropertyInfo subcommandConfig) + private static string GetDefaultMessage(PropertyInfo? subcommandConfig = null) { - ExtendedArgumentNullException.ThrowIfNull(subcommandConfig, nameof(subcommandConfig)); - return $"Subcommand configuration '{subcommandConfig.Name}' is null."; + string subcommandConfigPresenter = subcommandConfig is not null + ? $" '{subcommandConfig.Name}'" + : string.Empty; + + return $"Subcommand configuration{subcommandConfigPresenter} is null."; } } diff --git a/Core/NetArgumentParser/Generators/UnsupportedOptionConfigException.cs b/Core/NetArgumentParser/Generators/UnsupportedOptionConfigException.cs index 25bfff3..c90275a 100644 --- a/Core/NetArgumentParser/Generators/UnsupportedOptionConfigException.cs +++ b/Core/NetArgumentParser/Generators/UnsupportedOptionConfigException.cs @@ -8,16 +8,17 @@ namespace NetArgumentParser.Generators; [Serializable] public class UnsupportedOptionConfigException : Exception { - public UnsupportedOptionConfigException() { } + public UnsupportedOptionConfigException() + : this(GetDefaultMessage()) { } public UnsupportedOptionConfigException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public UnsupportedOptionConfigException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } public UnsupportedOptionConfigException(string? message, PropertyInfo optionConfig) - : this(message, optionConfig, null) { } + : this(message ?? GetDefaultMessage(optionConfig), optionConfig, null) { } public UnsupportedOptionConfigException( string? message, @@ -54,9 +55,12 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } - private static string GetDefaultMessage(PropertyInfo optionConfig) + private static string GetDefaultMessage(PropertyInfo? optionConfig = null) { - ExtendedArgumentNullException.ThrowIfNull(optionConfig, nameof(optionConfig)); - return $"Option configuration '{optionConfig.Name}' isn't supported."; + string optionConfigPresenter = optionConfig is not null + ? $" '{optionConfig.Name}'" + : string.Empty; + + return $"Option configuration{optionConfigPresenter} isn't supported."; } } diff --git a/Core/NetArgumentParser/Generators/UnsupportedParserConfigException.cs b/Core/NetArgumentParser/Generators/UnsupportedParserConfigException.cs index 42cdf68..f3ed93a 100644 --- a/Core/NetArgumentParser/Generators/UnsupportedParserConfigException.cs +++ b/Core/NetArgumentParser/Generators/UnsupportedParserConfigException.cs @@ -8,16 +8,17 @@ namespace NetArgumentParser.Generators; [Serializable] public class UnsupportedParserConfigException : Exception { - public UnsupportedParserConfigException() { } + public UnsupportedParserConfigException() + : this(GetDefaultMessage()) { } public UnsupportedParserConfigException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public UnsupportedParserConfigException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } public UnsupportedParserConfigException(string? message, object config) - : this(message, config, null) { } + : this(message ?? GetDefaultMessage(config), config, null) { } public UnsupportedParserConfigException( string? message, @@ -54,14 +55,19 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } - private static string GetDefaultMessage(object config) + private static string GetDefaultMessage(object? config = null) { - ExtendedArgumentNullException.ThrowIfNull(config, nameof(config)); - - string? configObjectName = config.GetType().FullName; + string? configObjectName = config?.GetType().FullName; string? necessaryAttributeName = typeof(ParserConfigAttribute).FullName; - return $"Config '{configObjectName}' isn't supported. " + - $"It must be marked by {necessaryAttributeName} attribute."; + string configObjectNamePresenter = !string.IsNullOrEmpty(configObjectName) + ? $" '{configObjectName}'" + : string.Empty; + + string message = $"Config{configObjectNamePresenter} isn't supported."; + + return !string.IsNullOrEmpty(necessaryAttributeName) + ? $"{message} It must be marked by {necessaryAttributeName} attribute." + : message; } } diff --git a/Core/NetArgumentParser/NetArgumentParser.csproj b/Core/NetArgumentParser/NetArgumentParser.csproj index 9897e8d..f75765a 100644 --- a/Core/NetArgumentParser/NetArgumentParser.csproj +++ b/Core/NetArgumentParser/NetArgumentParser.csproj @@ -2,12 +2,12 @@ NetArgumentParser - 1.0.7 + 1.0.8 NetArgumentParser NetArgumentParser yakovypg yakovypg - Copyright © yakovypg 2025 + Copyright © yakovypg 2024–2026 cli;options;args;command-line;argument-parser;arguments;cli-args;argument-parsing;subcommands;argparse;command-line-parser;flags;cli-parser;command-line-arguments;cli-arguments;net-argparse;csharp-argparse;subcommand-parser NetArgumentParser is a cross-platform, free and open source library for parsing command-line options, arguments and subcommands. It contains the main features of popular argument parsers such as argparse, as well as many of its own. https://github.com/yakovypg/NetArgumentParser @@ -15,7 +15,7 @@ git README.md LICENSE - + true true diff --git a/Core/NetArgumentParser/Options/ArgumentValueNotRecognizedException.cs b/Core/NetArgumentParser/Options/ArgumentValueNotRecognizedException.cs index 617b9b7..c6cc10c 100644 --- a/Core/NetArgumentParser/Options/ArgumentValueNotRecognizedException.cs +++ b/Core/NetArgumentParser/Options/ArgumentValueNotRecognizedException.cs @@ -7,16 +7,17 @@ namespace NetArgumentParser.Options; [Serializable] public class ArgumentValueNotRecognizedException : Exception { - public ArgumentValueNotRecognizedException() { } + public ArgumentValueNotRecognizedException() + : this(GetDefaultMessage()) { } public ArgumentValueNotRecognizedException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public ArgumentValueNotRecognizedException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } public ArgumentValueNotRecognizedException(string? message, string argument) - : this(message, argument, null) { } + : this(message ?? GetDefaultMessage(argument), argument, null) { } public ArgumentValueNotRecognizedException( string? message, @@ -53,9 +54,11 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } - private static string GetDefaultMessage(string argument) + private static string GetDefaultMessage(string? argument = null) { - ExtendedArgumentNullException.ThrowIfNull(argument, nameof(argument)); - return $"Value of the argument {argument} not recognized."; + if (!string.IsNullOrEmpty(argument)) + argument = $" {argument}"; + + return $"Value of the argument{argument} not recognized."; } } diff --git a/Core/NetArgumentParser/Options/ArgumentValueNotSpecifiedException.cs b/Core/NetArgumentParser/Options/ArgumentValueNotSpecifiedException.cs index c7e1947..1ac88cc 100644 --- a/Core/NetArgumentParser/Options/ArgumentValueNotSpecifiedException.cs +++ b/Core/NetArgumentParser/Options/ArgumentValueNotSpecifiedException.cs @@ -7,16 +7,17 @@ namespace NetArgumentParser.Options; [Serializable] public class ArgumentValueNotSpecifiedException : Exception { - public ArgumentValueNotSpecifiedException() { } + public ArgumentValueNotSpecifiedException() + : this(GetDefaultMessage()) { } public ArgumentValueNotSpecifiedException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public ArgumentValueNotSpecifiedException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } public ArgumentValueNotSpecifiedException(string? message, string argument) - : this(message, argument, null) { } + : this(message ?? GetDefaultMessage(argument), argument, null) { } public ArgumentValueNotSpecifiedException( string? message, @@ -53,9 +54,11 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } - private static string GetDefaultMessage(string argument) + private static string GetDefaultMessage(string? argument = null) { - ExtendedArgumentNullException.ThrowIfNull(argument, nameof(argument)); - return $"Argument {argument} does not have value."; + if (!string.IsNullOrEmpty(argument)) + argument = $" {argument}"; + + return $"Argument{argument} does not have value."; } } diff --git a/Core/NetArgumentParser/Options/ArgumentsAreUnknownException.cs b/Core/NetArgumentParser/Options/ArgumentsAreUnknownException.cs index 0dfbafc..bab0290 100644 --- a/Core/NetArgumentParser/Options/ArgumentsAreUnknownException.cs +++ b/Core/NetArgumentParser/Options/ArgumentsAreUnknownException.cs @@ -10,16 +10,17 @@ public class ArgumentsAreUnknownException : Exception { private readonly string[]? _arguments; - public ArgumentsAreUnknownException() { } + public ArgumentsAreUnknownException() + : this(GetDefaultMessage()) { } public ArgumentsAreUnknownException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public ArgumentsAreUnknownException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } public ArgumentsAreUnknownException(string? message, string[] arguments) - : this(message, arguments, null) { } + : this(message ?? GetDefaultMessage(arguments), arguments, null) { } public ArgumentsAreUnknownException( string? message, @@ -56,11 +57,12 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } - private static string GetDefaultMessage(string[] arguments) + private static string GetDefaultMessage(string[]? arguments = null) { - ExtendedArgumentNullException.ThrowIfNull(arguments, nameof(arguments)); + string argumentsPresenter = arguments is not null + ? $" {string.Join(", ", arguments)}" + : string.Empty; - string argumentsPresenter = string.Join(" ", arguments); - return $"Arguments {argumentsPresenter} are unknown."; + return $"Arguments{argumentsPresenter} are unknown."; } } diff --git a/Core/NetArgumentParser/Options/ChoicesAlreadyAddedToDescriptionException.cs b/Core/NetArgumentParser/Options/ChoicesAlreadyAddedToDescriptionException.cs index 0703a0b..a0f9528 100644 --- a/Core/NetArgumentParser/Options/ChoicesAlreadyAddedToDescriptionException.cs +++ b/Core/NetArgumentParser/Options/ChoicesAlreadyAddedToDescriptionException.cs @@ -7,10 +7,11 @@ namespace NetArgumentParser.Options; [Serializable] public class ChoicesAlreadyAddedToDescriptionException : Exception { - public ChoicesAlreadyAddedToDescriptionException() { } + public ChoicesAlreadyAddedToDescriptionException() + : this(GetDefaultMessage()) { } public ChoicesAlreadyAddedToDescriptionException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public ChoicesAlreadyAddedToDescriptionException(string? message, Exception? innerException) : base(message ?? GetDefaultMessage(), innerException) { } diff --git a/Core/NetArgumentParser/Options/Collections/OptionSet.cs b/Core/NetArgumentParser/Options/Collections/OptionSet.cs index 0556204..e28c5a2 100644 --- a/Core/NetArgumentParser/Options/Collections/OptionSet.cs +++ b/Core/NetArgumentParser/Options/Collections/OptionSet.cs @@ -3,7 +3,7 @@ using System.Linq; using NetArgumentParser.Converters; using NetArgumentParser.Options.Utils; -using NetArgumentParser.Options.Utils.Verifiers; +using NetArgumentParser.Options.Verifiers; namespace NetArgumentParser.Options.Collections; diff --git a/Core/NetArgumentParser/Options/CommonOption.cs b/Core/NetArgumentParser/Options/CommonOption.cs index 38696f7..be187c6 100644 --- a/Core/NetArgumentParser/Options/CommonOption.cs +++ b/Core/NetArgumentParser/Options/CommonOption.cs @@ -3,7 +3,7 @@ using System.Linq; using NetArgumentParser.Configuration; using NetArgumentParser.Options.Context; -using NetArgumentParser.Options.Utils.Verifiers; +using NetArgumentParser.Options.Verifiers; namespace NetArgumentParser.Options; diff --git a/Core/NetArgumentParser/Options/Context/ContextCaptureNotRecognizedException.cs b/Core/NetArgumentParser/Options/Context/ContextCaptureNotRecognizedException.cs index f909bbb..5455058 100644 --- a/Core/NetArgumentParser/Options/Context/ContextCaptureNotRecognizedException.cs +++ b/Core/NetArgumentParser/Options/Context/ContextCaptureNotRecognizedException.cs @@ -8,16 +8,17 @@ namespace NetArgumentParser.Options.Context; [Serializable] public class ContextCaptureNotRecognizedException : Exception { - public ContextCaptureNotRecognizedException() { } + public ContextCaptureNotRecognizedException() + : this(GetDefaultMessage()) { } public ContextCaptureNotRecognizedException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public ContextCaptureNotRecognizedException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } public ContextCaptureNotRecognizedException(string? message, double minValue, double maxValue) - : this(message, minValue, maxValue, null) { } + : this(message ?? GetDefaultMessage(minValue, maxValue), minValue, maxValue, null) { } public ContextCaptureNotRecognizedException( string? message, @@ -60,8 +61,15 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } + private static string GetDefaultMessage(bool addDot = true) + { + const string message = "Failed to recognize context capture"; + return addDot ? $"{message}." : message; + } + private static string GetDefaultMessage(double minValue, double maxValue) { - return $"Failed to recognize context capture from '{(minValue, maxValue)}' tuple."; + string message = GetDefaultMessage(false); + return $"{message} from '{(minValue, maxValue)}' tuple."; } } diff --git a/Core/NetArgumentParser/Options/DefaultValueAlreadyAddedToDescriptionException.cs b/Core/NetArgumentParser/Options/DefaultValueAlreadyAddedToDescriptionException.cs index 8becdf0..83052e2 100644 --- a/Core/NetArgumentParser/Options/DefaultValueAlreadyAddedToDescriptionException.cs +++ b/Core/NetArgumentParser/Options/DefaultValueAlreadyAddedToDescriptionException.cs @@ -7,10 +7,11 @@ namespace NetArgumentParser.Options; [Serializable] public class DefaultValueAlreadyAddedToDescriptionException : Exception { - public DefaultValueAlreadyAddedToDescriptionException() { } + public DefaultValueAlreadyAddedToDescriptionException() + : this(GetDefaultMessage()) { } public DefaultValueAlreadyAddedToDescriptionException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public DefaultValueAlreadyAddedToDescriptionException(string? message, Exception? innerException) : base(message ?? GetDefaultMessage(), innerException) { } diff --git a/Core/NetArgumentParser/Options/DefaultValueNotSpecifiedException.cs b/Core/NetArgumentParser/Options/DefaultValueNotSpecifiedException.cs index 92b31b6..64b86d0 100644 --- a/Core/NetArgumentParser/Options/DefaultValueNotSpecifiedException.cs +++ b/Core/NetArgumentParser/Options/DefaultValueNotSpecifiedException.cs @@ -7,16 +7,17 @@ namespace NetArgumentParser.Options; [Serializable] public class DefaultValueNotSpecifiedException : Exception { - public DefaultValueNotSpecifiedException() { } + public DefaultValueNotSpecifiedException() + : this(GetDefaultMessage()) { } public DefaultValueNotSpecifiedException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public DefaultValueNotSpecifiedException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } public DefaultValueNotSpecifiedException(string? message, ICommonOption option) - : this(message, option, null) { } + : this(message ?? GetDefaultMessage(option), option, null) { } public DefaultValueNotSpecifiedException( string? message, @@ -53,9 +54,12 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } - private static string GetDefaultMessage(ICommonOption option) + private static string GetDefaultMessage(ICommonOption? option = null) { - ExtendedArgumentNullException.ThrowIfNull(option, nameof(option)); - return $"Default value isn't specified for option '{option}'."; + string optionPresenter = option is not null + ? $" '{option}'" + : string.Empty; + + return $"Default value isn't specified for option{optionPresenter}."; } } diff --git a/Core/NetArgumentParser/Options/EnumValueOption.cs b/Core/NetArgumentParser/Options/EnumValueOption.cs index e062f4f..9851a67 100644 --- a/Core/NetArgumentParser/Options/EnumValueOption.cs +++ b/Core/NetArgumentParser/Options/EnumValueOption.cs @@ -10,8 +10,6 @@ namespace NetArgumentParser.Options; public class EnumValueOption : ValueOption where T : struct, Enum { -#pragma warning disable SA1118 // Parameter should not span multiple lines -#pragma warning disable CA2263 // Prefer generic overload when type is known public EnumValueOption( string longName, string shortName = "", @@ -50,8 +48,6 @@ public EnumValueOption( new FixedContextCapture(1)) { } -#pragma warning restore CA2263 // Prefer generic overload when type is known -#pragma warning restore SA1118 // Parameter should not span multiple lines protected override IValueConverter GetDefaultConverter() { diff --git a/Core/NetArgumentParser/Options/IOptionConfigurationProvider.cs b/Core/NetArgumentParser/Options/IOptionConfigurationProvider.cs new file mode 100644 index 0000000..c705cae --- /dev/null +++ b/Core/NetArgumentParser/Options/IOptionConfigurationProvider.cs @@ -0,0 +1,8 @@ +using NetArgumentParser.Subcommands; + +namespace NetArgumentParser.Options; + +public interface IOptionConfigurationProvider +{ + void ConfigureOptions(ParserQuantum subcommand); +} diff --git a/Core/NetArgumentParser/Options/IOptionConfigurationSetter.cs b/Core/NetArgumentParser/Options/IOptionConfigurationSetter.cs new file mode 100644 index 0000000..a675fd4 --- /dev/null +++ b/Core/NetArgumentParser/Options/IOptionConfigurationSetter.cs @@ -0,0 +1,6 @@ +namespace NetArgumentParser.Options; + +public interface IOptionConfigurationSetter +{ + void SetOptionConfigurations(ArgumentParser parser); +} diff --git a/Core/NetArgumentParser/Options/IncorrectOptionNameException.cs b/Core/NetArgumentParser/Options/IncorrectOptionNameException.cs index d3f6931..45c393a 100644 --- a/Core/NetArgumentParser/Options/IncorrectOptionNameException.cs +++ b/Core/NetArgumentParser/Options/IncorrectOptionNameException.cs @@ -7,16 +7,17 @@ namespace NetArgumentParser.Options; [Serializable] public class IncorrectOptionNameException : Exception { - public IncorrectOptionNameException() { } + public IncorrectOptionNameException() + : this(GetDefaultMessage()) { } public IncorrectOptionNameException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public IncorrectOptionNameException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } public IncorrectOptionNameException(string? message, string optionName) - : this(message, optionName, null) { } + : this(message ?? GetDefaultMessage(optionName), optionName, null) { } public IncorrectOptionNameException( string? message, @@ -53,9 +54,11 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } - private static string GetDefaultMessage(string optionName) + private static string GetDefaultMessage(string? optionName = null) { - ExtendedArgumentNullException.ThrowIfNull(optionName, nameof(optionName)); - return $"Option name '{optionName}' is not correct."; + if (!string.IsNullOrEmpty(optionName)) + optionName = $" {optionName}"; + + return $"Option name'{optionName}' is not correct."; } } diff --git a/Core/NetArgumentParser/Options/MutuallyExclusiveOptionsFoundException.cs b/Core/NetArgumentParser/Options/MutuallyExclusiveOptionsFoundException.cs index cacd458..6ac2d1d 100644 --- a/Core/NetArgumentParser/Options/MutuallyExclusiveOptionsFoundException.cs +++ b/Core/NetArgumentParser/Options/MutuallyExclusiveOptionsFoundException.cs @@ -7,19 +7,20 @@ namespace NetArgumentParser.Options; [Serializable] public class MutuallyExclusiveOptionsFoundException : Exception { - public MutuallyExclusiveOptionsFoundException() { } + public MutuallyExclusiveOptionsFoundException() + : this(GetDefaultMessage()) { } public MutuallyExclusiveOptionsFoundException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public MutuallyExclusiveOptionsFoundException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } public MutuallyExclusiveOptionsFoundException( string? message, ICommonOption newOption, ICommonOption existingOption) - : this(message, newOption, existingOption, null) { } + : this(message ?? GetDefaultMessage(newOption, existingOption), newOption, existingOption, null) { } public MutuallyExclusiveOptionsFoundException( string? message, @@ -64,11 +65,18 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } - private static string GetDefaultMessage(ICommonOption newOption, ICommonOption existingOption) + private static string GetDefaultMessage( + ICommonOption? newOption = null, + ICommonOption? existingOption = null) { - ExtendedArgumentNullException.ThrowIfNull(newOption, nameof(newOption)); - ExtendedArgumentNullException.ThrowIfNull(existingOption, nameof(existingOption)); + string newOptionPresenter = newOption is not null + ? $"Option '{newOption}'" + : "Some option"; + + string existingOptionPresenter = existingOption is not null + ? $"option '{existingOption}'" + : "other option"; - return $"Option '{newOption}' not allowed with option '{existingOption}'."; + return $"{newOptionPresenter} not allowed with {existingOptionPresenter}."; } } diff --git a/Core/NetArgumentParser/Options/NotEnoughValuesInContextException.cs b/Core/NetArgumentParser/Options/NotEnoughValuesInContextException.cs index 5f6571a..e9d14c9 100644 --- a/Core/NetArgumentParser/Options/NotEnoughValuesInContextException.cs +++ b/Core/NetArgumentParser/Options/NotEnoughValuesInContextException.cs @@ -10,26 +10,27 @@ public class NotEnoughValuesInContextException : Exception { private readonly string[]? _context; - public NotEnoughValuesInContextException() { } + public NotEnoughValuesInContextException() + : this(GetDefaultMessage()) { } public NotEnoughValuesInContextException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public NotEnoughValuesInContextException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } public NotEnoughValuesInContextException( string? message, string[] context, int numberOfNecessaryValues) - : this(message, context, numberOfNecessaryValues, null) { } + : this(message ?? GetDefaultMessage(context), context, numberOfNecessaryValues, null) { } public NotEnoughValuesInContextException( string? message, string[] context, int numberOfNecessaryValues, Exception? innerException) - : base(message ?? GetDefaultMessage(), innerException) + : base(message ?? GetDefaultMessage(context), innerException) { ExtendedArgumentNullException.ThrowIfNull(context, nameof(context)); @@ -67,8 +68,12 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } - private static string GetDefaultMessage() + private static string GetDefaultMessage(string[]? context = null) { - return "There are not enough values in the context."; + const string message = "There are not enough values in the context"; + + return context is not null + ? $"{message}: {string.Join(" ", context)}" + : $"{message}."; } } diff --git a/Core/NetArgumentParser/Options/OnlyUniqueConversionTypeException.cs b/Core/NetArgumentParser/Options/OnlyUniqueConversionTypeException.cs index 4c8d4e0..f587897 100644 --- a/Core/NetArgumentParser/Options/OnlyUniqueConversionTypeException.cs +++ b/Core/NetArgumentParser/Options/OnlyUniqueConversionTypeException.cs @@ -7,16 +7,17 @@ namespace NetArgumentParser.Options; [Serializable] public class OnlyUniqueConversionTypeException : Exception { - public OnlyUniqueConversionTypeException() { } + public OnlyUniqueConversionTypeException() + : this(GetDefaultMessage()) { } public OnlyUniqueConversionTypeException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public OnlyUniqueConversionTypeException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } - public OnlyUniqueConversionTypeException(string? message, Type outputType) - : this(message, outputType, null) { } + public OnlyUniqueConversionTypeException(string? message, Type conversionType) + : this(message ?? GetDefaultMessage(conversionType), conversionType, null) { } public OnlyUniqueConversionTypeException( string? message, @@ -53,9 +54,12 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } - private static string GetDefaultMessage(Type conversionType) + private static string GetDefaultMessage(Type? conversionType = null) { - ExtendedArgumentNullException.ThrowIfNull(conversionType, nameof(conversionType)); - return $"Conversion type '{conversionType.Name}' is already in use."; + string conversionTypePresenter = conversionType is not null + ? $" '{conversionType.Name}'" + : string.Empty; + + return $"Conversion type{conversionTypePresenter} is already in use."; } } diff --git a/Core/NetArgumentParser/Options/OnlyUniqueOptionNameException.cs b/Core/NetArgumentParser/Options/OnlyUniqueOptionNameException.cs index 46a0004..1d16f83 100644 --- a/Core/NetArgumentParser/Options/OnlyUniqueOptionNameException.cs +++ b/Core/NetArgumentParser/Options/OnlyUniqueOptionNameException.cs @@ -7,16 +7,17 @@ namespace NetArgumentParser.Options; [Serializable] public class OnlyUniqueOptionNameException : Exception { - public OnlyUniqueOptionNameException() { } + public OnlyUniqueOptionNameException() + : this(GetDefaultMessage()) { } public OnlyUniqueOptionNameException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public OnlyUniqueOptionNameException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } public OnlyUniqueOptionNameException(string? message, string optionName) - : this(message, optionName, null) { } + : this(message ?? GetDefaultMessage(optionName), optionName, null) { } public OnlyUniqueOptionNameException( string? message, @@ -53,9 +54,11 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } - private static string GetDefaultMessage(string optionName) + private static string GetDefaultMessage(string? optionName = null) { - ExtendedArgumentNullException.ThrowIfNull(optionName, nameof(optionName)); - return $"Option name '{optionName}' is already in use."; + if (!string.IsNullOrEmpty(optionName)) + optionName = $" '{optionName}'"; + + return $"Option name{optionName} is already in use."; } } diff --git a/Core/NetArgumentParser/Options/OptionAlreadyHandledException.cs b/Core/NetArgumentParser/Options/OptionAlreadyHandledException.cs index 8b5539a..96acb5a 100644 --- a/Core/NetArgumentParser/Options/OptionAlreadyHandledException.cs +++ b/Core/NetArgumentParser/Options/OptionAlreadyHandledException.cs @@ -7,16 +7,17 @@ namespace NetArgumentParser.Options; [Serializable] public class OptionAlreadyHandledException : Exception { - public OptionAlreadyHandledException() { } + public OptionAlreadyHandledException() + : this(GetDefaultMessage()) { } public OptionAlreadyHandledException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public OptionAlreadyHandledException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } public OptionAlreadyHandledException(string? message, ICommonOption option) - : this(message, option, null) { } + : this(message ?? GetDefaultMessage(option), option, null) { } public OptionAlreadyHandledException( string? message, @@ -53,9 +54,12 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } - private static string GetDefaultMessage(ICommonOption option) + private static string GetDefaultMessage(ICommonOption? option = null) { - ExtendedArgumentNullException.ThrowIfNull(option, nameof(option)); - return $"Option '{option}' has already been handled."; + string optionPresenter = option is not null + ? $" '{option}'" + : string.Empty; + + return $"Option{optionPresenter} has already been handled."; } } diff --git a/Core/NetArgumentParser/Options/OptionConfigurationProvider.cs b/Core/NetArgumentParser/Options/OptionConfigurationProvider.cs new file mode 100644 index 0000000..f1ee199 --- /dev/null +++ b/Core/NetArgumentParser/Options/OptionConfigurationProvider.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using NetArgumentParser.Subcommands; + +namespace NetArgumentParser.Options; + +public abstract class OptionConfigurationProvider : IOptionConfigurationProvider +{ + protected abstract IReadOnlyCollection> ConfigurationProviders { get; } + + public virtual void ConfigureOptions(ParserQuantum subcommand) + { + ExtendedArgumentNullException.ThrowIfNull(subcommand, nameof(subcommand)); + + foreach (Action configureAction in ConfigurationProviders) + { + configureAction.Invoke(subcommand); + } + } + + protected static IValueOption FindValueOption(ParserQuantum parserQuantum, string optionLongName) + { + ExtendedArgumentNullException.ThrowIfNull(parserQuantum, nameof(parserQuantum)); + ExtendedArgumentNullException.ThrowIfNull(optionLongName, nameof(optionLongName)); + + bool found = parserQuantum.FindFirstValueOptionByLongName( + optionLongName, + false, + out IValueOption? foundOption); + + return found && foundOption is not null + ? foundOption + : throw new ParserQuantumConfiguredIncorrectlyException(null, parserQuantum.Name); + } + + protected static IValueOption> FindMultipleValueOption(ParserQuantum parserQuantum, string optionLongName) + { + ExtendedArgumentNullException.ThrowIfNull(parserQuantum, nameof(parserQuantum)); + ExtendedArgumentNullException.ThrowIfNull(optionLongName, nameof(optionLongName)); + + return FindValueOption>(parserQuantum, optionLongName); + } +} diff --git a/Core/NetArgumentParser/Options/OptionConfigurationSetter.cs b/Core/NetArgumentParser/Options/OptionConfigurationSetter.cs new file mode 100644 index 0000000..17dbf25 --- /dev/null +++ b/Core/NetArgumentParser/Options/OptionConfigurationSetter.cs @@ -0,0 +1,51 @@ +using System.Collections.Generic; +using System.Linq; +using NetArgumentParser.Subcommands; + +namespace NetArgumentParser.Options; + +public class OptionConfigurationSetter : IOptionConfigurationSetter +{ + public OptionConfigurationSetter( + IReadOnlyDictionary optionConfigurationProviders) + { + ExtendedArgumentNullException.ThrowIfNull(optionConfigurationProviders, nameof(optionConfigurationProviders)); + + OptionConfigurationProviders = optionConfigurationProviders.ToDictionary( + t => t.Key, + t => new List() { t.Value }); + } + + public OptionConfigurationSetter( + IReadOnlyDictionary> optionConfigurationProviders) + { + ExtendedArgumentNullException.ThrowIfNull(optionConfigurationProviders, nameof(optionConfigurationProviders)); + OptionConfigurationProviders = optionConfigurationProviders; + } + + public IReadOnlyDictionary> OptionConfigurationProviders { get; } + + public void SetOptionConfigurations(ArgumentParser parser) + { + ExtendedArgumentNullException.ThrowIfNull(parser, nameof(parser)); + + IEnumerable parserQuantums = parser.Subcommands + .Cast() + .Concat([parser]); + + foreach (ParserQuantum parserQuantum in parserQuantums) + { + bool hasConfigurationProviders = OptionConfigurationProviders.TryGetValue( + parserQuantum.Name, + out List? configurationProviders); + + if (!hasConfigurationProviders || configurationProviders is null) + continue; + + foreach (IOptionConfigurationProvider configurationProvider in configurationProviders) + { + configurationProvider.ConfigureOptions(parserQuantum); + } + } + } +} diff --git a/Core/NetArgumentParser/Options/OptionDefaultValueProvider.cs b/Core/NetArgumentParser/Options/OptionDefaultValueProvider.cs new file mode 100644 index 0000000..3b453b9 --- /dev/null +++ b/Core/NetArgumentParser/Options/OptionDefaultValueProvider.cs @@ -0,0 +1,55 @@ +using System.Collections.Generic; +using NetArgumentParser.Options.Configuration; +using NetArgumentParser.Subcommands; + +namespace NetArgumentParser.Options; + +public abstract class OptionDefaultValueProvider : OptionConfigurationProvider +{ + protected static void AddDefaultValue( + ParserQuantum parserQuantum, + string optionLongName, + T defaultValue) + { + ExtendedArgumentNullException.ThrowIfNull(parserQuantum, nameof(parserQuantum)); + ExtendedArgumentNullException.ThrowIfNull(optionLongName, nameof(optionLongName)); + + AddDefaultValue(parserQuantum, optionLongName, new DefaultOptionValue(defaultValue)); + } + + protected static void AddDefaultValue( + ParserQuantum parserQuantum, + string optionLongName, + DefaultOptionValue defaultValue) + { + ExtendedArgumentNullException.ThrowIfNull(parserQuantum, nameof(parserQuantum)); + ExtendedArgumentNullException.ThrowIfNull(optionLongName, nameof(optionLongName)); + ExtendedArgumentNullException.ThrowIfNull(defaultValue, nameof(defaultValue)); + + IValueOption foundOption = FindValueOption(parserQuantum, optionLongName); + foundOption.DefaultValue = defaultValue; + } + + protected static void AddDefaultValueToMultipleValueOption( + ParserQuantum parserQuantum, + string optionLongName, + IList defaultValue) + { + ExtendedArgumentNullException.ThrowIfNull(parserQuantum, nameof(parserQuantum)); + ExtendedArgumentNullException.ThrowIfNull(optionLongName, nameof(optionLongName)); + + AddDefaultValue(parserQuantum, optionLongName, defaultValue); + } + + protected static void AddDefaultValueToMultipleValueOption( + ParserQuantum parserQuantum, + string optionLongName, + DefaultOptionValue> defaultValue) + { + ExtendedArgumentNullException.ThrowIfNull(parserQuantum, nameof(parserQuantum)); + ExtendedArgumentNullException.ThrowIfNull(optionLongName, nameof(optionLongName)); + ExtendedArgumentNullException.ThrowIfNull(defaultValue, nameof(defaultValue)); + + AddDefaultValue(parserQuantum, optionLongName, defaultValue); + } +} diff --git a/Core/NetArgumentParser/Options/OptionNotFoundException.cs b/Core/NetArgumentParser/Options/OptionNotFoundException.cs index 0275af3..d5db269 100644 --- a/Core/NetArgumentParser/Options/OptionNotFoundException.cs +++ b/Core/NetArgumentParser/Options/OptionNotFoundException.cs @@ -7,16 +7,17 @@ namespace NetArgumentParser.Options; [Serializable] public class OptionNotFoundException : Exception { - public OptionNotFoundException() { } + public OptionNotFoundException() + : this(GetDefaultMessage()) { } public OptionNotFoundException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public OptionNotFoundException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } public OptionNotFoundException(string? message, string optionName) - : this(message, optionName, null) { } + : this(message ?? GetDefaultMessage(optionName), optionName, null) { } public OptionNotFoundException( string? message, @@ -53,9 +54,11 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } - private static string GetDefaultMessage(string optionName) + private static string GetDefaultMessage(string? optionName = null) { - ExtendedArgumentNullException.ThrowIfNull(optionName, nameof(optionName)); - return $"Option with name '{optionName}' not found."; + if (!string.IsNullOrEmpty(optionName)) + optionName = $" '{optionName}'"; + + return $"Option with name{optionName} not found."; } } diff --git a/Core/NetArgumentParser/Options/OptionRestrictionProvider.cs b/Core/NetArgumentParser/Options/OptionRestrictionProvider.cs new file mode 100644 index 0000000..dc7f836 --- /dev/null +++ b/Core/NetArgumentParser/Options/OptionRestrictionProvider.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using NetArgumentParser.Options.Configuration; +using NetArgumentParser.Subcommands; + +namespace NetArgumentParser.Options; + +public abstract class OptionRestrictionProvider : OptionConfigurationProvider +{ + protected static string CreateValueNotSatisfuRestrictionMessage(string optionName, string? reason = null) + { + ExtendedArgumentNullException.ThrowIfNull(optionName, nameof(optionName)); + + if (!string.IsNullOrEmpty(reason)) + reason = $": {reason}"; + + return $"Value of '{optionName}' is incorrect{reason}."; + } + + protected static void AddRestriction( + ParserQuantum parserQuantum, + string optionLongName, + Predicate isValueAllowed, + string? valueNotSatisfuRestrictionMessage = null) + { + ExtendedArgumentNullException.ThrowIfNull(parserQuantum, nameof(parserQuantum)); + ExtendedArgumentNullException.ThrowIfNull(optionLongName, nameof(optionLongName)); + ExtendedArgumentNullException.ThrowIfNull(isValueAllowed, nameof(isValueAllowed)); + + AddRestriction( + parserQuantum, + optionLongName, + new OptionValueRestriction(isValueAllowed, valueNotSatisfuRestrictionMessage)); + } + + protected static void AddRestriction( + ParserQuantum parserQuantum, + string optionLongName, + OptionValueRestriction? valueRestriction) + { + ExtendedArgumentNullException.ThrowIfNull(parserQuantum, nameof(parserQuantum)); + ExtendedArgumentNullException.ThrowIfNull(optionLongName, nameof(optionLongName)); + + IValueOption foundOption = FindValueOption(parserQuantum, optionLongName); + foundOption.ValueRestriction = valueRestriction; + } + + protected static void AddRestrictionToMultipleValueOption( + ParserQuantum parserQuantum, + string optionLongName, + Predicate> isValueAllowed, + string? valueNotSatisfuRestrictionMessage = null) + { + ExtendedArgumentNullException.ThrowIfNull(parserQuantum, nameof(parserQuantum)); + ExtendedArgumentNullException.ThrowIfNull(optionLongName, nameof(optionLongName)); + ExtendedArgumentNullException.ThrowIfNull(isValueAllowed, nameof(isValueAllowed)); + + AddRestriction( + parserQuantum, + optionLongName, + isValueAllowed, + valueNotSatisfuRestrictionMessage); + } + + protected static void AddRestrictionToMultipleValueOption( + ParserQuantum parserQuantum, + string optionLongName, + OptionValueRestriction>? valueRestriction) + { + ExtendedArgumentNullException.ThrowIfNull(parserQuantum, nameof(parserQuantum)); + ExtendedArgumentNullException.ThrowIfNull(optionLongName, nameof(optionLongName)); + + AddRestriction(parserQuantum, optionLongName, valueRestriction); + } +} diff --git a/Core/NetArgumentParser/Options/OptionSetNotBuiltException.cs b/Core/NetArgumentParser/Options/OptionSetNotBuiltException.cs index 7b68a25..b0b71bf 100644 --- a/Core/NetArgumentParser/Options/OptionSetNotBuiltException.cs +++ b/Core/NetArgumentParser/Options/OptionSetNotBuiltException.cs @@ -7,10 +7,11 @@ namespace NetArgumentParser.Options; [Serializable] public class OptionSetNotBuiltException : Exception { - public OptionSetNotBuiltException() { } + public OptionSetNotBuiltException() + : this(GetDefaultMessage()) { } public OptionSetNotBuiltException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public OptionSetNotBuiltException(string? message, Exception? innerException) : base(message ?? GetDefaultMessage(), innerException) { } diff --git a/Core/NetArgumentParser/Options/OptionValueConverterProvider.cs b/Core/NetArgumentParser/Options/OptionValueConverterProvider.cs new file mode 100644 index 0000000..ff7c1f7 --- /dev/null +++ b/Core/NetArgumentParser/Options/OptionValueConverterProvider.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using NetArgumentParser.Converters; +using NetArgumentParser.Subcommands; + +namespace NetArgumentParser.Options; + +public abstract class OptionValueConverterProvider : OptionConfigurationProvider +{ + protected static void AddValueConverter( + ParserQuantum parserQuantum, + string optionLongName, + Func converter) + { + ExtendedArgumentNullException.ThrowIfNull(parserQuantum, nameof(parserQuantum)); + ExtendedArgumentNullException.ThrowIfNull(optionLongName, nameof(optionLongName)); + ExtendedArgumentNullException.ThrowIfNull(converter, nameof(converter)); + + AddValueConverter(parserQuantum, optionLongName, new ValueConverter(converter)); + } + + protected static void AddValueConverter( + ParserQuantum parserQuantum, + string optionLongName, + ValueConverter? converter) + { + ExtendedArgumentNullException.ThrowIfNull(parserQuantum, nameof(parserQuantum)); + ExtendedArgumentNullException.ThrowIfNull(optionLongName, nameof(optionLongName)); + + IValueOption foundOption = FindValueOption(parserQuantum, optionLongName); + foundOption.Converter = converter; + } + + protected static void AddValueConverterToMultipleValueOption( + ParserQuantum parserQuantum, + string optionLongName, + Func> converter) + { + ExtendedArgumentNullException.ThrowIfNull(parserQuantum, nameof(parserQuantum)); + ExtendedArgumentNullException.ThrowIfNull(optionLongName, nameof(optionLongName)); + ExtendedArgumentNullException.ThrowIfNull(converter, nameof(converter)); + + AddValueConverter(parserQuantum, optionLongName, converter); + } + + protected static void AddValueConverterToMultipleValueOption( + ParserQuantum parserQuantum, + string optionLongName, + ValueConverter>? converter) + { + ExtendedArgumentNullException.ThrowIfNull(parserQuantum, nameof(parserQuantum)); + ExtendedArgumentNullException.ThrowIfNull(optionLongName, nameof(optionLongName)); + + AddValueConverter(parserQuantum, optionLongName, converter); + } +} diff --git a/Core/NetArgumentParser/Options/OptionValueNotRecognizedException.cs b/Core/NetArgumentParser/Options/OptionValueNotRecognizedException.cs index 5ec7f4a..0563c4c 100644 --- a/Core/NetArgumentParser/Options/OptionValueNotRecognizedException.cs +++ b/Core/NetArgumentParser/Options/OptionValueNotRecognizedException.cs @@ -10,16 +10,17 @@ public class OptionValueNotRecognizedException : Exception { private readonly string[]? _optionValue; - public OptionValueNotRecognizedException() { } + public OptionValueNotRecognizedException() + : this(GetDefaultMessage()) { } public OptionValueNotRecognizedException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public OptionValueNotRecognizedException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } public OptionValueNotRecognizedException(string? message, string[] optionValue) - : this(message, optionValue, null) { } + : this(message ?? GetDefaultMessage(optionValue), optionValue, null) { } public OptionValueNotRecognizedException( string? message, @@ -56,11 +57,12 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } - private static string GetDefaultMessage(string[] optionValue) + private static string GetDefaultMessage(string[]? optionValue = null) { - ExtendedArgumentNullException.ThrowIfNull(optionValue, nameof(optionValue)); + string optionValuePresenter = optionValue is not null + ? $" '{string.Join(" ", optionValue)}'" + : string.Empty; - string value = string.Join(" ", optionValue); - return $"Option value '{value}' not recognized."; + return $"Option value{optionValuePresenter} not recognized."; } } diff --git a/Core/NetArgumentParser/Options/OptionValueNotSatisfyChoicesException.cs b/Core/NetArgumentParser/Options/OptionValueNotSatisfyChoicesException.cs index 53391ac..8459577 100644 --- a/Core/NetArgumentParser/Options/OptionValueNotSatisfyChoicesException.cs +++ b/Core/NetArgumentParser/Options/OptionValueNotSatisfyChoicesException.cs @@ -11,19 +11,24 @@ public class OptionValueNotSatisfyChoicesException : Exception private readonly string[]? _optionValue; private readonly string[]? _allowedValues; - public OptionValueNotSatisfyChoicesException() { } + public OptionValueNotSatisfyChoicesException() + : this(GetDefaultMessage()) { } public OptionValueNotSatisfyChoicesException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public OptionValueNotSatisfyChoicesException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } public OptionValueNotSatisfyChoicesException( string? message, string[] optionValue, string[] allowedValues) - : this(message, optionValue, allowedValues, null) { } + : this( + message ?? GetDefaultMessage(optionValue, allowedValues), + optionValue, + allowedValues, + null) { } public OptionValueNotSatisfyChoicesException( string? message, @@ -69,15 +74,20 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } - private static string GetDefaultMessage(string[] optionValue, string[] allowedValues) + private static string GetDefaultMessage(string[]? optionValue = null, string[]? allowedValues = null) { - ExtendedArgumentNullException.ThrowIfNull(optionValue, nameof(optionValue)); - ExtendedArgumentNullException.ThrowIfNull(allowedValues, nameof(allowedValues)); + string optionValuePresenter = optionValue is not null + ? $" '{string.Join(" ", optionValue)}'" + : string.Empty; + + string allowedValuesPresenter = allowedValues is not null + ? string.Join(", ", allowedValues) + : string.Empty; - string optionValuePresenter = string.Join(", ", optionValue); - string allowedValuesPresenter = string.Join(", ", allowedValues); + string message = $"Option value{optionValuePresenter} not allowed."; - return $"Option value '{optionValuePresenter}' not allowed. " + - "It must be one of {" + allowedValuesPresenter + "}."; + return !string.IsNullOrEmpty(allowedValuesPresenter) + ? message + " It must be one of { " + allowedValuesPresenter + " }." + : message; } } diff --git a/Core/NetArgumentParser/Options/OptionValueNotSatisfyRestrictionException.cs b/Core/NetArgumentParser/Options/OptionValueNotSatisfyRestrictionException.cs index 7661d73..5106e9e 100644 --- a/Core/NetArgumentParser/Options/OptionValueNotSatisfyRestrictionException.cs +++ b/Core/NetArgumentParser/Options/OptionValueNotSatisfyRestrictionException.cs @@ -10,16 +10,17 @@ public class OptionValueNotSatisfyRestrictionException : Exception { private readonly string[]? _optionValue; - public OptionValueNotSatisfyRestrictionException() { } + public OptionValueNotSatisfyRestrictionException() + : this(GetDefaultMessage()) { } public OptionValueNotSatisfyRestrictionException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public OptionValueNotSatisfyRestrictionException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } public OptionValueNotSatisfyRestrictionException(string? message, string[] optionValue) - : this(message, optionValue, null) { } + : this(message ?? GetDefaultMessage(optionValue), optionValue, null) { } public OptionValueNotSatisfyRestrictionException( string? message, @@ -56,11 +57,12 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } - private static string GetDefaultMessage(string[] optionValue) + private static string GetDefaultMessage(string[]? optionValue = null) { - ExtendedArgumentNullException.ThrowIfNull(optionValue, nameof(optionValue)); + string optionValuePresenter = optionValue is not null + ? $" '{string.Join(" ", optionValue)}'" + : string.Empty; - string value = string.Join(" ", optionValue); - return $"Option value '{value}' doesn't satisfy the restriction."; + return $"Option value{optionValuePresenter} doesn't satisfy the restriction."; } } diff --git a/Core/NetArgumentParser/Options/OptionValueNotSpecifiedException.cs b/Core/NetArgumentParser/Options/OptionValueNotSpecifiedException.cs index 64515d3..bc9bd96 100644 --- a/Core/NetArgumentParser/Options/OptionValueNotSpecifiedException.cs +++ b/Core/NetArgumentParser/Options/OptionValueNotSpecifiedException.cs @@ -7,16 +7,17 @@ namespace NetArgumentParser.Options; [Serializable] public class OptionValueNotSpecifiedException : Exception { - public OptionValueNotSpecifiedException() { } + public OptionValueNotSpecifiedException() + : this(GetDefaultMessage()) { } public OptionValueNotSpecifiedException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public OptionValueNotSpecifiedException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } public OptionValueNotSpecifiedException(string? message, string optionName) - : this(message, optionName, null) { } + : this(message ?? GetDefaultMessage(optionName), optionName, null) { } public OptionValueNotSpecifiedException( string? message, @@ -53,9 +54,11 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } - private static string GetDefaultMessage(string optionName) + private static string GetDefaultMessage(string? optionName = null) { - ExtendedArgumentNullException.ThrowIfNull(optionName, nameof(optionName)); - return $"Value for option '{optionName}' is not specified."; + if (!string.IsNullOrEmpty(optionName)) + optionName = $" '{optionName}'"; + + return $"Value for option{optionName} is not specified."; } } diff --git a/Core/NetArgumentParser/Options/RequiredOptionNotSpecifiedException.cs b/Core/NetArgumentParser/Options/RequiredOptionNotSpecifiedException.cs index 38bfce6..fa38bc9 100644 --- a/Core/NetArgumentParser/Options/RequiredOptionNotSpecifiedException.cs +++ b/Core/NetArgumentParser/Options/RequiredOptionNotSpecifiedException.cs @@ -7,16 +7,17 @@ namespace NetArgumentParser.Options; [Serializable] public class RequiredOptionNotSpecifiedException : Exception { - public RequiredOptionNotSpecifiedException() { } + public RequiredOptionNotSpecifiedException() + : this(GetDefaultMessage()) { } public RequiredOptionNotSpecifiedException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public RequiredOptionNotSpecifiedException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } public RequiredOptionNotSpecifiedException(string? message, ICommonOption option) - : this(message, option, null) { } + : this(message ?? GetDefaultMessage(option), option, null) { } public RequiredOptionNotSpecifiedException( string? message, @@ -53,9 +54,12 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } - private static string GetDefaultMessage(ICommonOption option) + private static string GetDefaultMessage(ICommonOption? option = null) { - ExtendedArgumentNullException.ThrowIfNull(option, nameof(option)); - return $"Required option '{option}' not specified."; + string optionPresenter = option is not null + ? $" '{option}'" + : string.Empty; + + return $"Required option{optionPresenter} not specified."; } } diff --git a/Core/NetArgumentParser/Options/Utils/Verifiers/ConversionTypeUniquenessVerifier.cs b/Core/NetArgumentParser/Options/Verifiers/ConversionTypeUniquenessVerifier.cs similarity index 93% rename from Core/NetArgumentParser/Options/Utils/Verifiers/ConversionTypeUniquenessVerifier.cs rename to Core/NetArgumentParser/Options/Verifiers/ConversionTypeUniquenessVerifier.cs index 5bbf91a..a3dc3fe 100644 --- a/Core/NetArgumentParser/Options/Utils/Verifiers/ConversionTypeUniquenessVerifier.cs +++ b/Core/NetArgumentParser/Options/Verifiers/ConversionTypeUniquenessVerifier.cs @@ -3,7 +3,7 @@ using System.Linq; using NetArgumentParser.Converters; -namespace NetArgumentParser.Options.Utils.Verifiers; +namespace NetArgumentParser.Options.Verifiers; internal sealed class ConversionTypeUniquenessVerifier { diff --git a/Core/NetArgumentParser/Options/Utils/Verifiers/OptionNameCorrectnessVerifier.cs b/Core/NetArgumentParser/Options/Verifiers/OptionNameCorrectnessVerifier.cs similarity index 82% rename from Core/NetArgumentParser/Options/Utils/Verifiers/OptionNameCorrectnessVerifier.cs rename to Core/NetArgumentParser/Options/Verifiers/OptionNameCorrectnessVerifier.cs index 6b859a9..570cf94 100644 --- a/Core/NetArgumentParser/Options/Utils/Verifiers/OptionNameCorrectnessVerifier.cs +++ b/Core/NetArgumentParser/Options/Verifiers/OptionNameCorrectnessVerifier.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text.RegularExpressions; -namespace NetArgumentParser.Options.Utils.Verifiers; +namespace NetArgumentParser.Options.Verifiers; internal static partial class OptionNameCorrectnessVerifier { @@ -24,9 +24,7 @@ internal static void VerifyNameIsCorrect(string name) { ExtendedArgumentNullException.ThrowIfNull(name, nameof(name)); -#pragma warning disable SYSLIB1045 // Use GeneratedRegexAttribute to generate the regular expression implementation at compile time var correctNameRegex = new Regex(@"^[a-zA-Z]+([a-zA-Z0-9_\-]*[a-zA-Z0-9]+)*$"); -#pragma warning restore SYSLIB1045 // Use GeneratedRegexAttribute to generate the regular expression implementation at compile time if (!string.IsNullOrEmpty(name) && !_reservedNames.Contains(name) diff --git a/Core/NetArgumentParser/Options/Utils/Verifiers/OptionNameUniquenessVerifier.cs b/Core/NetArgumentParser/Options/Verifiers/OptionNameUniquenessVerifier.cs similarity index 96% rename from Core/NetArgumentParser/Options/Utils/Verifiers/OptionNameUniquenessVerifier.cs rename to Core/NetArgumentParser/Options/Verifiers/OptionNameUniquenessVerifier.cs index 16ac5b4..1b9819d 100644 --- a/Core/NetArgumentParser/Options/Utils/Verifiers/OptionNameUniquenessVerifier.cs +++ b/Core/NetArgumentParser/Options/Verifiers/OptionNameUniquenessVerifier.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; -namespace NetArgumentParser.Options.Utils.Verifiers; +namespace NetArgumentParser.Options.Verifiers; internal sealed class OptionNameUniquenessVerifier { diff --git a/Core/NetArgumentParser/Options/Utils/Verifiers/ReuiredOptionVerifier.cs b/Core/NetArgumentParser/Options/Verifiers/ReuiredOptionVerifier.cs similarity index 93% rename from Core/NetArgumentParser/Options/Utils/Verifiers/ReuiredOptionVerifier.cs rename to Core/NetArgumentParser/Options/Verifiers/ReuiredOptionVerifier.cs index 017b57b..edd3c92 100644 --- a/Core/NetArgumentParser/Options/Utils/Verifiers/ReuiredOptionVerifier.cs +++ b/Core/NetArgumentParser/Options/Verifiers/ReuiredOptionVerifier.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace NetArgumentParser.Options.Utils.Verifiers; +namespace NetArgumentParser.Options.Verifiers; internal static class ReuiredOptionVerifier { diff --git a/Core/NetArgumentParser/Subcommands/IncorrectSubcommandNameException.cs b/Core/NetArgumentParser/Subcommands/IncorrectSubcommandNameException.cs index d9172ab..c94004c 100644 --- a/Core/NetArgumentParser/Subcommands/IncorrectSubcommandNameException.cs +++ b/Core/NetArgumentParser/Subcommands/IncorrectSubcommandNameException.cs @@ -7,16 +7,17 @@ namespace NetArgumentParser.Subcommands; [Serializable] public class IncorrectSubcommandNameException : Exception { - public IncorrectSubcommandNameException() { } + public IncorrectSubcommandNameException() + : this(GetDefaultMessage()) { } public IncorrectSubcommandNameException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public IncorrectSubcommandNameException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } public IncorrectSubcommandNameException(string? message, string subcommandName) - : this(message, subcommandName, null) { } + : this(message ?? GetDefaultMessage(subcommandName), subcommandName, null) { } public IncorrectSubcommandNameException( string? message, @@ -53,9 +54,11 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } - private static string GetDefaultMessage(string subcommandName) + private static string GetDefaultMessage(string? subcommandName = null) { - ExtendedArgumentNullException.ThrowIfNull(subcommandName, nameof(subcommandName)); - return $"Subcommand name '{subcommandName}' is not correct."; + if (!string.IsNullOrEmpty(subcommandName)) + subcommandName = $" '{subcommandName}'"; + + return $"Subcommand name{subcommandName} is not correct."; } } diff --git a/Core/NetArgumentParser/Subcommands/OnlyUniqueSubcommandNameException.cs b/Core/NetArgumentParser/Subcommands/OnlyUniqueSubcommandNameException.cs index 2e106d9..1be7bdd 100644 --- a/Core/NetArgumentParser/Subcommands/OnlyUniqueSubcommandNameException.cs +++ b/Core/NetArgumentParser/Subcommands/OnlyUniqueSubcommandNameException.cs @@ -7,16 +7,17 @@ namespace NetArgumentParser.Subcommands; [Serializable] public class OnlyUniqueSubcommandNameException : Exception { - public OnlyUniqueSubcommandNameException() { } + public OnlyUniqueSubcommandNameException() + : this(GetDefaultMessage()) { } public OnlyUniqueSubcommandNameException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public OnlyUniqueSubcommandNameException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } public OnlyUniqueSubcommandNameException(string? message, string subcommandName) - : this(message, subcommandName, null) { } + : this(message ?? GetDefaultMessage(subcommandName), subcommandName, null) { } public OnlyUniqueSubcommandNameException( string? message, @@ -53,9 +54,11 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } - private static string GetDefaultMessage(string subcommandName) + private static string GetDefaultMessage(string? subcommandName = null) { - ExtendedArgumentNullException.ThrowIfNull(subcommandName, nameof(subcommandName)); - return $"Subcommand name '{subcommandName}' is already in use."; + if (!string.IsNullOrEmpty(subcommandName)) + subcommandName = $" '{subcommandName}'"; + + return $"Subcommand name{subcommandName} is already in use."; } } diff --git a/Core/NetArgumentParser/Subcommands/ParserQuantum.cs b/Core/NetArgumentParser/Subcommands/ParserQuantum.cs index 73dccb7..26ca485 100644 --- a/Core/NetArgumentParser/Subcommands/ParserQuantum.cs +++ b/Core/NetArgumentParser/Subcommands/ParserQuantum.cs @@ -5,7 +5,7 @@ using NetArgumentParser.Generators; using NetArgumentParser.Options; using NetArgumentParser.Options.Collections; -using NetArgumentParser.Subcommands.Utils.Verifiers; +using NetArgumentParser.Subcommands.Verifiers; namespace NetArgumentParser.Subcommands; @@ -18,17 +18,21 @@ public class ParserQuantum : IOptionSetOrganizer, ISubcommandContainer private ITextWriter? _outputWriter; - public ParserQuantum() + public ParserQuantum(string name) { + ExtendedArgumentNullException.ThrowIfNull(name, nameof(name)); + _optionSet = new OptionSet(); _optionGroups = [new OptionGroup("Options:", string.Empty, _optionSet)]; _subcommands = []; _nameUniquenessVerifier = new SubcommandNameUniquenessVerifier(_subcommands); + Name = name; UseDefaultHelpOption = true; UsageStartTerm = string.Empty; } + public string Name { get; } public string UsageStartTerm { get; set; } public bool UseDefaultHelpOption { get; set; } diff --git a/Core/NetArgumentParser/Subcommands/ParserQuantumConfiguredIncorrectlyException.cs b/Core/NetArgumentParser/Subcommands/ParserQuantumConfiguredIncorrectlyException.cs new file mode 100644 index 0000000..840aea1 --- /dev/null +++ b/Core/NetArgumentParser/Subcommands/ParserQuantumConfiguredIncorrectlyException.cs @@ -0,0 +1,63 @@ +using System; +using System.ComponentModel; +using System.Runtime.Serialization; + +namespace NetArgumentParser.Subcommands; + +[Serializable] +public class ParserQuantumConfiguredIncorrectlyException : Exception +{ + public ParserQuantumConfiguredIncorrectlyException() + : this(GetDefaultMessage()) { } + + public ParserQuantumConfiguredIncorrectlyException(string? message) + : base(message ?? GetDefaultMessage()) { } + + public ParserQuantumConfiguredIncorrectlyException(string? message, Exception? innerException) + : base(message ?? GetDefaultMessage(), innerException) { } + + public ParserQuantumConfiguredIncorrectlyException(string? message, string parserQuantumName) + : this(message ?? GetDefaultMessage(parserQuantumName), parserQuantumName, null) { } + + public ParserQuantumConfiguredIncorrectlyException( + string? message, + string parserQuantumName, + Exception? innerException) + : base(message ?? GetDefaultMessage(parserQuantumName), innerException) + { + ParserQuantumName = parserQuantumName; + } + +#if NET8_0_OR_GREATER + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This API supports obsolete formatter-based serialization. It should not be called or extended by application code.", DiagnosticId = "SYSLIB0051", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] +#endif + private ParserQuantumConfiguredIncorrectlyException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + ExtendedArgumentNullException.ThrowIfNull(info, nameof(info)); + ParserQuantumName = info.GetString(nameof(ParserQuantumName)); + } + + public string? ParserQuantumName { get; private set; } + +#if NET8_0_OR_GREATER + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This API supports obsolete formatter-based serialization. It should not be called or extended by application code.", DiagnosticId = "SYSLIB0051", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] +#endif + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + ExtendedArgumentNullException.ThrowIfNull(info, nameof(info)); + + info.AddValue(nameof(ParserQuantumName), ParserQuantumName, typeof(string)); + base.GetObjectData(info, context); + } + + private static string GetDefaultMessage(string? parserQuantumName = null) + { + if (!string.IsNullOrEmpty(parserQuantumName)) + parserQuantumName = $" {parserQuantumName}"; + + return $"Parser quantum{parserQuantumName} is configured incorrectly."; + } +} diff --git a/Core/NetArgumentParser/Subcommands/Subcommand.cs b/Core/NetArgumentParser/Subcommands/Subcommand.cs index e15b080..6750457 100644 --- a/Core/NetArgumentParser/Subcommands/Subcommand.cs +++ b/Core/NetArgumentParser/Subcommands/Subcommand.cs @@ -5,17 +5,14 @@ namespace NetArgumentParser.Subcommands; public class Subcommand : ParserQuantum, ISubcommand { internal Subcommand(string name, string description) + : base(name ?? throw new ArgumentNullException(nameof(name))) { - ExtendedArgumentNullException.ThrowIfNull(name, nameof(name)); ExtendedArgumentNullException.ThrowIfNull(description, nameof(description)); - - Name = name; Description = description; } public event EventHandler? Handled; - public string Name { get; } public string Description { get; } public bool IsHandled { get; protected set; } diff --git a/Core/NetArgumentParser/Subcommands/SubcommandAlreadyHandledException.cs b/Core/NetArgumentParser/Subcommands/SubcommandAlreadyHandledException.cs index 00d73b3..a700aa7 100644 --- a/Core/NetArgumentParser/Subcommands/SubcommandAlreadyHandledException.cs +++ b/Core/NetArgumentParser/Subcommands/SubcommandAlreadyHandledException.cs @@ -7,16 +7,17 @@ namespace NetArgumentParser.Subcommands; [Serializable] public class SubcommandAlreadyHandledException : Exception { - public SubcommandAlreadyHandledException() { } + public SubcommandAlreadyHandledException() + : this(GetDefaultMessage()) { } public SubcommandAlreadyHandledException(string? message) - : base(message) { } + : base(message ?? GetDefaultMessage()) { } public SubcommandAlreadyHandledException(string? message, Exception? innerException) - : base(message, innerException) { } + : base(message ?? GetDefaultMessage(), innerException) { } public SubcommandAlreadyHandledException(string? message, ISubcommand subcommand) - : this(message, subcommand, null) { } + : this(message ?? GetDefaultMessage(subcommand), subcommand, null) { } public SubcommandAlreadyHandledException( string? message, @@ -53,9 +54,12 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); } - private static string GetDefaultMessage(ISubcommand subcommand) + private static string GetDefaultMessage(ISubcommand? subcommand = null) { - ExtendedArgumentNullException.ThrowIfNull(subcommand, nameof(subcommand)); - return $"Subcommand '{subcommand}' has already been handled."; + string subcommandPresenter = subcommand is not null + ? $" '{subcommand}'" + : string.Empty; + + return $"Subcommand{subcommandPresenter} has already been handled."; } } diff --git a/Core/NetArgumentParser/Subcommands/Utils/Verifiers/SubcommandNameCorrectnessVerifier.cs b/Core/NetArgumentParser/Subcommands/Verifiers/SubcommandNameCorrectnessVerifier.cs similarity index 66% rename from Core/NetArgumentParser/Subcommands/Utils/Verifiers/SubcommandNameCorrectnessVerifier.cs rename to Core/NetArgumentParser/Subcommands/Verifiers/SubcommandNameCorrectnessVerifier.cs index 2d1b492..3ecb0f2 100644 --- a/Core/NetArgumentParser/Subcommands/Utils/Verifiers/SubcommandNameCorrectnessVerifier.cs +++ b/Core/NetArgumentParser/Subcommands/Verifiers/SubcommandNameCorrectnessVerifier.cs @@ -1,8 +1,7 @@ -using System; using System.Collections.Generic; using System.Text.RegularExpressions; -namespace NetArgumentParser.Subcommands.Utils.Verifiers; +namespace NetArgumentParser.Subcommands.Verifiers; internal static partial class CommandNameCorrectnessVerifier { @@ -12,9 +11,7 @@ internal static void VerifyNameIsCorrect(string name) { ExtendedArgumentNullException.ThrowIfNull(name, nameof(name)); -#pragma warning disable SYSLIB1045 // Use GeneratedRegexAttribute to generate the regular expression implementation at compile time var correctNameRegex = new Regex(@"^[a-zA-Z]+([a-zA-Z0-9_\-]*[a-zA-Z0-9]+)*$"); -#pragma warning restore SYSLIB1045 // Use GeneratedRegexAttribute to generate the regular expression implementation at compile time if (!string.IsNullOrEmpty(name) && !_reservedNames.Contains(name) diff --git a/Core/NetArgumentParser/Subcommands/Utils/Verifiers/SubcommandNameUniquenessVerifier.cs b/Core/NetArgumentParser/Subcommands/Verifiers/SubcommandNameUniquenessVerifier.cs similarity index 90% rename from Core/NetArgumentParser/Subcommands/Utils/Verifiers/SubcommandNameUniquenessVerifier.cs rename to Core/NetArgumentParser/Subcommands/Verifiers/SubcommandNameUniquenessVerifier.cs index 1d4d1c2..727045f 100644 --- a/Core/NetArgumentParser/Subcommands/Utils/Verifiers/SubcommandNameUniquenessVerifier.cs +++ b/Core/NetArgumentParser/Subcommands/Verifiers/SubcommandNameUniquenessVerifier.cs @@ -1,8 +1,7 @@ -using System; using System.Collections.Generic; using System.Linq; -namespace NetArgumentParser.Subcommands.Utils.Verifiers; +namespace NetArgumentParser.Subcommands.Verifiers; internal sealed class SubcommandNameUniquenessVerifier { diff --git a/Directory.Build.props b/Directory.Build.props index eb3705e..b33d20c 100755 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -23,7 +23,7 @@ - + all diff --git a/Documentation/AdditionalFeatures.md b/Documentation/AdditionalFeatures.md index b2aa69a..de138d3 100644 --- a/Documentation/AdditionalFeatures.md +++ b/Documentation/AdditionalFeatures.md @@ -5,6 +5,7 @@ * [Negative Numbers & Scientific Notation](#negative-numbers--scientific-notation) * [Use `option=value` Syntax](#use-optionvalue-syntax) * [Parse Known Arguments](#parse-known-arguments) +* [Parse Arguments Multiple Times](#parse-arguments-multiple-times) * [Skip Arguments](#skip-arguments) * [Getting Info About Handled Options And Subcommands](#getting-info-about-handled-options-and-subcommands) * [Add Default Value To Description](#add-default-value-to-description) @@ -77,6 +78,39 @@ parser.ParseKnownArguments(new string[] { "-v", "10", "-a" }, out List e // extraArguments: [10, -a] ``` +## Parse Arguments Multiple Times +You can parse arguments multiple times using a single instance of `ArgumentParser`. When you call the `Parse()` or `ParseKnownArguments()` methods, it automatically invokes the `ResetOptionsHandledState()` and `ResetSubcommandsHandledState()` methods, so you don't need to call them manually. + +```cs +int angle = 0; +int width = 0; +int height = 0; + +var options = new ICommonOption[] +{ + new ValueOption("angle", afterValueParsingAction: t => angle = t), + new ValueOption("width", afterValueParsingAction: t => width = t), + new ValueOption("height", afterValueParsingAction: t => height = t) +}; + +var parser = new ArgumentParser(); +parser.AddOptions(options); + +_ = parser.Parse(["--angle", "1", "--width", "2", "--height", "3"]); +PrintSummary("=== Parse 1 ==="); + +_ = parser.Parse(["--angle", "4", "--width", "5", "--height", "6"]); +PrintSummary("\n=== Parse 2 ==="); + +void PrintSummary(string name) +{ + Console.WriteLine(name); + Console.WriteLine($"Angle: {angle}"); + Console.WriteLine($"Width: {width}"); + Console.WriteLine($"Height: {height}"); +} +``` + ## Skip Arguments Sometimes a program may need to skip some arguments from the beginning of the argument list and handle them in a special way. In this case, the `NumberOfArgumentsToSkip` property may be useful. With it, you can specify the number of arguments to be skipped. diff --git a/Documentation/ParserGenerationUsingAttributes.md b/Documentation/ParserGenerationUsingAttributes.md index 58e5656..b68dadc 100644 --- a/Documentation/ParserGenerationUsingAttributes.md +++ b/Documentation/ParserGenerationUsingAttributes.md @@ -434,3 +434,129 @@ internal sealed class CustomParserConfig public DateTime BirthDate { get; set; } } ``` + +A more advanced way to configure options is to create custom classes that inherit from `OptionValueConverterProvider`, `OptionDefaultValueProvider`, or `OptionRestrictionProvider`. You can add your configuration inside those classes and then apply the configuration using `OptionConfigurationSetter`. + +```cs +var generator = new ArgumentParserGenerator(); +var parser = new ArgumentParser(name: CustomParserConfig.ParserName); +var config = new CustomParserConfig(); + +generator.ConfigureParser(parser, config); + +var optionConfigurationsFactory = new OptionConfigurationsFactory(); +var optionConfigurations = optionConfigurationsFactory.Create(); + +var optionConfigurationSetter = new OptionConfigurationSetter(optionConfigurations); +optionConfigurationSetter.SetOptionConfigurations(parser); + +string[] arguments = +[ + $"--{CustomParserConfig.WidthOptionLongName}", + "-500", + CustomParserConfig.CustomSubcommandName, + $"--{CustomSubcommand.FilesOptionLongName}", + "file1.txt", + "file2.jpg", + "file3.mp4", +]; + +parser.Parse(arguments); + +string parsedFiles = string.Join(" ", config.CustomSubcommand.Files); + +Console.WriteLine(config.Width); // 500 +Console.WriteLine(config.Height); // 1080 +Console.WriteLine(parsedFiles); // file1.txt file2.jpg file3.mp4 + +public class RootOptionValueConverters : OptionValueConverterProvider +{ + protected override IReadOnlyCollection> ConfigurationProviders => + [ + AddValueConverterForWidthOption + ]; + + private static void AddValueConverterForWidthOption(ParserQuantum parserQuantum) + { + AddValueConverter( + parserQuantum, + CustomParserConfig.WidthOptionLongName, + t => Math.Abs(int.Parse(t))); + } +} + +public class RootOptionDefaultValues : OptionDefaultValueProvider +{ + protected override IReadOnlyCollection> ConfigurationProviders => + [ + AddDefaultValueForWidthOption, + AddDefaultValueForHeightOption + ]; + + private static void AddDefaultValueForWidthOption(ParserQuantum parserQuantum) + { + AddDefaultValue(parserQuantum, CustomParserConfig.WidthOptionLongName, 1920); + } + + private static void AddDefaultValueForHeightOption(ParserQuantum parserQuantum) + { + AddDefaultValue(parserQuantum, CustomParserConfig.HeightOptionLongName, 1080); + } +} + +public class CustomSubcommandOptionRestrictions : OptionRestrictionProvider +{ + protected override IReadOnlyCollection> ConfigurationProviders => + [ + AddRestrictionForFilesOption + ]; + + private static void AddRestrictionForFilesOption(ParserQuantum parserQuantum) + { + AddRestrictionToMultipleValueOption( + parserQuantum, + CustomSubcommand.FilesOptionLongName, + t => t.All(x => x.Contains('.'))); + } +} + +public class OptionConfigurationsFactory +{ + public Dictionary> Create() + { + return new() + { + { CustomParserConfig.ParserName, [new RootOptionValueConverters(), new RootOptionDefaultValues()] }, + { CustomParserConfig.CustomSubcommandName, [new CustomSubcommandOptionRestrictions()] } + }; + } +} + +[ParserConfig] +public sealed class CustomParserConfig +{ + public const string ParserName = nameof(ArgumentParser); + public const string WidthOptionLongName = "width"; + public const string HeightOptionLongName = "height"; + public const string CustomSubcommandName = "subcommand"; + + [ValueOption(WidthOptionLongName)] + public int Width { get; set; } + + [ValueOption(HeightOptionLongName)] + public int Height { get; set; } + + [Subcommand(CustomSubcommandName, "")] + public CustomSubcommand CustomSubcommand { get; } = new(); +} + +public class CustomSubcommand +{ + public const string FilesOptionLongName = "files"; + + [MultipleValueOption(FilesOptionLongName, contextCaptureType: ContextCaptureType.OneOrMore)] + public List Files { get; set; } = []; +} +``` + +Note the line `var parser = new ArgumentParser(name: CustomParserConfig.ParserName);`. We assign a custom name to the `ArgumentParser` because `OptionConfigurationSetter` expects a dictionary that uses parser quantum names as keys. You can omit this name if you don't need a configuration for root options or you want to use the parser's default name, which is equal to `nameof(ArgumentParser)`. diff --git a/Examples/NetArgumentParser.Examples.ComplexFurtherConfigureOption/NetArgumentParser.Examples.ComplexFurtherConfigureOption.csproj b/Examples/NetArgumentParser.Examples.ComplexFurtherConfigureOption/NetArgumentParser.Examples.ComplexFurtherConfigureOption.csproj new file mode 100644 index 0000000..44dcb4e --- /dev/null +++ b/Examples/NetArgumentParser.Examples.ComplexFurtherConfigureOption/NetArgumentParser.Examples.ComplexFurtherConfigureOption.csproj @@ -0,0 +1,12 @@ + + + + Exe + net6.0 + + + + + + + diff --git a/Examples/NetArgumentParser.Examples.ComplexFurtherConfigureOption/Program.cs b/Examples/NetArgumentParser.Examples.ComplexFurtherConfigureOption/Program.cs new file mode 100644 index 0000000..63e7d21 --- /dev/null +++ b/Examples/NetArgumentParser.Examples.ComplexFurtherConfigureOption/Program.cs @@ -0,0 +1,142 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using NetArgumentParser; +using NetArgumentParser.Attributes; +using NetArgumentParser.Generators; +using NetArgumentParser.Options; +using NetArgumentParser.Options.Context; +using NetArgumentParser.Subcommands; + +var generator = new ArgumentParserGenerator(); +var parser = new ArgumentParser(name: CustomParserConfig.ParserName); +var config = new CustomParserConfig(); + +generator.ConfigureParser(parser, config); + +var optionConfigurationsFactory = new OptionConfigurationsFactory(); +var optionConfigurations = optionConfigurationsFactory.Create(); + +var optionConfigurationSetter = new OptionConfigurationSetter(optionConfigurations); +optionConfigurationSetter.SetOptionConfigurations(parser); + +string[] arguments = +[ + $"--{CustomParserConfig.WidthOptionLongName}", + "-500", + CustomParserConfig.CustomSubcommandName, + $"--{CustomSubcommand.FilesOptionLongName}", + "file1.txt", + "file2.jpg", + "file3.mp4", +]; + +parser.Parse(arguments); // Ok + +/* +string[] argumentsWithError = +[ + CustomParserConfig.CustomSubcommandName, + $"--{CustomSubcommand.FilesOptionLongName}", + "file", +]; + +parser.Parse(argumentsWithError); // Error: Option value 'file' doesn't satisfy the restriction +*/ + +string parsedFiles = string.Join(" ", config.CustomSubcommand.Files); + +Console.WriteLine(config.Width); // 500 +Console.WriteLine(config.Height); // 1080 +Console.WriteLine(parsedFiles); // file1.txt file2.jpg file3.mp4 + +#pragma warning disable +public class RootOptionValueConverters : OptionValueConverterProvider +{ + protected override IReadOnlyCollection> ConfigurationProviders => + [ + AddValueConverterForWidthOption + ]; + + private static void AddValueConverterForWidthOption(ParserQuantum parserQuantum) + { + AddValueConverter( + parserQuantum, + CustomParserConfig.WidthOptionLongName, + t => Math.Abs(int.Parse(t))); + } +} + +public class RootOptionDefaultValues : OptionDefaultValueProvider +{ + protected override IReadOnlyCollection> ConfigurationProviders => + [ + AddDefaultValueForWidthOption, + AddDefaultValueForHeightOption + ]; + + private static void AddDefaultValueForWidthOption(ParserQuantum parserQuantum) + { + AddDefaultValue(parserQuantum, CustomParserConfig.WidthOptionLongName, 1920); + } + + private static void AddDefaultValueForHeightOption(ParserQuantum parserQuantum) + { + AddDefaultValue(parserQuantum, CustomParserConfig.HeightOptionLongName, 1080); + } +} + +public class CustomSubcommandOptionRestrictions : OptionRestrictionProvider +{ + protected override IReadOnlyCollection> ConfigurationProviders => + [ + AddRestrictionForFilesOption + ]; + + private static void AddRestrictionForFilesOption(ParserQuantum parserQuantum) + { + AddRestrictionToMultipleValueOption( + parserQuantum, + CustomSubcommand.FilesOptionLongName, + t => t.All(x => x.Contains('.'))); + } +} + +public class OptionConfigurationsFactory +{ + public Dictionary> Create() + { + return new() + { + { CustomParserConfig.ParserName, [new RootOptionValueConverters(), new RootOptionDefaultValues()] }, + { CustomParserConfig.CustomSubcommandName, [new CustomSubcommandOptionRestrictions()] } + }; + } +} + +[ParserConfig] +public sealed class CustomParserConfig +{ + public const string ParserName = nameof(ArgumentParser); + public const string WidthOptionLongName = "width"; + public const string HeightOptionLongName = "height"; + public const string CustomSubcommandName = "subcommand"; + + [ValueOption(WidthOptionLongName)] + public int Width { get; set; } + + [ValueOption(HeightOptionLongName)] + public int Height { get; set; } + + [Subcommand(CustomSubcommandName, "")] + public CustomSubcommand CustomSubcommand { get; } = new(); +} + +public class CustomSubcommand +{ + public const string FilesOptionLongName = "files"; + + [MultipleValueOption(FilesOptionLongName, contextCaptureType: ContextCaptureType.OneOrMore)] + public List Files { get; set; } = []; +} +#pragma warning restore diff --git a/Examples/NetArgumentParser.Examples.ParseArgumentsMultipleTimes/NetArgumentParser.Examples.ParseArgumentsMultipleTimes.csproj b/Examples/NetArgumentParser.Examples.ParseArgumentsMultipleTimes/NetArgumentParser.Examples.ParseArgumentsMultipleTimes.csproj new file mode 100644 index 0000000..44dcb4e --- /dev/null +++ b/Examples/NetArgumentParser.Examples.ParseArgumentsMultipleTimes/NetArgumentParser.Examples.ParseArgumentsMultipleTimes.csproj @@ -0,0 +1,12 @@ + + + + Exe + net6.0 + + + + + + + diff --git a/Examples/NetArgumentParser.Examples.ParseArgumentsMultipleTimes/Program.cs b/Examples/NetArgumentParser.Examples.ParseArgumentsMultipleTimes/Program.cs new file mode 100644 index 0000000..17b0b7c --- /dev/null +++ b/Examples/NetArgumentParser.Examples.ParseArgumentsMultipleTimes/Program.cs @@ -0,0 +1,31 @@ +using System; +using NetArgumentParser; +using NetArgumentParser.Options; + +int angle = 0; +int width = 0; +int height = 0; + +var options = new ICommonOption[] +{ + new ValueOption("angle", afterValueParsingAction: t => angle = t), + new ValueOption("width", afterValueParsingAction: t => width = t), + new ValueOption("height", afterValueParsingAction: t => height = t) +}; + +var parser = new ArgumentParser(); +parser.AddOptions(options); + +_ = parser.Parse(["--angle", "1", "--width", "2", "--height", "3"]); +PrintSummary("=== Parse 1 ==="); + +_ = parser.Parse(["--angle", "4", "--width", "5", "--height", "6"]); +PrintSummary("\n=== Parse 2 ==="); + +void PrintSummary(string name) +{ + Console.WriteLine(name); + Console.WriteLine($"Angle: {angle}"); + Console.WriteLine($"Width: {width}"); + Console.WriteLine($"Height: {height}"); +} diff --git a/NetArgumentParser.sln b/NetArgumentParser.sln index 41c5699..2947945 100644 --- a/NetArgumentParser.sln +++ b/NetArgumentParser.sln @@ -1,101 +1,223 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31903.59 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{649A384F-36AE-432F-8AF5-D28674D77B7D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetArgumentParser", "Core\NetArgumentParser\NetArgumentParser.csproj", "{2C140CC4-00C6-4017-8CB3-68B32CC7C058}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{DCD4DEB9-0ACD-4CA0-AAF6-A7298C908266}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetArgumentParser.Tests", "Tests\NetArgumentParser.Tests\NetArgumentParser.Tests.csproj", "{3AB4D374-88E7-4681-B9C7-2C3D57DF8DC8}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{5F8AF5AE-CF52-4ECE-92B8-EE6F7F401E98}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetArgumentParser.Examples.Simple", "Examples\NetArgumentParser.Examples.Simple\NetArgumentParser.Examples.Simple.csproj", "{540F9CC0-410A-48D4-B44E-8B3845C66F0B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetArgumentParser.Examples.AllUseCases", "Examples\NetArgumentParser.Examples.AllUseCases\NetArgumentParser.Examples.AllUseCases.csproj", "{F56E27F2-A034-4268-BF1A-9D211648D999}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetArgumentParser.Examples.FurtherConfigureOption", "Examples\NetArgumentParser.Examples.FurtherConfigureOption\NetArgumentParser.Examples.FurtherConfigureOption.csproj", "{850C9444-F85A-46FA-AE65-734A9AED1A0B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetArgumentParser.Examples.CustomConverter", "Examples\NetArgumentParser.Examples.CustomConverter\NetArgumentParser.Examples.CustomConverter.csproj", "{67AEF7CC-BDC4-43D0-8627-9C807502A6EE}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetArgumentParser.Examples.OptionalArguments", "Examples\NetArgumentParser.Examples.OptionalArguments\NetArgumentParser.Examples.OptionalArguments.csproj", "{3B17B627-D157-47C8-8F1A-4A768ADA0F74}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetArgumentParser.Examples.ParserGenerationUsingAttributes", "Examples\NetArgumentParser.Examples.ParserGenerationUsingAttributes\NetArgumentParser.Examples.ParserGenerationUsingAttributes.csproj", "{150103E0-BAED-4EB7-BB3A-7871D5E5EB22}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetArgumentParser.Examples.Subcommands", "Examples\NetArgumentParser.Examples.Subcommands\NetArgumentParser.Examples.Subcommands.csproj", "{A9379A83-FBDD-425F-8C4A-9EA60EC6D779}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetArgumentParser.Examples.PrintingHelp", "Examples\NetArgumentParser.Examples.PrintingHelp\NetArgumentParser.Examples.PrintingHelp.csproj", "{91681128-8B86-471D-82B4-2A7F0390569F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetArgumentParser.Examples.AddChoicesToDescription", "Examples\NetArgumentParser.Examples.AddChoicesToDescription\NetArgumentParser.Examples.AddChoicesToDescription.csproj", "{61A10479-C5AC-4D81-B004-9BE69CC8ADDD}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2C140CC4-00C6-4017-8CB3-68B32CC7C058}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2C140CC4-00C6-4017-8CB3-68B32CC7C058}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2C140CC4-00C6-4017-8CB3-68B32CC7C058}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2C140CC4-00C6-4017-8CB3-68B32CC7C058}.Release|Any CPU.Build.0 = Release|Any CPU - {3AB4D374-88E7-4681-B9C7-2C3D57DF8DC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3AB4D374-88E7-4681-B9C7-2C3D57DF8DC8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3AB4D374-88E7-4681-B9C7-2C3D57DF8DC8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3AB4D374-88E7-4681-B9C7-2C3D57DF8DC8}.Release|Any CPU.Build.0 = Release|Any CPU - {540F9CC0-410A-48D4-B44E-8B3845C66F0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {540F9CC0-410A-48D4-B44E-8B3845C66F0B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {540F9CC0-410A-48D4-B44E-8B3845C66F0B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {540F9CC0-410A-48D4-B44E-8B3845C66F0B}.Release|Any CPU.Build.0 = Release|Any CPU - {F56E27F2-A034-4268-BF1A-9D211648D999}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F56E27F2-A034-4268-BF1A-9D211648D999}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F56E27F2-A034-4268-BF1A-9D211648D999}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F56E27F2-A034-4268-BF1A-9D211648D999}.Release|Any CPU.Build.0 = Release|Any CPU - {850C9444-F85A-46FA-AE65-734A9AED1A0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {850C9444-F85A-46FA-AE65-734A9AED1A0B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {850C9444-F85A-46FA-AE65-734A9AED1A0B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {850C9444-F85A-46FA-AE65-734A9AED1A0B}.Release|Any CPU.Build.0 = Release|Any CPU - {67AEF7CC-BDC4-43D0-8627-9C807502A6EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {67AEF7CC-BDC4-43D0-8627-9C807502A6EE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {67AEF7CC-BDC4-43D0-8627-9C807502A6EE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {67AEF7CC-BDC4-43D0-8627-9C807502A6EE}.Release|Any CPU.Build.0 = Release|Any CPU - {3B17B627-D157-47C8-8F1A-4A768ADA0F74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3B17B627-D157-47C8-8F1A-4A768ADA0F74}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3B17B627-D157-47C8-8F1A-4A768ADA0F74}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3B17B627-D157-47C8-8F1A-4A768ADA0F74}.Release|Any CPU.Build.0 = Release|Any CPU - {150103E0-BAED-4EB7-BB3A-7871D5E5EB22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {150103E0-BAED-4EB7-BB3A-7871D5E5EB22}.Debug|Any CPU.Build.0 = Debug|Any CPU - {150103E0-BAED-4EB7-BB3A-7871D5E5EB22}.Release|Any CPU.ActiveCfg = Release|Any CPU - {150103E0-BAED-4EB7-BB3A-7871D5E5EB22}.Release|Any CPU.Build.0 = Release|Any CPU - {A9379A83-FBDD-425F-8C4A-9EA60EC6D779}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A9379A83-FBDD-425F-8C4A-9EA60EC6D779}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A9379A83-FBDD-425F-8C4A-9EA60EC6D779}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A9379A83-FBDD-425F-8C4A-9EA60EC6D779}.Release|Any CPU.Build.0 = Release|Any CPU - {91681128-8B86-471D-82B4-2A7F0390569F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {91681128-8B86-471D-82B4-2A7F0390569F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {91681128-8B86-471D-82B4-2A7F0390569F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {91681128-8B86-471D-82B4-2A7F0390569F}.Release|Any CPU.Build.0 = Release|Any CPU - {61A10479-C5AC-4D81-B004-9BE69CC8ADDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {61A10479-C5AC-4D81-B004-9BE69CC8ADDD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {61A10479-C5AC-4D81-B004-9BE69CC8ADDD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {61A10479-C5AC-4D81-B004-9BE69CC8ADDD}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {2C140CC4-00C6-4017-8CB3-68B32CC7C058} = {649A384F-36AE-432F-8AF5-D28674D77B7D} - {3AB4D374-88E7-4681-B9C7-2C3D57DF8DC8} = {DCD4DEB9-0ACD-4CA0-AAF6-A7298C908266} - {540F9CC0-410A-48D4-B44E-8B3845C66F0B} = {5F8AF5AE-CF52-4ECE-92B8-EE6F7F401E98} - {F56E27F2-A034-4268-BF1A-9D211648D999} = {5F8AF5AE-CF52-4ECE-92B8-EE6F7F401E98} - {850C9444-F85A-46FA-AE65-734A9AED1A0B} = {5F8AF5AE-CF52-4ECE-92B8-EE6F7F401E98} - {67AEF7CC-BDC4-43D0-8627-9C807502A6EE} = {5F8AF5AE-CF52-4ECE-92B8-EE6F7F401E98} - {3B17B627-D157-47C8-8F1A-4A768ADA0F74} = {5F8AF5AE-CF52-4ECE-92B8-EE6F7F401E98} - {150103E0-BAED-4EB7-BB3A-7871D5E5EB22} = {5F8AF5AE-CF52-4ECE-92B8-EE6F7F401E98} - {A9379A83-FBDD-425F-8C4A-9EA60EC6D779} = {5F8AF5AE-CF52-4ECE-92B8-EE6F7F401E98} - {91681128-8B86-471D-82B4-2A7F0390569F} = {5F8AF5AE-CF52-4ECE-92B8-EE6F7F401E98} - {61A10479-C5AC-4D81-B004-9BE69CC8ADDD} = {5F8AF5AE-CF52-4ECE-92B8-EE6F7F401E98} - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{649A384F-36AE-432F-8AF5-D28674D77B7D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetArgumentParser", "Core\NetArgumentParser\NetArgumentParser.csproj", "{2C140CC4-00C6-4017-8CB3-68B32CC7C058}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{DCD4DEB9-0ACD-4CA0-AAF6-A7298C908266}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetArgumentParser.Tests", "Tests\NetArgumentParser.Tests\NetArgumentParser.Tests.csproj", "{3AB4D374-88E7-4681-B9C7-2C3D57DF8DC8}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{5F8AF5AE-CF52-4ECE-92B8-EE6F7F401E98}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetArgumentParser.Examples.Simple", "Examples\NetArgumentParser.Examples.Simple\NetArgumentParser.Examples.Simple.csproj", "{540F9CC0-410A-48D4-B44E-8B3845C66F0B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetArgumentParser.Examples.AllUseCases", "Examples\NetArgumentParser.Examples.AllUseCases\NetArgumentParser.Examples.AllUseCases.csproj", "{F56E27F2-A034-4268-BF1A-9D211648D999}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetArgumentParser.Examples.FurtherConfigureOption", "Examples\NetArgumentParser.Examples.FurtherConfigureOption\NetArgumentParser.Examples.FurtherConfigureOption.csproj", "{850C9444-F85A-46FA-AE65-734A9AED1A0B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetArgumentParser.Examples.CustomConverter", "Examples\NetArgumentParser.Examples.CustomConverter\NetArgumentParser.Examples.CustomConverter.csproj", "{67AEF7CC-BDC4-43D0-8627-9C807502A6EE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetArgumentParser.Examples.OptionalArguments", "Examples\NetArgumentParser.Examples.OptionalArguments\NetArgumentParser.Examples.OptionalArguments.csproj", "{3B17B627-D157-47C8-8F1A-4A768ADA0F74}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetArgumentParser.Examples.ParserGenerationUsingAttributes", "Examples\NetArgumentParser.Examples.ParserGenerationUsingAttributes\NetArgumentParser.Examples.ParserGenerationUsingAttributes.csproj", "{150103E0-BAED-4EB7-BB3A-7871D5E5EB22}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetArgumentParser.Examples.Subcommands", "Examples\NetArgumentParser.Examples.Subcommands\NetArgumentParser.Examples.Subcommands.csproj", "{A9379A83-FBDD-425F-8C4A-9EA60EC6D779}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetArgumentParser.Examples.PrintingHelp", "Examples\NetArgumentParser.Examples.PrintingHelp\NetArgumentParser.Examples.PrintingHelp.csproj", "{91681128-8B86-471D-82B4-2A7F0390569F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetArgumentParser.Examples.AddChoicesToDescription", "Examples\NetArgumentParser.Examples.AddChoicesToDescription\NetArgumentParser.Examples.AddChoicesToDescription.csproj", "{61A10479-C5AC-4D81-B004-9BE69CC8ADDD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetArgumentParser.Examples.ComplexFurtherConfigureOption", "Examples\NetArgumentParser.Examples.ComplexFurtherConfigureOption\NetArgumentParser.Examples.ComplexFurtherConfigureOption.csproj", "{E63FD1A4-3CBB-4DAD-80DE-185EF8586AA0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetArgumentParser.Examples.ParseArgumentsMultipleTimes", "Examples\NetArgumentParser.Examples.ParseArgumentsMultipleTimes\NetArgumentParser.Examples.ParseArgumentsMultipleTimes.csproj", "{FB1F330C-502B-42FC-8D24-46A9106A0F2A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2C140CC4-00C6-4017-8CB3-68B32CC7C058}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2C140CC4-00C6-4017-8CB3-68B32CC7C058}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2C140CC4-00C6-4017-8CB3-68B32CC7C058}.Debug|x64.ActiveCfg = Debug|Any CPU + {2C140CC4-00C6-4017-8CB3-68B32CC7C058}.Debug|x64.Build.0 = Debug|Any CPU + {2C140CC4-00C6-4017-8CB3-68B32CC7C058}.Debug|x86.ActiveCfg = Debug|Any CPU + {2C140CC4-00C6-4017-8CB3-68B32CC7C058}.Debug|x86.Build.0 = Debug|Any CPU + {2C140CC4-00C6-4017-8CB3-68B32CC7C058}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2C140CC4-00C6-4017-8CB3-68B32CC7C058}.Release|Any CPU.Build.0 = Release|Any CPU + {2C140CC4-00C6-4017-8CB3-68B32CC7C058}.Release|x64.ActiveCfg = Release|Any CPU + {2C140CC4-00C6-4017-8CB3-68B32CC7C058}.Release|x64.Build.0 = Release|Any CPU + {2C140CC4-00C6-4017-8CB3-68B32CC7C058}.Release|x86.ActiveCfg = Release|Any CPU + {2C140CC4-00C6-4017-8CB3-68B32CC7C058}.Release|x86.Build.0 = Release|Any CPU + {3AB4D374-88E7-4681-B9C7-2C3D57DF8DC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3AB4D374-88E7-4681-B9C7-2C3D57DF8DC8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3AB4D374-88E7-4681-B9C7-2C3D57DF8DC8}.Debug|x64.ActiveCfg = Debug|Any CPU + {3AB4D374-88E7-4681-B9C7-2C3D57DF8DC8}.Debug|x64.Build.0 = Debug|Any CPU + {3AB4D374-88E7-4681-B9C7-2C3D57DF8DC8}.Debug|x86.ActiveCfg = Debug|Any CPU + {3AB4D374-88E7-4681-B9C7-2C3D57DF8DC8}.Debug|x86.Build.0 = Debug|Any CPU + {3AB4D374-88E7-4681-B9C7-2C3D57DF8DC8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3AB4D374-88E7-4681-B9C7-2C3D57DF8DC8}.Release|Any CPU.Build.0 = Release|Any CPU + {3AB4D374-88E7-4681-B9C7-2C3D57DF8DC8}.Release|x64.ActiveCfg = Release|Any CPU + {3AB4D374-88E7-4681-B9C7-2C3D57DF8DC8}.Release|x64.Build.0 = Release|Any CPU + {3AB4D374-88E7-4681-B9C7-2C3D57DF8DC8}.Release|x86.ActiveCfg = Release|Any CPU + {3AB4D374-88E7-4681-B9C7-2C3D57DF8DC8}.Release|x86.Build.0 = Release|Any CPU + {540F9CC0-410A-48D4-B44E-8B3845C66F0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {540F9CC0-410A-48D4-B44E-8B3845C66F0B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {540F9CC0-410A-48D4-B44E-8B3845C66F0B}.Debug|x64.ActiveCfg = Debug|Any CPU + {540F9CC0-410A-48D4-B44E-8B3845C66F0B}.Debug|x64.Build.0 = Debug|Any CPU + {540F9CC0-410A-48D4-B44E-8B3845C66F0B}.Debug|x86.ActiveCfg = Debug|Any CPU + {540F9CC0-410A-48D4-B44E-8B3845C66F0B}.Debug|x86.Build.0 = Debug|Any CPU + {540F9CC0-410A-48D4-B44E-8B3845C66F0B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {540F9CC0-410A-48D4-B44E-8B3845C66F0B}.Release|Any CPU.Build.0 = Release|Any CPU + {540F9CC0-410A-48D4-B44E-8B3845C66F0B}.Release|x64.ActiveCfg = Release|Any CPU + {540F9CC0-410A-48D4-B44E-8B3845C66F0B}.Release|x64.Build.0 = Release|Any CPU + {540F9CC0-410A-48D4-B44E-8B3845C66F0B}.Release|x86.ActiveCfg = Release|Any CPU + {540F9CC0-410A-48D4-B44E-8B3845C66F0B}.Release|x86.Build.0 = Release|Any CPU + {F56E27F2-A034-4268-BF1A-9D211648D999}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F56E27F2-A034-4268-BF1A-9D211648D999}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F56E27F2-A034-4268-BF1A-9D211648D999}.Debug|x64.ActiveCfg = Debug|Any CPU + {F56E27F2-A034-4268-BF1A-9D211648D999}.Debug|x64.Build.0 = Debug|Any CPU + {F56E27F2-A034-4268-BF1A-9D211648D999}.Debug|x86.ActiveCfg = Debug|Any CPU + {F56E27F2-A034-4268-BF1A-9D211648D999}.Debug|x86.Build.0 = Debug|Any CPU + {F56E27F2-A034-4268-BF1A-9D211648D999}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F56E27F2-A034-4268-BF1A-9D211648D999}.Release|Any CPU.Build.0 = Release|Any CPU + {F56E27F2-A034-4268-BF1A-9D211648D999}.Release|x64.ActiveCfg = Release|Any CPU + {F56E27F2-A034-4268-BF1A-9D211648D999}.Release|x64.Build.0 = Release|Any CPU + {F56E27F2-A034-4268-BF1A-9D211648D999}.Release|x86.ActiveCfg = Release|Any CPU + {F56E27F2-A034-4268-BF1A-9D211648D999}.Release|x86.Build.0 = Release|Any CPU + {850C9444-F85A-46FA-AE65-734A9AED1A0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {850C9444-F85A-46FA-AE65-734A9AED1A0B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {850C9444-F85A-46FA-AE65-734A9AED1A0B}.Debug|x64.ActiveCfg = Debug|Any CPU + {850C9444-F85A-46FA-AE65-734A9AED1A0B}.Debug|x64.Build.0 = Debug|Any CPU + {850C9444-F85A-46FA-AE65-734A9AED1A0B}.Debug|x86.ActiveCfg = Debug|Any CPU + {850C9444-F85A-46FA-AE65-734A9AED1A0B}.Debug|x86.Build.0 = Debug|Any CPU + {850C9444-F85A-46FA-AE65-734A9AED1A0B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {850C9444-F85A-46FA-AE65-734A9AED1A0B}.Release|Any CPU.Build.0 = Release|Any CPU + {850C9444-F85A-46FA-AE65-734A9AED1A0B}.Release|x64.ActiveCfg = Release|Any CPU + {850C9444-F85A-46FA-AE65-734A9AED1A0B}.Release|x64.Build.0 = Release|Any CPU + {850C9444-F85A-46FA-AE65-734A9AED1A0B}.Release|x86.ActiveCfg = Release|Any CPU + {850C9444-F85A-46FA-AE65-734A9AED1A0B}.Release|x86.Build.0 = Release|Any CPU + {67AEF7CC-BDC4-43D0-8627-9C807502A6EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {67AEF7CC-BDC4-43D0-8627-9C807502A6EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {67AEF7CC-BDC4-43D0-8627-9C807502A6EE}.Debug|x64.ActiveCfg = Debug|Any CPU + {67AEF7CC-BDC4-43D0-8627-9C807502A6EE}.Debug|x64.Build.0 = Debug|Any CPU + {67AEF7CC-BDC4-43D0-8627-9C807502A6EE}.Debug|x86.ActiveCfg = Debug|Any CPU + {67AEF7CC-BDC4-43D0-8627-9C807502A6EE}.Debug|x86.Build.0 = Debug|Any CPU + {67AEF7CC-BDC4-43D0-8627-9C807502A6EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {67AEF7CC-BDC4-43D0-8627-9C807502A6EE}.Release|Any CPU.Build.0 = Release|Any CPU + {67AEF7CC-BDC4-43D0-8627-9C807502A6EE}.Release|x64.ActiveCfg = Release|Any CPU + {67AEF7CC-BDC4-43D0-8627-9C807502A6EE}.Release|x64.Build.0 = Release|Any CPU + {67AEF7CC-BDC4-43D0-8627-9C807502A6EE}.Release|x86.ActiveCfg = Release|Any CPU + {67AEF7CC-BDC4-43D0-8627-9C807502A6EE}.Release|x86.Build.0 = Release|Any CPU + {3B17B627-D157-47C8-8F1A-4A768ADA0F74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B17B627-D157-47C8-8F1A-4A768ADA0F74}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B17B627-D157-47C8-8F1A-4A768ADA0F74}.Debug|x64.ActiveCfg = Debug|Any CPU + {3B17B627-D157-47C8-8F1A-4A768ADA0F74}.Debug|x64.Build.0 = Debug|Any CPU + {3B17B627-D157-47C8-8F1A-4A768ADA0F74}.Debug|x86.ActiveCfg = Debug|Any CPU + {3B17B627-D157-47C8-8F1A-4A768ADA0F74}.Debug|x86.Build.0 = Debug|Any CPU + {3B17B627-D157-47C8-8F1A-4A768ADA0F74}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3B17B627-D157-47C8-8F1A-4A768ADA0F74}.Release|Any CPU.Build.0 = Release|Any CPU + {3B17B627-D157-47C8-8F1A-4A768ADA0F74}.Release|x64.ActiveCfg = Release|Any CPU + {3B17B627-D157-47C8-8F1A-4A768ADA0F74}.Release|x64.Build.0 = Release|Any CPU + {3B17B627-D157-47C8-8F1A-4A768ADA0F74}.Release|x86.ActiveCfg = Release|Any CPU + {3B17B627-D157-47C8-8F1A-4A768ADA0F74}.Release|x86.Build.0 = Release|Any CPU + {150103E0-BAED-4EB7-BB3A-7871D5E5EB22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {150103E0-BAED-4EB7-BB3A-7871D5E5EB22}.Debug|Any CPU.Build.0 = Debug|Any CPU + {150103E0-BAED-4EB7-BB3A-7871D5E5EB22}.Debug|x64.ActiveCfg = Debug|Any CPU + {150103E0-BAED-4EB7-BB3A-7871D5E5EB22}.Debug|x64.Build.0 = Debug|Any CPU + {150103E0-BAED-4EB7-BB3A-7871D5E5EB22}.Debug|x86.ActiveCfg = Debug|Any CPU + {150103E0-BAED-4EB7-BB3A-7871D5E5EB22}.Debug|x86.Build.0 = Debug|Any CPU + {150103E0-BAED-4EB7-BB3A-7871D5E5EB22}.Release|Any CPU.ActiveCfg = Release|Any CPU + {150103E0-BAED-4EB7-BB3A-7871D5E5EB22}.Release|Any CPU.Build.0 = Release|Any CPU + {150103E0-BAED-4EB7-BB3A-7871D5E5EB22}.Release|x64.ActiveCfg = Release|Any CPU + {150103E0-BAED-4EB7-BB3A-7871D5E5EB22}.Release|x64.Build.0 = Release|Any CPU + {150103E0-BAED-4EB7-BB3A-7871D5E5EB22}.Release|x86.ActiveCfg = Release|Any CPU + {150103E0-BAED-4EB7-BB3A-7871D5E5EB22}.Release|x86.Build.0 = Release|Any CPU + {A9379A83-FBDD-425F-8C4A-9EA60EC6D779}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A9379A83-FBDD-425F-8C4A-9EA60EC6D779}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A9379A83-FBDD-425F-8C4A-9EA60EC6D779}.Debug|x64.ActiveCfg = Debug|Any CPU + {A9379A83-FBDD-425F-8C4A-9EA60EC6D779}.Debug|x64.Build.0 = Debug|Any CPU + {A9379A83-FBDD-425F-8C4A-9EA60EC6D779}.Debug|x86.ActiveCfg = Debug|Any CPU + {A9379A83-FBDD-425F-8C4A-9EA60EC6D779}.Debug|x86.Build.0 = Debug|Any CPU + {A9379A83-FBDD-425F-8C4A-9EA60EC6D779}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A9379A83-FBDD-425F-8C4A-9EA60EC6D779}.Release|Any CPU.Build.0 = Release|Any CPU + {A9379A83-FBDD-425F-8C4A-9EA60EC6D779}.Release|x64.ActiveCfg = Release|Any CPU + {A9379A83-FBDD-425F-8C4A-9EA60EC6D779}.Release|x64.Build.0 = Release|Any CPU + {A9379A83-FBDD-425F-8C4A-9EA60EC6D779}.Release|x86.ActiveCfg = Release|Any CPU + {A9379A83-FBDD-425F-8C4A-9EA60EC6D779}.Release|x86.Build.0 = Release|Any CPU + {91681128-8B86-471D-82B4-2A7F0390569F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {91681128-8B86-471D-82B4-2A7F0390569F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {91681128-8B86-471D-82B4-2A7F0390569F}.Debug|x64.ActiveCfg = Debug|Any CPU + {91681128-8B86-471D-82B4-2A7F0390569F}.Debug|x64.Build.0 = Debug|Any CPU + {91681128-8B86-471D-82B4-2A7F0390569F}.Debug|x86.ActiveCfg = Debug|Any CPU + {91681128-8B86-471D-82B4-2A7F0390569F}.Debug|x86.Build.0 = Debug|Any CPU + {91681128-8B86-471D-82B4-2A7F0390569F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {91681128-8B86-471D-82B4-2A7F0390569F}.Release|Any CPU.Build.0 = Release|Any CPU + {91681128-8B86-471D-82B4-2A7F0390569F}.Release|x64.ActiveCfg = Release|Any CPU + {91681128-8B86-471D-82B4-2A7F0390569F}.Release|x64.Build.0 = Release|Any CPU + {91681128-8B86-471D-82B4-2A7F0390569F}.Release|x86.ActiveCfg = Release|Any CPU + {91681128-8B86-471D-82B4-2A7F0390569F}.Release|x86.Build.0 = Release|Any CPU + {61A10479-C5AC-4D81-B004-9BE69CC8ADDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {61A10479-C5AC-4D81-B004-9BE69CC8ADDD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {61A10479-C5AC-4D81-B004-9BE69CC8ADDD}.Debug|x64.ActiveCfg = Debug|Any CPU + {61A10479-C5AC-4D81-B004-9BE69CC8ADDD}.Debug|x64.Build.0 = Debug|Any CPU + {61A10479-C5AC-4D81-B004-9BE69CC8ADDD}.Debug|x86.ActiveCfg = Debug|Any CPU + {61A10479-C5AC-4D81-B004-9BE69CC8ADDD}.Debug|x86.Build.0 = Debug|Any CPU + {61A10479-C5AC-4D81-B004-9BE69CC8ADDD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {61A10479-C5AC-4D81-B004-9BE69CC8ADDD}.Release|Any CPU.Build.0 = Release|Any CPU + {61A10479-C5AC-4D81-B004-9BE69CC8ADDD}.Release|x64.ActiveCfg = Release|Any CPU + {61A10479-C5AC-4D81-B004-9BE69CC8ADDD}.Release|x64.Build.0 = Release|Any CPU + {61A10479-C5AC-4D81-B004-9BE69CC8ADDD}.Release|x86.ActiveCfg = Release|Any CPU + {61A10479-C5AC-4D81-B004-9BE69CC8ADDD}.Release|x86.Build.0 = Release|Any CPU + {E63FD1A4-3CBB-4DAD-80DE-185EF8586AA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E63FD1A4-3CBB-4DAD-80DE-185EF8586AA0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E63FD1A4-3CBB-4DAD-80DE-185EF8586AA0}.Debug|x64.ActiveCfg = Debug|Any CPU + {E63FD1A4-3CBB-4DAD-80DE-185EF8586AA0}.Debug|x64.Build.0 = Debug|Any CPU + {E63FD1A4-3CBB-4DAD-80DE-185EF8586AA0}.Debug|x86.ActiveCfg = Debug|Any CPU + {E63FD1A4-3CBB-4DAD-80DE-185EF8586AA0}.Debug|x86.Build.0 = Debug|Any CPU + {E63FD1A4-3CBB-4DAD-80DE-185EF8586AA0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E63FD1A4-3CBB-4DAD-80DE-185EF8586AA0}.Release|Any CPU.Build.0 = Release|Any CPU + {E63FD1A4-3CBB-4DAD-80DE-185EF8586AA0}.Release|x64.ActiveCfg = Release|Any CPU + {E63FD1A4-3CBB-4DAD-80DE-185EF8586AA0}.Release|x64.Build.0 = Release|Any CPU + {E63FD1A4-3CBB-4DAD-80DE-185EF8586AA0}.Release|x86.ActiveCfg = Release|Any CPU + {E63FD1A4-3CBB-4DAD-80DE-185EF8586AA0}.Release|x86.Build.0 = Release|Any CPU + {FB1F330C-502B-42FC-8D24-46A9106A0F2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FB1F330C-502B-42FC-8D24-46A9106A0F2A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FB1F330C-502B-42FC-8D24-46A9106A0F2A}.Debug|x64.ActiveCfg = Debug|Any CPU + {FB1F330C-502B-42FC-8D24-46A9106A0F2A}.Debug|x64.Build.0 = Debug|Any CPU + {FB1F330C-502B-42FC-8D24-46A9106A0F2A}.Debug|x86.ActiveCfg = Debug|Any CPU + {FB1F330C-502B-42FC-8D24-46A9106A0F2A}.Debug|x86.Build.0 = Debug|Any CPU + {FB1F330C-502B-42FC-8D24-46A9106A0F2A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FB1F330C-502B-42FC-8D24-46A9106A0F2A}.Release|Any CPU.Build.0 = Release|Any CPU + {FB1F330C-502B-42FC-8D24-46A9106A0F2A}.Release|x64.ActiveCfg = Release|Any CPU + {FB1F330C-502B-42FC-8D24-46A9106A0F2A}.Release|x64.Build.0 = Release|Any CPU + {FB1F330C-502B-42FC-8D24-46A9106A0F2A}.Release|x86.ActiveCfg = Release|Any CPU + {FB1F330C-502B-42FC-8D24-46A9106A0F2A}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {2C140CC4-00C6-4017-8CB3-68B32CC7C058} = {649A384F-36AE-432F-8AF5-D28674D77B7D} + {3AB4D374-88E7-4681-B9C7-2C3D57DF8DC8} = {DCD4DEB9-0ACD-4CA0-AAF6-A7298C908266} + {540F9CC0-410A-48D4-B44E-8B3845C66F0B} = {5F8AF5AE-CF52-4ECE-92B8-EE6F7F401E98} + {F56E27F2-A034-4268-BF1A-9D211648D999} = {5F8AF5AE-CF52-4ECE-92B8-EE6F7F401E98} + {850C9444-F85A-46FA-AE65-734A9AED1A0B} = {5F8AF5AE-CF52-4ECE-92B8-EE6F7F401E98} + {67AEF7CC-BDC4-43D0-8627-9C807502A6EE} = {5F8AF5AE-CF52-4ECE-92B8-EE6F7F401E98} + {3B17B627-D157-47C8-8F1A-4A768ADA0F74} = {5F8AF5AE-CF52-4ECE-92B8-EE6F7F401E98} + {150103E0-BAED-4EB7-BB3A-7871D5E5EB22} = {5F8AF5AE-CF52-4ECE-92B8-EE6F7F401E98} + {A9379A83-FBDD-425F-8C4A-9EA60EC6D779} = {5F8AF5AE-CF52-4ECE-92B8-EE6F7F401E98} + {91681128-8B86-471D-82B4-2A7F0390569F} = {5F8AF5AE-CF52-4ECE-92B8-EE6F7F401E98} + {61A10479-C5AC-4D81-B004-9BE69CC8ADDD} = {5F8AF5AE-CF52-4ECE-92B8-EE6F7F401E98} + {E63FD1A4-3CBB-4DAD-80DE-185EF8586AA0} = {5F8AF5AE-CF52-4ECE-92B8-EE6F7F401E98} + {FB1F330C-502B-42FC-8D24-46A9106A0F2A} = {5F8AF5AE-CF52-4ECE-92B8-EE6F7F401E98} + EndGlobalSection +EndGlobal diff --git a/README.md b/README.md index 809fe7e..eee8c9d 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ license - version + version csharp

diff --git a/Config/Shared/IsExternalInit.cs b/Shared/IsExternalInit.cs similarity index 100% rename from Config/Shared/IsExternalInit.cs rename to Shared/IsExternalInit.cs diff --git a/Tests/NetArgumentParser.Tests/Models/Configurations/OptionValueRestrictionParserGeneratorConfig.cs b/Tests/NetArgumentParser.Tests/Models/Configurations/OptionValueRestrictionParserGeneratorConfig.cs index c6b1c66..6095c2f 100644 --- a/Tests/NetArgumentParser.Tests/Models/Configurations/OptionValueRestrictionParserGeneratorConfig.cs +++ b/Tests/NetArgumentParser.Tests/Models/Configurations/OptionValueRestrictionParserGeneratorConfig.cs @@ -79,10 +79,8 @@ internal partial class OptionValueRestrictionParserGeneratorConfig public static Predicate LengthValueRestrictionPredicate { get; } = t => t >= 23; public static Predicate VerbosityValueRestrictionPredicate { get; } = t => t >= 0 && t <= 4; -#pragma warning disable SYSLIB1045 // Use GeneratedRegexAttribute to generate the regular expression implementation at compile time public static Predicate NameValueRestrictionPredicate { get; } = t => new Regex(NamePattern).IsMatch(t); public static Predicate PhoneValueRestrictionPredicate { get; } = t => new Regex(PhonePattern).IsMatch(t); -#pragma warning restore SYSLIB1045 // Use GeneratedRegexAttribute to generate the regular expression implementation at compile time public static Predicate DefaultValueTypeValueRestrictionPredicate { get; } = t => { diff --git a/Tests/NetArgumentParser.Tests/ParserGeneratorTests.cs b/Tests/NetArgumentParser.Tests/ParserGeneratorTests.cs index a61edee..18196e0 100644 --- a/Tests/NetArgumentParser.Tests/ParserGeneratorTests.cs +++ b/Tests/NetArgumentParser.Tests/ParserGeneratorTests.cs @@ -789,9 +789,7 @@ public void ConfigureParser_AllValueOptionTypes_ValueRestrictionsConfiguredCorre outputFilePathOption.ValueRestriction.IsValueAllowed.Invoke(path)); } -#pragma warning disable CA2263 // Prefer generic overload when type is known FileMode[] fileModes = (FileMode[])Enum.GetValues(typeof(FileMode)); -#pragma warning restore CA2263 // Prefer generic overload when type is known foreach (FileMode fileMode in fileModes) { @@ -1197,9 +1195,7 @@ private static void VerifyComplexParserGeneratorConfigQuantum(ParserQuantum quan if (ComplexParserGeneratorConfig.ModeUseDefaultChoices && ComplexParserGeneratorConfig.ModeChoices is null) { -#pragma warning disable CA2263 // Prefer generic overload when type is known FileMode[] expectedChoices = (FileMode[])Enum.GetValues(typeof(FileMode)); -#pragma warning restore CA2263 // Prefer generic overload when type is known Assert.True(expectedChoices.ScrambledEquals(modeOption.Choices)); } else