1
0
mirror of https://github.com/CLIUtils/CLI11.git synced 2025-04-29 12:13:52 +00:00

Moving code to Error, better ArgumentMismatch throwing

This commit is contained in:
Henry Fredrick Schreiner 2017-11-26 08:54:14 -05:00 committed by Henry Schreiner
parent 4d5bff2393
commit f6c9ce6109
6 changed files with 52 additions and 23 deletions

View File

@ -452,7 +452,7 @@ class App {
CLI::callback_t fun = [&member, options, simple_name](CLI::results_t res) {
bool retval = detail::lexical_cast(res[0], member);
if(!retval)
throw ConversionError("The value " + res[0] + "is not an allowed value for " + simple_name);
throw ConversionError(res[0], simple_name);
return std::find(std::begin(options), std::end(options), member) != std::end(options);
};
@ -475,7 +475,7 @@ class App {
CLI::callback_t fun = [&member, options, simple_name](CLI::results_t res) {
bool retval = detail::lexical_cast(res[0], member);
if(!retval)
throw ConversionError("The value " + res[0] + "is not an allowed value for " + simple_name);
throw ConversionError(res[0], simple_name);
return std::find(std::begin(options), std::end(options), member) != std::end(options);
};
@ -504,7 +504,7 @@ class App {
return detail::to_lower(val) == member;
});
if(iter == std::end(options))
throw ConversionError("The value " + member + "is not an allowed value for " + simple_name);
throw ConversionError(member, simple_name);
else {
member = *iter;
return true;
@ -533,7 +533,7 @@ class App {
return detail::to_lower(val) == member;
});
if(iter == std::end(options))
throw ConversionError("The value " + member + "is not an allowed value for " + simple_name);
throw ConversionError(member, simple_name);
else {
member = *iter;
return true;
@ -1149,12 +1149,7 @@ class App {
// Required but empty
if(opt->get_required() && opt->count() == 0)
throw RequiredError(opt->help_name() + " is required");
// Partially filled
if(opt->get_expected() > 0 && static_cast<int>(opt->count()) < opt->get_expected())
throw RequiredError(opt->help_name() + " requires " + std::to_string(opt->get_expected()) +
" arguments");
throw RequiredError(opt->single_name() + " is required");
}
// Requires
for(const Option *opt_req : opt->requires_)
@ -1409,8 +1404,8 @@ class App {
}
if(num > 0) {
throw RequiredError(op->single_name() + ": " + std::to_string(num) + " required " +
op->get_type_name() + " missing");
throw ArgumentMismatch(op->single_name() + ": " + std::to_string(num) + " required " +
op->get_type_name() + " missing");
}
}
@ -1490,8 +1485,8 @@ class App {
args.pop_back();
}
if(num > 0) {
throw RequiredError(op->single_name() + ": " + std::to_string(num) + " required " +
op->get_type_name() + " missing");
throw ArgumentMismatch(op->single_name() + ": " + std::to_string(num) + " required " +
op->get_type_name() + " missing");
}
}
return;

View File

