-
Notifications
You must be signed in to change notification settings - Fork 0
ParseErrors
If any errors occured during argument parsing an erroneous ParseResult<T>
is returned. It doesn't contain Options
object, but contains non-null
Errors
collection. The library is designed to be resilient to any kind of input (with the exception of null
or in any other way invalid input collection itself), so any combination of input string
s must produce a ParseResult<T>
and not fail with an exception. All error-related functionality lives in ArgumentParsing.Results.Errors
namespace.
The Errors
property of a ParseResult<T>
is of type ParseErrorCollection
. This type represents a read-only collection of ParseError
s and is meant to be constructed only by the generated argument parser method. Given the nature of source generators, the way to construct this type has to be accessible to user's code, but that entry point is hidden from the IntelliSense and is not considered a part of public API. The library reserves the rights to change how the errors collection is constructed for any release without notice in the changelog.
The base abstract class for all possible errors is ParseError
. It has GetMessage()
method, which constructs a final error message with all the details about an error. This message is meant to be shown to the end user. ExecuteDefaults
implementation for the error scenario shows a help screen with errors section, in which it lists all error messages obtained through this GetMessage()
method. Other than that, ParseError
doesn't provide any additional functionality besides value-like equality and good implementation of GetHashCode()
.
Each parse error has its own dedicated type. These error types are all well-known and used by the generator. Arbitrary extending this error set is not supported.
All error types are public (thus can be used with is
check if desired). Each error exposes all the details about itself, e.g. UnknownOptionError
exposes OptionName
and ContainingArgument
, in which it was encountered. These details are obviously different for different errors and are used to construct a final error message with GetMessage()
method.
Final error messages are constructed via string.Format
method, supplyed with a message format and arguments. Each error has a default message format string. All these default messages can be found in this file in the source. It is possible to change message formats for all errors though. In order to do this, an error message format provider type is specified as ErrorMessageProvider
named argument in [GeneratedArgumentParser]
attribute:
using ArgumentParsing;
using ArgumentParsing.Results;
partial class Program
{
[GeneratedArgumentParser(ErrorMessageFormatProvider = typeof(CustomErrorMessageFormatProvider))]
private static partial ParseResult<Options> ParseArguments(string[] args);
}
public class CustomErrorMessageFormatProvider
{
// ...
}
[OptionsType]
class Options
{
}
In the example above CustomErrorMessageFormatProvider
is responsible for messages of all errors, which can occur during parsing of options type.
Each error must have a corresponding entry in the message provider. 'Entry' here is a statically accessible member of string
type. It can be a property or a constant, it only matters, that it can be accessed outside of the error message provider type in the same assembly, e.g. like CustomErrorMessageFormatProvider.UnrecognizedArgumentError
. The intent here is that a string resource will be used, which will return different values for different cultures, since error message localization is the primary target of this feature.
Error message formats correspond to the name of the error type, e.g. for DuplicateOptionError
the name of the message format member is also DuplicateOptionError
and so on. The only exception from this rule is MissingRequiredOptionError
. There are 3 possible cases for it:
- Missing option has only a short name. The name of the message format member is
MissingRequiredOptionError_OnlyShortOptionName
then - Missing option has only a long name. The name of the message format member is
MissingRequiredOptionError_OnlyLongOptionName
then - Missing option has both short and names. The name of the message format member is
MissingRequiredOptionError_BothOptionNames
then
Note
The default message format for MissingRequiredOptionError
is identical for case 1 and case 2 from above and correspond to a single MissingRequiredOptionError_OneOptionName
member in the default error message formats list. That's an implementation detail and I'm leaving this note here just to avoid potential confusion. MissingRequiredOptionError_OneOptionName
has no effect in a custom message format provider type. Of course, you are absolutly free to do the same and share the same resource string for MissingRequiredOptionError_OnlyShortOptionName
and MissingRequiredOptionError_OnlyLongOptionName
, but you will still need 2 different members pointing to a shared resource to achieve it
Given that a slightly different set of possible parse errors for various options types, the library doesn't provide any custom diagnostics for missing error message format strings. If you lack some message format members, you'll get a 'Missing member X' C# compiler error, pointing to the generated source when building your app, this is expected.