diff --git a/CliFx/Services/CommandInitializer.cs b/CliFx/Services/CommandInitializer.cs
index e35d749..9cff52a 100644
--- a/CliFx/Services/CommandInitializer.cs
+++ b/CliFx/Services/CommandInitializer.cs
@@ -84,7 +84,7 @@ namespace CliFx.Services
if (unsetRequiredOptions.Any())
{
var unsetRequiredOptionNames = unsetRequiredOptions.Select(o => o.GetAliases().FirstOrDefault()).JoinToString(", ");
- throw new CliFxException($"One or more required options were not set: {unsetRequiredOptionNames}.");
+ throw new CliFxException($"Some of the required options were not provided: {unsetRequiredOptionNames}.");
}
}
}
diff --git a/CliFx/Services/CommandOptionInputConverter.cs b/CliFx/Services/CommandOptionInputConverter.cs
index c4006fc..c72d714 100644
--- a/CliFx/Services/CommandOptionInputConverter.cs
+++ b/CliFx/Services/CommandOptionInputConverter.cs
@@ -133,11 +133,16 @@ namespace CliFx.Services
catch (Exception ex)
{
// Wrap and rethrow exceptions that occur when trying to convert the value
- throw new CliFxException($"Can't convert value [{value}] to type [{targetType}].", ex);
+ throw new CliFxException(
+ $"Can't convert value [{value}] to type [{targetType}]. " +
+ "Provided value probably doesn't match the expected format. " +
+ $"Underlying exception message: {ex.Message}", ex);
}
// Throw if we can't find a way to convert the value
- throw new CliFxException($"Can't convert value [{value}] to type [{targetType}].");
+ throw new CliFxException(
+ $"Can't find a way to convert user input to type [{targetType}]. " +
+ "This type is not among the list of types supported by this library.");
}
///
@@ -192,12 +197,12 @@ namespace CliFx.Services
public partial class CommandOptionInputConverter
{
- private static ConstructorInfo GetStringConstructor(Type type) => type.GetConstructor(new[] {typeof(string)});
+ private static ConstructorInfo? GetStringConstructor(Type type) => type.GetConstructor(new[] {typeof(string)});
- private static MethodInfo GetStaticParseMethod(Type type) =>
+ private static MethodInfo? GetStaticParseMethod(Type type) =>
type.GetMethod("Parse", BindingFlags.Public | BindingFlags.Static, null, new[] {typeof(string)}, null);
- private static MethodInfo GetStaticParseMethodWithFormatProvider(Type type) =>
+ private static MethodInfo? GetStaticParseMethodWithFormatProvider(Type type) =>
type.GetMethod("Parse", BindingFlags.Public | BindingFlags.Static, null, new[] {typeof(string), typeof(IFormatProvider)}, null);
}
}
\ No newline at end of file
diff --git a/CliFx/Services/CommandSchemaResolver.cs b/CliFx/Services/CommandSchemaResolver.cs
index 23ff8be..8798319 100644
--- a/CliFx/Services/CommandSchemaResolver.cs
+++ b/CliFx/Services/CommandSchemaResolver.cs
@@ -42,8 +42,9 @@ namespace CliFx.Services
if (existingOptionWithSameName != null)
{
throw new CliFxException(
- $"Command type [{commandType}] has options defined with the same name: " +
- $"[{existingOptionWithSameName.Property}] and [{optionSchema.Property}].");
+ $"Command type [{commandType}] has two options that have the same name ({optionSchema.Name}): " +
+ $"[{existingOptionWithSameName.Property}] and [{optionSchema.Property}]. " +
+ "All options in a command need to have unique names (case-insensitive).");
}
// Make sure there are no other options with the same short name
@@ -54,8 +55,9 @@ namespace CliFx.Services
if (existingOptionWithSameShortName != null)
{
throw new CliFxException(
- $"Command type [{commandType}] has options defined with the same short name: " +
- $"[{existingOptionWithSameShortName.Property}] and [{optionSchema.Property}].");
+ $"Command type [{commandType}] has two options that have the same short name ({optionSchema.ShortName}): " +
+ $"[{existingOptionWithSameShortName.Property}] and [{optionSchema.Property}]. " +
+ "All options in a command need to have unique short names (case-sensitive).");
}
// Add schema to list
@@ -71,7 +73,9 @@ namespace CliFx.Services
// Make sure there's at least one command defined
if (!commandTypes.Any())
{
- throw new CliFxException("There are no commands defined.");
+ throw new CliFxException(
+ "There are no commands defined. " +
+ "An application needs to have at least one command to work.");
}
var result = new List();
@@ -81,7 +85,11 @@ namespace CliFx.Services
// Make sure command type implements ICommand.
if (!commandType.Implements(typeof(ICommand)))
{
- throw new CliFxException($"Command type [{commandType}] must implement {typeof(ICommand)}.");
+ throw new CliFxException(
+ $"Command type [{commandType}] needs to implement [{typeof(ICommand)}]."
+ + Environment.NewLine + Environment.NewLine +
+ $"public class {commandType.Name} : ICommand" + Environment.NewLine +
+ "// ^-- implement interface");
}
// Get attribute
@@ -90,7 +98,11 @@ namespace CliFx.Services
// Make sure attribute is set
if (attribute == null)
{
- throw new CliFxException($"Command type [{commandType}] must be annotated with [{typeof(CommandAttribute)}].");
+ throw new CliFxException(
+ $"Command type [{commandType}] needs to be annotated with [{typeof(CommandAttribute)}]."
+ + Environment.NewLine + Environment.NewLine +
+ "[Command] // <-- add attribute" + Environment.NewLine +
+ $"public class {commandType.Name} : ICommand");
}
// Get option schemas
@@ -109,7 +121,8 @@ namespace CliFx.Services
if (existingCommandWithSameName != null)
{
throw new CliFxException(
- $"Command type [{existingCommandWithSameName.Type}] has the same name as another command type [{commandType}].");
+ $"Command type [{existingCommandWithSameName.Type}] has the same name as another command type [{commandType}]. " +
+ "All commands need to have unique names (case-insensitive).");
}
// Add schema to list