Commit f6c9ce610966f9a71e314dc85a6a43360a3d722e

Authored by Henry Fredrick Schreiner
Committed by Henry Schreiner
1 parent 4d5bff23

Moving code to Error, better ArgumentMismatch throwing

include/CLI/App.hpp
... ... @@ -452,7 +452,7 @@ class App {
452 452 CLI::callback_t fun = [&member, options, simple_name](CLI::results_t res) {
453 453 bool retval = detail::lexical_cast(res[0], member);
454 454 if(!retval)
455   - throw ConversionError("The value " + res[0] + "is not an allowed value for " + simple_name);
  455 + throw ConversionError(res[0], simple_name);
456 456 return std::find(std::begin(options), std::end(options), member) != std::end(options);
457 457 };
458 458  
... ... @@ -475,7 +475,7 @@ class App {
475 475 CLI::callback_t fun = [&member, options, simple_name](CLI::results_t res) {
476 476 bool retval = detail::lexical_cast(res[0], member);
477 477 if(!retval)
478   - throw ConversionError("The value " + res[0] + "is not an allowed value for " + simple_name);
  478 + throw ConversionError(res[0], simple_name);
479 479 return std::find(std::begin(options), std::end(options), member) != std::end(options);
480 480 };
481 481  
... ... @@ -504,7 +504,7 @@ class App {
504 504 return detail::to_lower(val) == member;
505 505 });
506 506 if(iter == std::end(options))
507   - throw ConversionError("The value " + member + "is not an allowed value for " + simple_name);
  507 + throw ConversionError(member, simple_name);
508 508 else {
509 509 member = *iter;
510 510 return true;
... ... @@ -533,7 +533,7 @@ class App {
533 533 return detail::to_lower(val) == member;
534 534 });
535 535 if(iter == std::end(options))
536   - throw ConversionError("The value " + member + "is not an allowed value for " + simple_name);
  536 + throw ConversionError(member, simple_name);
537 537 else {
538 538 member = *iter;
539 539 return true;
... ... @@ -1149,12 +1149,7 @@ class App {
1149 1149  
1150 1150 // Required but empty
1151 1151 if(opt->get_required() && opt->count() == 0)
1152   - throw RequiredError(opt->help_name() + " is required");
1153   -
1154   - // Partially filled
1155   - if(opt->get_expected() > 0 && static_cast<int>(opt->count()) < opt->get_expected())
1156   - throw RequiredError(opt->help_name() + " requires " + std::to_string(opt->get_expected()) +
1157   - " arguments");
  1152 + throw RequiredError(opt->single_name() + " is required");
1158 1153 }
1159 1154 // Requires
1160 1155 for(const Option *opt_req : opt->requires_)
... ... @@ -1409,8 +1404,8 @@ class App {
1409 1404 }
1410 1405  
1411 1406 if(num > 0) {
1412   - throw RequiredError(op->single_name() + ": " + std::to_string(num) + " required " +
1413   - op->get_type_name() + " missing");
  1407 + throw ArgumentMismatch(op->single_name() + ": " + std::to_string(num) + " required " +
  1408 + op->get_type_name() + " missing");
1414 1409 }
1415 1410 }
1416 1411  
... ... @@ -1490,8 +1485,8 @@ class App {
1490 1485 args.pop_back();
1491 1486 }
1492 1487 if(num > 0) {
1493   - throw RequiredError(op->single_name() + ": " + std::to_string(num) + " required " +
1494   - op->get_type_name() + " missing");
  1488 + throw ArgumentMismatch(op->single_name() + ": " + std::to_string(num) + " required " +
  1489 + op->get_type_name() + " missing");
1495 1490 }
1496 1491 }
1497 1492 return;
... ...
include/CLI/Error.hpp
... ... @@ -126,19 +126,22 @@ class RuntimeError : public ParseError {
126 126 /// Thrown when parsing an INI file and it is missing
127 127 class FileError : public ParseError {
128 128 CLI11_ERROR_DEF(ParseError, FileError)
129   - FileError(std::string msg) : FileError(msg, ExitCodes::File) {}
  129 + FileError(std::string name) : FileError(name + " was not readable (missing?)", ExitCodes::File) {}
130 130 };
131 131  
132 132 /// Thrown when conversion call back fails, such as when an int fails to coerce to a string
133 133 class ConversionError : public ParseError {
134 134 CLI11_ERROR_DEF(ParseError, ConversionError)
135 135 CLI11_ERROR_SIMPLE(ConversionError)
  136 + ConversionError(std::string member, std::string name)
  137 + : ConversionError("The value " + member + "is not an allowed value for " + name) {}
136 138 };
137 139  
138 140 /// Thrown when validation of results fails
139 141 class ValidationError : public ParseError {
140 142 CLI11_ERROR_DEF(ParseError, ValidationError)
141 143 CLI11_ERROR_SIMPLE(ValidationError)
  144 + ValidationError(std::string name, std::string msg) : ValidationError(name + ": " + msg) {}
142 145 };
143 146  
144 147 /// Thrown when a required option is missing
... ... @@ -150,6 +153,7 @@ class RequiredError : public ParseError {
150 153 /// Thrown when the wrong number of arguments has been recieved
151 154 class ArgumentMismatch : ParseError {
152 155 CLI11_ERROR_DEF(ParseError, ArgumentMismatch)
  156 + CLI11_ERROR_SIMPLE(ArgumentMismatch)
153 157 ArgumentMismatch(std::string name, int expected, size_t recieved)
154 158 : ArgumentMismatch(expected > 0 ? ("Expected exactly " + std::to_string(expected) + " arguments to " + name +
155 159 ", got " + std::to_string(recieved))
... ...
include/CLI/Ini.hpp
... ... @@ -106,7 +106,7 @@ inline std::vector&lt;ini_ret_t&gt; parse_ini(const std::string &amp;name) {
106 106  
107 107 std::ifstream input{name};
108 108 if(!input.good())
109   - throw FileError(name + " was not readable (missing?)");
  109 + throw FileError(name);
110 110  
111 111 return parse_ini(input);
112 112 }
... ...
include/CLI/Option.hpp
... ... @@ -438,7 +438,7 @@ class Option : public OptionBase&lt;Option&gt; {
438 438 for(const std::function<std::string(std::string &)> &vali : validators_) {
439 439 std::string err_msg = vali(result);
440 440 if(!err_msg.empty())
441   - throw ValidationError(single_name() + ": " + err_msg);
  441 + throw ValidationError(single_name(), err_msg);
442 442 }
443 443 }
444 444  
... ...
tests/AppTest.cpp
... ... @@ -243,6 +243,26 @@ TEST_F(TApp, MissingValueNonRequiredOpt) {
243 243 EXPECT_ANY_THROW(run());
244 244 }
245 245  
  246 +TEST_F(TApp, NotRequiredOptsSingle) {
  247 +
  248 + std::string str;
  249 + app.add_option("--str", str);
  250 +
  251 + args = {"--str"};
  252 +
  253 + EXPECT_THROW(run(), CLI::ArgumentMismatch);
  254 +}
  255 +
  256 +TEST_F(TApp, NotRequiredOptsSingleShort) {
  257 +
  258 + std::string str;
  259 + app.add_option("-s", str);
  260 +
  261 + args = {"-s"};
  262 +
  263 + EXPECT_THROW(run(), CLI::ArgumentMismatch);
  264 +}
  265 +
246 266 TEST_F(TApp, RequiredOptsSingle) {
247 267  
248 268 std::string str;
... ... @@ -250,7 +270,7 @@ TEST_F(TApp, RequiredOptsSingle) {
250 270  
251 271 args = {"--str"};
252 272  
253   - EXPECT_THROW(run(), CLI::RequiredError);
  273 + EXPECT_THROW(run(), CLI::ArgumentMismatch);
254 274 }
255 275  
256 276 TEST_F(TApp, RequiredOptsSingleShort) {
... ... @@ -260,7 +280,7 @@ TEST_F(TApp, RequiredOptsSingleShort) {
260 280  
261 281 args = {"-s"};
262 282  
263   - EXPECT_THROW(run(), CLI::RequiredError);
  283 + EXPECT_THROW(run(), CLI::ArgumentMismatch);
264 284 }
265 285  
266 286 TEST_F(TApp, RequiredOptsDouble) {
... ... @@ -270,7 +290,7 @@ TEST_F(TApp, RequiredOptsDouble) {
270 290  
271 291 args = {"--str", "one"};
272 292  
273   - EXPECT_THROW(run(), CLI::RequiredError);
  293 + EXPECT_THROW(run(), CLI::ArgumentMismatch);
274 294  
275 295 app.reset();
276 296 args = {"--str", "one", "two"};
... ... @@ -287,7 +307,7 @@ TEST_F(TApp, RequiredOptsDoubleShort) {
287 307  
288 308 args = {"-s", "one"};
289 309  
290   - EXPECT_THROW(run(), CLI::RequiredError);
  310 + EXPECT_THROW(run(), CLI::ArgumentMismatch);
291 311  
292 312 app.reset();
293 313 args = {"-s", "one", "two"};
... ... @@ -414,7 +434,17 @@ TEST_F(TApp, NotRequiedExpectedDouble) {
414 434  
415 435 args = {"--str", "one"};
416 436  
417   - EXPECT_THROW(run(), CLI::RequiredError);
  437 + EXPECT_THROW(run(), CLI::ArgumentMismatch);
  438 +}
  439 +
  440 +TEST_F(TApp, NotRequiedExpectedDoubleShort) {
  441 +
  442 + std::vector<std::string> strs;
  443 + app.add_option("-s", strs)->expected(2);
  444 +
  445 + args = {"-s", "one"};
  446 +
  447 + EXPECT_THROW(run(), CLI::ArgumentMismatch);
418 448 }
419 449  
420 450 TEST_F(TApp, EnumTest) {
... ...
tests/NewParseTest.cpp
... ... @@ -91,5 +91,5 @@ TEST_F(TApp, BuiltinComplexFail) {
91 91  
92 92 args = {"-c", "4"};
93 93  
94   - EXPECT_THROW(run(), CLI::RequiredError);
  94 + EXPECT_THROW(run(), CLI::ArgumentMismatch);
95 95 }
... ...