Permalink
Browse files

premature error handling

  • Loading branch information...
1 parent 5a56e02 commit 13baef8b02b26c8d365c750fa5531e40ca9e20b5 @adrianaisemberg committed Mar 15, 2012
Showing with 381 additions and 58 deletions.
  1. +22 −2 CLAP/Exceptions.cs
  2. +36 −23 CLAP/HelpGenerator.cs
  3. +9 −2 CLAP/HelpInfo.cs
  4. +63 −17 CLAP/MultiParser.cs
  5. +1 −1 CLAP/ParametersExpressionValidator.cs
  6. +72 −6 CLAP/ParserRunner.cs
  7. +20 −6 ConsoleTest/Program.cs
  8. +123 −0 Tests/Samples.cs
  9. +35 −1 Tests/Tests.cs
View
@@ -382,7 +382,7 @@ public InvalidHelpHandlerException(MethodInfo method, Exception ex)
public class AmbiguousParameterDefaultException : CommandLineParserException
{
/// <summary>
- /// The method that is defined as help
+ /// The parameter that has both a Default and a DefaultProvider
/// </summary>
public ParameterInfo Parameter { get; private set; }
@@ -402,7 +402,7 @@ public AmbiguousParameterDefaultException(ParameterInfo parameter)
public class InvalidParameterDefaultProviderException : CommandLineParserException
{
/// <summary>
- /// The method that is defined as help
+ /// The parameter that has an invalid DefaultProvider
/// </summary>
public ParameterInfo Parameter { get; private set; }
@@ -417,4 +417,24 @@ public InvalidParameterDefaultProviderException(ParameterInfo parameter)
System.Runtime.Serialization.StreamingContext context)
: base(info, context) { }
}
+
+ [Serializable]
+ public class DuplicateGlobalHandlerException : CommandLineParserException
+ {
+ /// <summary>
+ /// The global handler name
+ /// </summary>
+ public string Name { get; private set; }
+
+ public DuplicateGlobalHandlerException(string name)
+ : base("Global parameter '{0}' is defined more than once".FormatWith(name))
+ {
+ Name = name;
+ }
+
+ protected DuplicateGlobalHandlerException(
+ System.Runtime.Serialization.SerializationInfo info,
+ System.Runtime.Serialization.StreamingContext context)
+ : base(info, context) { }
+ }
}
View
@@ -3,6 +3,7 @@
#if !FW2
using System.Linq;
+using System;
#endif
namespace CLAP
@@ -47,7 +48,7 @@ private static string GetHelpString(HelpInfo helpInfo)
{
var parser = helpInfo.Parsers[i];
- foreach (var verb in parser.Verbs.OrderBy(v => v.Names.First()))
+ foreach (var verb in parser.Verbs.OrderByDescending(v => v.IsDefault).ThenBy(v => v.Names.First()))
{
sb.AppendLine();
sb.Append(verbsLead);
@@ -57,26 +58,38 @@ private static string GetHelpString(HelpInfo helpInfo)
sb.AppendFormat("{0}.", parser.Type.Name.ToLowerInvariant());
}
- sb.AppendLine(verb.Names.StringJoin("|").ToLowerInvariant());
+ sb.Append(verb.Names.StringJoin("|").ToLowerInvariant());
+
+ if (verb.IsDefault)
+ {
+ sb.Append(" (Default)");
+ }
+
+ if (!string.IsNullOrEmpty(verb.Description))
+ {
+ sb.AppendFormat(": {0}", verb.Description);
+ }
+
+ sb.AppendLine();
if (verb.Parameters.Any())
{
- var longestParameter = verb.Parameters.Max(p => p.Names.StringJoin("|").Length);
+ var longestParameter = verb.Parameters.Max(p => p.Names.StringJoin(" /").Length);
var longestType = verb.Parameters.Max(p => p.Type.GetGenericTypeName().Length);
foreach (var p in verb.Parameters.OrderBy(p => p.Names.First()))
{
sb.Append(parametersLead);
sb.AppendFormat("/{0} : ",
- p.Names.StringJoin("|").ToLowerInvariant().PadRight(longestParameter, ' '));
-
- sb.AppendFormat("<{0}> ", p.Type.GetGenericTypeName());
+ p.Names.StringJoin(" /").ToLowerInvariant().PadRight(longestParameter, ' '));
if (!string.IsNullOrEmpty(p.Description))
{
sb.AppendFormat("{0} ", p.Description);
}
+ sb.AppendFormat("({0}) ", GetTypeName(p.Type));
+
if (p.Required)
{
sb.Append("(Required) ");
@@ -114,31 +127,23 @@ private static string GetHelpString(HelpInfo helpInfo)
if (parser.Globals.Any())
{
sb.AppendLine();
+ sb.Append(verbsLead);
+ sb.AppendLine("Global Parameters:");
var longestGlobal = parser.Globals.Max(p => p.Names.StringJoin("|").Length);
foreach (var g in parser.Globals.OrderBy(g => g.Names.First()))
{
- sb.Append(verbsLead);
+ sb.Append(parametersLead);
sb.AppendFormat("/{0} : ",
g.Names.StringJoin("|").ToLowerInvariant().PadRight(longestGlobal, ' '));
- sb.AppendFormat("<{0}> ", g.Type.GetGenericTypeName());
-
if (!string.IsNullOrEmpty(g.Description))
{
sb.AppendFormat("{0} ", g.Description);
}
- if (g.Required)
- {
- sb.Append("(Required) ");
- }
-
- if (g.Default != null)
- {
- sb.AppendFormat("(Default = {0}) ", g.Default);
- }
+ sb.AppendFormat("({0}) ", GetTypeName(g.Type));
if (g.Validations.Any())
{
@@ -160,14 +165,24 @@ private static string GetHelpString(HelpInfo helpInfo)
return sb.ToString();
}
+ private static string GetTypeName(Type type)
+ {
+ if (type.IsEnum)
+ {
+ return string.Format("{0} ({1})", type.Name, string.Join("/", Enum.GetNames(type)));
+ }
+
+ return type.GetGenericTypeName();
+ }
+
private static ParserHelpInfo GetParserHelp(ParserRunner parser)
{
return new ParserHelpInfo
{
Type = parser.Type,
Verbs = parser.GetVerbs().Select(verb => new VerbHelpInfo
{
- Names = verb.Names.OrderBy(n => n.Length).ToList(),
+ Names = verb.Names.OrderByDescending(n => n.Length).ToList(),
Description = verb.Description,
IsDefault = verb.IsDefault,
Validations = verb.MethodInfo.GetInterfaceAttributes<ICollectionValidation>().Select(v => v.Description).ToList(),
@@ -187,17 +202,15 @@ private static ParserHelpInfo GetParserHelp(ParserRunner parser)
var att = g.GetAttribute<GlobalAttribute>();
var parameter = ParserRunner.GetParameters(g).FirstOrDefault();
- return new ParameterHelpInfo
+ return new GlobalParameterHelpInfo
{
- IsGlobal = true,
Names = att.Aliases.CommaSplit().Union(new[] { att.Name ?? g.Name }).OrderBy(n => n.Length).ToList(),
Type = parameter != null ? parameter.ParameterInfo.ParameterType : typeof(bool),
Description = att.Description,
Validations = g.GetInterfaceAttributes<ICollectionValidation>().Select(v => v.Description).ToList(),
};
- }).Union(parser.Register.RegisteredGlobalHandlers.Values.Select(handler => new ParameterHelpInfo
+ }).Union(parser.Register.RegisteredGlobalHandlers.Values.Select(handler => new GlobalParameterHelpInfo
{
- IsGlobal = true,
Names = handler.Names.OrderBy(n => n.Length).ToList(),
Type = handler.Type,
Description = handler.Desription,
View
@@ -12,7 +12,7 @@ internal class ParserHelpInfo
{
internal Type Type { get; set; }
internal List<VerbHelpInfo> Verbs { get; set; }
- internal List<ParameterHelpInfo> Globals { get; set; }
+ internal List<GlobalParameterHelpInfo> Globals { get; set; }
}
internal class VerbHelpInfo
@@ -32,6 +32,13 @@ internal class ParameterHelpInfo
internal Type Type { get; set; }
internal object Default { get; set; }
internal string Description { get; set; }
- internal bool IsGlobal { get; set; }
+ }
+
+ internal class GlobalParameterHelpInfo
+ {
+ internal List<string> Names { get; set; }
+ internal List<string> Validations { get; set; }
+ internal Type Type { get; set; }
+ internal string Description { get; set; }
}
}
View
@@ -57,12 +57,12 @@ private void Init()
{
Debug.Assert(m_types.Any());
+ Register = new ParserRegistration(m_types, GetHelpString, ValuesFactory.GetValueForParameter);
+
foreach (var type in m_types)
{
- ParserRunner.Validate(type);
+ ParserRunner.Validate(type, Register);
}
-
- Register = new ParserRegistration(m_types, GetHelpString, ValuesFactory.GetValueForParameter);
}
private void HandleEmptyArguments(object[] targets)
@@ -183,26 +183,42 @@ public void RunStatic(string[] args)
/// <param name="targets">The instances of the verb classes</param>
public void RunTargets(string[] args, params object[] targets)
{
- // no args
- //
- if (args.None() || args.All(a => string.IsNullOrEmpty(a)))
+ ParserRunner parser = null;
+
+ try
{
- HandleEmptyArguments(targets);
+ // no args
+ //
+ if (args.None() || args.All(a => string.IsNullOrEmpty(a)))
+ {
+ HandleEmptyArguments(targets);
- return;
- }
+ return;
+ }
- ParserRunner parser;
+ if (m_types.Length == 1)
+ {
+ parser = GetSingleTypeParser(args, targets, Register);
+ }
+ else
+ {
+ Debug.Assert(m_types.Length > 1);
- if (m_types.Length == 1)
- {
- parser = GetSingleTypeParser(args, targets, Register);
+ parser = GetMultiTypesParser(args, targets, Register);
+ }
}
- else
+ catch (Exception ex)
{
- Debug.Assert(m_types.Length > 1);
-
- parser = GetMultiTypesParser(args, targets, Register);
+ // handle error using the first available error handler
+ //
+ if (TryHandlePrematureError(ex, targets))
+ {
+ return;
+ }
+ else
+ {
+ throw;
+ }
}
Debug.Assert(parser != null);
@@ -216,6 +232,36 @@ public void RunTargets(string[] args, params object[] targets)
parser.Run(args, target);
}
+ private bool TryHandlePrematureError(Exception ex, object[] targets)
+ {
+ if (Register.RegisteredErrorHandler != null)
+ {
+ Register.RegisteredErrorHandler(new ExceptionContext(ex));
+
+ return true;
+ }
+ else
+ {
+ for (int i = 0; i < m_types.Length; i++)
+ {
+ var type = m_types[i];
+
+ var errorHandler = ParserRunner.GetDefinedErrorHandlers(type).FirstOrDefault();
+
+ if (errorHandler != null)
+ {
+ var target = targets == null ? null : targets[i];
+
+ errorHandler.Invoke(target, new[] { new ExceptionContext(ex) });
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
/// <summary>
/// Gets a help string that describes all the parser information for the user
/// </summary>
@@ -51,7 +51,7 @@ public void Validate(ValueInfo[] parameters)
if (!selected.Any())
{
- throw new ValidationException(string.Format("Expression failed validation: '{0}' for arguments: [{1}]",
+ throw new ValidationException("Expression failed validation: '{0}' for arguments: [{1}]".FormatWith(
Expression,
parameters.Select(
p => "{0}={1}".FormatWith(
Oops, something went wrong.

0 comments on commit 13baef8

Please sign in to comment.