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 @@
-
+
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