Make exceptions slightly more friendly

This commit is contained in:
Alexey Golub
2019-12-16 22:58:31 +02:00
parent 6ce52c70f7
commit ed87373dc3
3 changed files with 32 additions and 14 deletions

View File

@@ -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}.");
}
}
}

View File

@@ -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.");
}
/// <inheritdoc />
@@ -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);
}
}

View File

@@ -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<CommandSchema>();
@@ -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