// Copyright 2005-2015 Giacomo Stelluti Scala & Contributors. All rights reserved. See License.md in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
namespace CommandLine
{
///
/// Discriminator enumeration of derivates.
///
public enum ErrorType
{
///
/// Value of type.
///
BadFormatTokenError,
///
/// Value of type.
///
MissingValueOptionError,
///
/// Value of type.
///
UnknownOptionError,
///
/// Value of type.
///
MissingRequiredOptionError,
///
/// Value of type.
///
MutuallyExclusiveSetError,
///
/// Value of type.
///
BadFormatConversionError,
///
/// Value of type.
///
SequenceOutOfRangeError,
///
/// Value of type.
///
RepeatedOptionError,
///
/// Value of type.
///
NoVerbSelectedError,
///
/// Value of type.
///
BadVerbSelectedError,
///
/// Value of type.
///
HelpRequestedError,
///
/// Value of type.
///
HelpVerbRequestedError,
///
/// Value of type.
///
VersionRequestedError,
///
/// Value of type.
///
SetValueExceptionError,
///
/// Value of type.
///
InvalidAttributeConfigurationError,
///
/// Value of type.
///
MissingGroupOptionError,
///
/// Value of type.
///
GroupOptionAmbiguityError,
///
/// Value of type.
///
MultipleDefaultVerbsError
}
///
/// Base type of all errors.
///
/// All errors are defined within the system. There's no reason to create custom derivate types.
public abstract class Error : IEquatable
{
private readonly ErrorType tag;
private readonly bool stopsProcessing;
///
/// Initializes a new instance of the class.
///
/// Type discriminator tag.
/// Tells if error stops parsing process.
protected internal Error(ErrorType tag, bool stopsProcessing)
{
this.tag = tag;
this.stopsProcessing = stopsProcessing;
}
///
/// Initializes a new instance of the class.
///
/// Type discriminator tag.
protected internal Error(ErrorType tag)
: this(tag, false)
{
}
///
/// Error type discriminator, defined as enumeration.
///
public ErrorType Tag
{
get { return tag; }
}
///
/// Tells if error stops parsing process.
/// Filtered by .
///
public bool StopsProcessing
{
get { return stopsProcessing; }
}
///
/// Determines whether the specified is equal to the current .
///
/// The to compare with the current .
/// true if the specified is equal to the current ; otherwise, false.
public override bool Equals(object obj)
{
var other = obj as Error;
if (other != null)
{
return Equals(other);
}
return base.Equals(obj);
}
///
/// Serves as a hash function for a particular type.
///
/// A hash code for the current .
public override int GetHashCode()
{
return new { Tag, StopsProcessing }.GetHashCode();
}
///
/// Returns a value that indicates whether the current instance and a specified have the same value.
///
/// The instance to compare.
/// true if this instance of and have the same value; otherwise, false.
public bool Equals(Error other)
{
if (other == null)
{
return false;
}
return Tag.Equals(other.Tag);
}
}
///
/// Base type of all errors related to bad token detection.
///
public abstract class TokenError : Error, IEquatable
{
private readonly string token;
///
/// Initializes a new instance of the class.
///
/// Error type.
/// Problematic token.
protected internal TokenError(ErrorType tag, string token)
: base(tag)
{
if (token == null) throw new ArgumentNullException("token");
this.token = token;
}
///
/// The string containing the token text.
///
public string Token
{
get { return token; }
}
///
/// Determines whether the specified is equal to the current .
///
/// The to compare with the current .
/// true if the specified is equal to the current ; otherwise, false.
public override bool Equals(object obj)
{
var other = obj as TokenError;
if (other != null)
{
return Equals(other);
}
return base.Equals(obj);
}
///
/// Serves as a hash function for a particular type.
///
/// A hash code for the current .
public override int GetHashCode()
{
return new { Tag, StopsProcessing, Token }.GetHashCode();
}
///
/// Returns a value that indicates whether the current instance and a specified have the same value.
///
/// The instance to compare.
/// true if this instance of and have the same value; otherwise, false.
public bool Equals(TokenError other)
{
if (other == null)
{
return false;
}
return Tag.Equals(other.Tag) && Token.Equals(other.Token);
}
}
///
/// Models an error generated when an invalid token is detected.
///
public sealed class BadFormatTokenError : TokenError
{
internal BadFormatTokenError(string token)
: base(ErrorType.BadFormatTokenError, token)
{
}
}
///
/// Base type of all erros with name information.
///
public abstract class NamedError : Error, IEquatable
{
private readonly NameInfo nameInfo;
///
/// Initializes a new instance of the class.
///
/// Error type.
/// Problematic name.
protected internal NamedError(ErrorType tag, NameInfo nameInfo)
: base(tag)
{
this.nameInfo = nameInfo;
}
///
/// Name information relative to this error instance.
///
public NameInfo NameInfo
{
get { return nameInfo; }
}
///
/// Determines whether the specified is equal to the current .
///
/// The to compare with the current .
/// true if the specified is equal to the current ; otherwise, false.
public override bool Equals(object obj)
{
var other = obj as NamedError;
if (other != null)
{
return Equals(other);
}
return base.Equals(obj);
}
///
/// Serves as a hash function for a particular type.
///
/// A hash code for the current .
public override int GetHashCode()
{
return new { Tag, StopsProcessing, NameInfo }.GetHashCode();
}
///
/// Returns a value that indicates whether the current instance and a specified have the same value.
///
/// The instance to compare.
/// true if this instance of and have the same value; otherwise, false.
public bool Equals(NamedError other)
{
if (other == null)
{
return false;
}
return Tag.Equals(other.Tag) && NameInfo.Equals(other.NameInfo);
}
}
///
/// Models an error generated when an option lacks its value.
///
public sealed class MissingValueOptionError : NamedError
{
internal MissingValueOptionError(NameInfo nameInfo)
: base(ErrorType.MissingValueOptionError, nameInfo)
{
}
}
///
/// Models an error generated when an unknown option is detected.
///
public sealed class UnknownOptionError : TokenError
{
internal UnknownOptionError(string token)
: base(ErrorType.UnknownOptionError, token)
{
}
}
///
/// Models an error generated when a required option is required.
///
public sealed class MissingRequiredOptionError : NamedError
{
internal MissingRequiredOptionError(NameInfo nameInfo)
: base(ErrorType.MissingRequiredOptionError, nameInfo)
{
}
}
///
/// Models an error generated when a an option from another set is defined.
///
public sealed class MutuallyExclusiveSetError : NamedError
{
private readonly string setName;
internal MutuallyExclusiveSetError(NameInfo nameInfo, string setName)
: base(ErrorType.MutuallyExclusiveSetError, nameInfo)
{
this.setName = setName;
}
///
/// Option's set name.
///
public string SetName
{
get { return setName; }
}
}
///
/// Models an error generated when a value conversion fails.
///
public sealed class BadFormatConversionError : NamedError
{
internal BadFormatConversionError(NameInfo nameInfo)
: base(ErrorType.BadFormatConversionError, nameInfo)
{
}
}
///
/// Models an error generated when a sequence value lacks elements.
///
public sealed class SequenceOutOfRangeError : NamedError
{
internal SequenceOutOfRangeError(NameInfo nameInfo)
: base(ErrorType.SequenceOutOfRangeError, nameInfo)
{
}
}
///
/// Models an error generated when an option is repeated two or more times.
///
public sealed class RepeatedOptionError : NamedError
{
internal RepeatedOptionError(NameInfo nameInfo)
: base(ErrorType.RepeatedOptionError, nameInfo)
{
}
}
///
/// Models an error generated when an unknown verb is detected.
///
public sealed class BadVerbSelectedError : TokenError
{
internal BadVerbSelectedError(string token)
: base(ErrorType.BadVerbSelectedError, token)
{
}
}
///
/// Models an error generated when a user explicitly requests help.
///
public sealed class HelpRequestedError : Error
{
internal HelpRequestedError()
: base(ErrorType.HelpRequestedError, true)
{
}
}
///
/// Models an error generated when a user explicitly requests help in verb commands scenario.
///
public sealed class HelpVerbRequestedError : Error
{
private readonly string verb;
private readonly Type type;
private readonly bool matched;
internal HelpVerbRequestedError(string verb, Type type, bool matched)
: base(ErrorType.HelpVerbRequestedError, true)
{
this.verb = verb;
this.type = type;
this.matched = matched;
}
///
/// Verb command string.
///
public string Verb
{
get { return verb; }
}
///
/// of verb command.
///
public Type Type
{
get { return type; }
}
///
/// true if verb command is found; otherwise false.
///
public bool Matched
{
get { return matched; }
}
}
///
/// Models an error generated when no verb is selected.
///
public sealed class NoVerbSelectedError : Error
{
internal NoVerbSelectedError()
: base(ErrorType.NoVerbSelectedError)
{
}
}
///
/// Models an error generated when a user explicitly requests version.
///
public sealed class VersionRequestedError : Error
{
internal VersionRequestedError()
: base(ErrorType.VersionRequestedError, true)
{
}
}
///
/// Models as error generated when exception is thrown at Property.SetValue
///
public sealed class SetValueExceptionError : NamedError
{
private readonly Exception exception;
private readonly object value;
internal SetValueExceptionError(NameInfo nameInfo, Exception exception, object value)
: base(ErrorType.SetValueExceptionError, nameInfo)
{
this.exception = exception;
this.value = value;
}
///
/// The expection thrown from Property.SetValue
///
public Exception Exception
{
get { return exception; }
}
///
/// The value that had to be set to the property
///
public object Value
{
get { return value; }
}
}
///
/// Models an error generated when an invalid token is detected.
///
public sealed class InvalidAttributeConfigurationError : Error
{
public const string ErrorMessage = "Check if Option or Value attribute values are set properly for the given type.";
internal InvalidAttributeConfigurationError()
: base(ErrorType.InvalidAttributeConfigurationError, true)
{
}
}
public sealed class MissingGroupOptionError : Error, IEquatable, IEquatable
{
public const string ErrorMessage = "At least one option in a group must have value.";
private readonly string group;
private readonly IEnumerable names;
internal MissingGroupOptionError(string group, IEnumerable names)
: base(ErrorType.MissingGroupOptionError)
{
this.group = group;
this.names = names;
}
public string Group
{
get { return group; }
}
public IEnumerable Names
{
get { return names; }
}
public new bool Equals(Error obj)
{
var other = obj as MissingGroupOptionError;
if (other != null)
{
return Equals(other);
}
return base.Equals(obj);
}
public bool Equals(MissingGroupOptionError other)
{
if (other == null)
{
return false;
}
return Group.Equals(other.Group) && Names.SequenceEqual(other.Names);
}
}
public sealed class GroupOptionAmbiguityError : NamedError
{
public NameInfo Option;
internal GroupOptionAmbiguityError(NameInfo option)
: base(ErrorType.GroupOptionAmbiguityError, option)
{
Option = option;
}
}
///
/// Models an error generated when multiple default verbs are defined.
///
public sealed class MultipleDefaultVerbsError : Error
{
public const string ErrorMessage = "More than one default verb is not allowed.";
internal MultipleDefaultVerbsError()
: base(ErrorType.MultipleDefaultVerbsError)
{ }
}
}