@ -126,19 +126,22 @@ class RuntimeError : public ParseError {
/// Thrown when parsing an INI file and it is missing
class FileError : public ParseError {
CLI11_ERROR_DEF(ParseError, FileError)
FileError(std::string msg) : FileError(msg, ExitCodes::File) {}
FileError(std::string name) : FileError(name + " was not readable (missing?)", ExitCodes::File) {}
};
/// Thrown when conversion call back fails, such as when an int fails to coerce to a string
class ConversionError : public ParseError {
CLI11_ERROR_DEF(ParseError, ConversionError)
CLI11_ERROR_SIMPLE(ConversionError)
ConversionError(std::string member, std::string name)
: ConversionError("The value " + member + "is not an allowed value for " + name) {}
};
/// Thrown when validation of results fails
class ValidationError : public ParseError {
CLI11_ERROR_DEF(ParseError, ValidationError)
CLI11_ERROR_SIMPLE(ValidationError)
ValidationError(std::string name, std::string msg) : ValidationError(name + ": " + msg) {}
};
/// Thrown when a required option is missing
@ -150,6 +153,7 @@ class RequiredError : public ParseError {
/// Thrown when the wrong number of arguments has been recieved
class ArgumentMismatch : ParseError {
CLI11_ERROR_DEF(ParseError, ArgumentMismatch)
CLI11_ERROR_SIMPLE(ArgumentMismatch)
ArgumentMismatch(std::string name, int expected, size_t recieved)
: ArgumentMismatch(expected > 0 ? ("Expected exactly " + std::to_string(expected) + " arguments to " + name +
", got " + std::to_string(recieved))

View File

@ -106,7 +106,7 @@ inline std::vector<ini_ret_t> parse_ini(const std::string &name) {
std::ifstream input{name};
if(!input.good())
throw FileError(name + " was not readable (missing?)");
throw FileError(name);
return parse_ini(input);
}

View File

@ -438,7 +438,7 @@ class Option : public OptionBase<Option> {
for(const std::function<std::string(std::string &)> &vali : validators_) {
std::string err_msg = vali(result);
if(!err_msg.empty())
throw ValidationError(single_name() + ": " + err_msg);
throw ValidationError(single_name(), err_msg);
}
}

View File

@ -243,6 +243,26 @@ TEST_F(TApp, MissingValueNonRequiredOpt) {
EXPECT_ANY_THROW(run());
}
TEST_F(TApp, NotRequiredOptsSingle) {
std::string str;
app.add_option("--str", str);
args = {"--str"};
EXPECT_THROW(run(), CLI::ArgumentMismatch);
}
TEST_F(TApp, NotRequiredOptsSingleShort) {
std::string str;
app.add_option("-s", str);
args = {"-s"};
EXPECT_THROW(run(), CLI::ArgumentMismatch);
}
TEST_F(TApp, RequiredOptsSingle) {
std::string str;
@ -250,7 +270,7 @@ TEST_F(TApp, RequiredOptsSingle) {
args = {"--str"};
EXPECT_THROW(run(), CLI::RequiredError);
EXPECT_THROW(run(), CLI::ArgumentMismatch);
}
TEST_F(TApp, RequiredOptsSingleShort) {
@ -260,7 +280,7 @@ TEST_F(TApp, RequiredOptsSingleShort) {
args = {"-s"};
EXPECT_THROW(run(), CLI::RequiredError);
EXPECT_THROW(run(), CLI::ArgumentMismatch);
}
TEST_F(TApp, RequiredOptsDouble) {
@ -270,7 +290,7 @@ TEST_F(TApp, RequiredOptsDouble) {
args = {"--str", "one"};
EXPECT_THROW(run(), CLI::RequiredError);
EXPECT_THROW(run(), CLI::ArgumentMismatch);
app.reset();
args = {"--str", "one", "two"};
@ -287,7 +307,7 @@ TEST_F(TApp, RequiredOptsDoubleShort) {
args = {"-s", "one"};
EXPECT_THROW(run(), CLI::RequiredError);
EXPECT_THROW(run(), CLI::ArgumentMismatch);
app.reset();
args = {"-s", "one", "two"};
@ -414,7 +434,17 @@ TEST_F(TApp, NotRequiedExpectedDouble) {
args = {"--str", "one"};
EXPECT_THROW(run(), CLI::RequiredError);
EXPECT_THROW(run(), CLI::ArgumentMismatch);
}
TEST_F(TApp, NotRequiedExpectedDoubleShort) {
std::vector<std::string> strs;
app.add_option("-s", strs)->expected(2);
args = {"-s", "one"};
EXPECT_THROW(run(), CLI::ArgumentMismatch);
}
TEST_F(TApp, EnumTest) {

View File

@ -91,5 +91,5 @@ TEST_F(TApp, BuiltinComplexFail) {
args = {"-c", "4"};
EXPECT_THROW(run(), CLI::RequiredError);
EXPECT_THROW(run(), CLI::ArgumentMismatch);
}