Commit 17564cec05d862b79643092b876036186005a050

Authored by Henry Fredrick Schreiner
1 parent e49cc11f

Scoped enum for errors

CHANGELOG.md
@@ -3,7 +3,9 @@ @@ -3,7 +3,9 @@
3 * Ini files support flags (only read) 3 * Ini files support flags (only read)
4 * Ini files support subcommands (only read) 4 * Ini files support subcommands (only read)
5 * Ini files support vectors (only read) 5 * Ini files support vectors (only read)
6 -* Added CodeCov code coverage reports, increased coverage 6 +* Added CodeCov code coverage reports
  7 +* Lots of small bugfixes related to adding tests to increase coverage
  8 +* Error handling now uses scoped enum in errors
7 9
8 ## Version 0.6 10 ## Version 0.6
9 11
include/CLI/App.hpp
@@ -482,7 +482,7 @@ public: @@ -482,7 +482,7 @@ public:
482 482
483 /// Print a nice error message and return the exit code 483 /// Print a nice error message and return the exit code
484 int exit(const Error& e) const { 484 int exit(const Error& e) const {
485 - if(e.exit_code != 0) { 485 + if(e.exit_code != ErrorCodes::Success) {
486 std::cerr << "ERROR: "; 486 std::cerr << "ERROR: ";
487 std::cerr << e.what() << std::endl; 487 std::cerr << e.what() << std::endl;
488 if(e.print_help) 488 if(e.print_help)
@@ -491,7 +491,7 @@ public: @@ -491,7 +491,7 @@ public:
491 if(e.print_help) 491 if(e.print_help)
492 std::cout << help(); 492 std::cout << help();
493 } 493 }
494 - return e.exit_code; 494 + return e.get_exit_code();
495 } 495 }
496 496
497 /// Reset the parsed data 497 /// Reset the parsed data
@@ -757,7 +757,7 @@ protected: @@ -757,7 +757,7 @@ protected:
757 try { 757 try {
758 std::vector<detail::ini_ret_t> values = detail::parse_ini(config_name_); 758 std::vector<detail::ini_ret_t> values = detail::parse_ini(config_name_);
759 while(values.size() > 0) { 759 while(values.size() > 0) {
760 - if(!_parse_env(values)) { 760 + if(!_parse_ini(values)) {
761 throw ExtrasError(values.back().name()); 761 throw ExtrasError(values.back().name());
762 } 762 }
763 } 763 }
@@ -821,11 +821,11 @@ protected: @@ -821,11 +821,11 @@ protected:
821 } 821 }
822 } 822 }
823 823
824 - /// Parse one env param, ignore if not applicable, remove if it is 824 + /// Parse one ini param, return false if not found in any subcommand, remove if it is
825 /// 825 ///
826 /// If this has more than one dot.separated.name, go into the subcommand matching it 826 /// If this has more than one dot.separated.name, go into the subcommand matching it
827 /// Returns true if it managed to find the option, if false you'll need to remove the arg manully. 827 /// Returns true if it managed to find the option, if false you'll need to remove the arg manully.
828 - bool _parse_env(std::vector<detail::ini_ret_t> &args) { 828 + bool _parse_ini(std::vector<detail::ini_ret_t> &args) {
829 detail::ini_ret_t& current = args.back(); 829 detail::ini_ret_t& current = args.back();
830 std::string parent = current.parent(); 830 std::string parent = current.parent();
831 std::string name = current.name(); 831 std::string name = current.name();
@@ -833,8 +833,9 @@ protected: @@ -833,8 +833,9 @@ protected:
833 current.level++; 833 current.level++;
834 for(const App_p &com : subcommands_) 834 for(const App_p &com : subcommands_)
835 if(com->check_name(parent)) 835 if(com->check_name(parent))
836 - return com->_parse_env(args); 836 + return com->_parse_ini(args);
837 return false; 837 return false;
  838 + //throw CLI::ExtraINIError(current.fullname);
838 } 839 }
839 840
840 auto op_ptr = std::find_if(std::begin(options_), std::end(options_), 841 auto op_ptr = std::find_if(std::begin(options_), std::end(options_),
include/CLI/Error.hpp
@@ -9,6 +9,25 @@ @@ -9,6 +9,25 @@
9 9
10 namespace CLI { 10 namespace CLI {
11 11
  12 +enum class ErrorCodes {
  13 + Success = 0,
  14 + IncorrectConstruction=100,
  15 + BadNameString,
  16 + OptionAlreadyAdded,
  17 + File,
  18 + Conversion,
  19 + Validation,
  20 + Required,
  21 + Requires,
  22 + Excludes,
  23 + Extras,
  24 + ExtrasINI,
  25 + Invalid,
  26 + Horrible,
  27 + OptionNotFound,
  28 + BaseClass = 255
  29 +};
  30 +
12 // Error definitions 31 // Error definitions
13 32
14 /// @defgroup error_group Errors 33 /// @defgroup error_group Errors
@@ -19,102 +38,127 @@ namespace CLI { @@ -19,102 +38,127 @@ namespace CLI {
19 38
20 /// All errors derive from this one 39 /// All errors derive from this one
21 struct Error : public std::runtime_error { 40 struct Error : public std::runtime_error {
22 - int exit_code; 41 + ErrorCodes exit_code;
23 bool print_help; 42 bool print_help;
24 - Error(std::string parent, std::string name, int exit_code=255, bool print_help=true) : runtime_error(parent + ": " + name), exit_code(exit_code), print_help(print_help) {} 43 + int get_exit_code() const {return static_cast<int>(exit_code);}
  44 + Error(std::string parent, std::string name, ErrorCodes exit_code=ErrorCodes::BaseClass, bool print_help=true)
  45 + : runtime_error(parent + ": " + name), exit_code(exit_code), print_help(print_help) {}
25 }; 46 };
26 47
27 /// Construction errors (not in parsing) 48 /// Construction errors (not in parsing)
28 struct ConstructionError : public Error { 49 struct ConstructionError : public Error {
29 // Using Error::Error constructors seem to not work on GCC 4.7 50 // Using Error::Error constructors seem to not work on GCC 4.7
30 - ConstructionError(std::string parent, std::string name, int exit_code=255, bool print_help=true) : Error(parent, name, exit_code, print_help) {} 51 + ConstructionError(std::string parent, std::string name, ErrorCodes exit_code=ErrorCodes::BaseClass, bool print_help=true)
  52 + : Error(parent, name, exit_code, print_help) {}
31 }; 53 };
32 54
33 /// Thrown when an option is set to conflicting values (non-vector and multi args, for example) 55 /// Thrown when an option is set to conflicting values (non-vector and multi args, for example)
34 struct IncorrectConstruction : public ConstructionError { 56 struct IncorrectConstruction : public ConstructionError {
35 - IncorrectConstruction(std::string name) : ConstructionError("IncorrectConstruction", name, 8) {} 57 + IncorrectConstruction(std::string name)
  58 + : ConstructionError("IncorrectConstruction", name, ErrorCodes::IncorrectConstruction) {}
36 }; 59 };
37 60
38 /// Thrown on construction of a bad name 61 /// Thrown on construction of a bad name
39 struct BadNameString : public ConstructionError { 62 struct BadNameString : public ConstructionError {
40 - BadNameString(std::string name) : ConstructionError("BadNameString", name, 1) {} 63 + BadNameString(std::string name)
  64 + : ConstructionError("BadNameString", name, ErrorCodes::BadNameString) {}
41 }; 65 };
42 66
43 /// Thrown when an option already exists 67 /// Thrown when an option already exists
44 struct OptionAlreadyAdded : public ConstructionError { 68 struct OptionAlreadyAdded : public ConstructionError {
45 - OptionAlreadyAdded(std::string name) : ConstructionError("OptionAlreadyAdded", name, 3) {} 69 + OptionAlreadyAdded(std::string name)
  70 + : ConstructionError("OptionAlreadyAdded", name, ErrorCodes::OptionAlreadyAdded) {}
46 }; 71 };
47 72
48 // Parsing errors 73 // Parsing errors
49 74
50 /// Anything that can error in Parse 75 /// Anything that can error in Parse
51 struct ParseError : public Error { 76 struct ParseError : public Error {
52 - ParseError(std::string parent, std::string name, int exit_code=255, bool print_help=true) : Error(parent, name, exit_code, print_help) {} 77 + ParseError(std::string parent, std::string name, ErrorCodes exit_code=ErrorCodes::BaseClass, bool print_help=true)
  78 + : Error(parent, name, exit_code, print_help) {}
53 }; 79 };
54 80
55 // Not really "errors" 81 // Not really "errors"
56 82
57 /// This is a successful completion on parsing, supposed to exit 83 /// This is a successful completion on parsing, supposed to exit
58 struct Success : public ParseError { 84 struct Success : public ParseError {
59 - Success() : ParseError("Success", "Successfully completed, should be caught and quit", 0, false) {} 85 + Success()
  86 + : ParseError("Success", "Successfully completed, should be caught and quit", ErrorCodes::Success, false) {}
60 }; 87 };
61 88
62 /// -h or --help on command line 89 /// -h or --help on command line
63 struct CallForHelp : public ParseError { 90 struct CallForHelp : public ParseError {
64 - CallForHelp() : ParseError("CallForHelp", "This should be caught in your main function, see examples", 0) {} 91 + CallForHelp()
  92 + : ParseError("CallForHelp", "This should be caught in your main function, see examples", ErrorCodes::Success) {}
65 }; 93 };
66 94
67 95
68 /// Thrown when parsing an INI file and it is missing 96 /// Thrown when parsing an INI file and it is missing
69 struct FileError : public ParseError { 97 struct FileError : public ParseError {
70 - FileError (std::string name) : ParseError("FileError", name, 10) {} 98 + FileError (std::string name)
  99 + : ParseError("FileError", name, ErrorCodes::File) {}
71 }; 100 };
72 101
73 /// Thrown when conversion call back fails, such as when an int fails to coerse to a string 102 /// Thrown when conversion call back fails, such as when an int fails to coerse to a string
74 struct ConversionError : public ParseError { 103 struct ConversionError : public ParseError {
75 - ConversionError(std::string name) : ParseError("ConversionError", name, 2) {} 104 + ConversionError(std::string name)
  105 + : ParseError("ConversionError", name, ErrorCodes::Conversion) {}
76 }; 106 };
77 107
78 /// Thrown when validation of results fails 108 /// Thrown when validation of results fails
79 struct ValidationError : public ParseError { 109 struct ValidationError : public ParseError {
80 - ValidationError(std::string name) : ParseError("ValidationError", name, 2) {} 110 + ValidationError(std::string name)
  111 + : ParseError("ValidationError", name, ErrorCodes::Validation) {}
81 }; 112 };
82 113
83 /// Thrown when a required option is missing 114 /// Thrown when a required option is missing
84 struct RequiredError : public ParseError { 115 struct RequiredError : public ParseError {
85 - RequiredError(std::string name) : ParseError("RequiredError", name, 5) {} 116 + RequiredError(std::string name)
  117 + : ParseError("RequiredError", name, ErrorCodes::Required) {}
86 }; 118 };
87 119
88 /// Thrown when a requires option is missing 120 /// Thrown when a requires option is missing
89 struct RequiresError : public ParseError { 121 struct RequiresError : public ParseError {
90 - RequiresError(std::string name, std::string subname) : ParseError("RequiresError", name + " requires " + subname, 13) {} 122 + RequiresError(std::string name, std::string subname)
  123 + : ParseError("RequiresError", name + " requires " + subname, ErrorCodes::Requires) {}
91 }; 124 };
92 125
93 /// Thrown when a exludes option is present 126 /// Thrown when a exludes option is present
94 struct ExcludesError : public ParseError { 127 struct ExcludesError : public ParseError {
95 - ExcludesError(std::string name, std::string subname) : ParseError("ExcludesError", name + " excludes " + subname, 14) {} 128 + ExcludesError(std::string name, std::string subname)
  129 + : ParseError("ExcludesError", name + " excludes " + subname, ErrorCodes::Excludes) {}
96 }; 130 };
97 131
98 /// Thrown when too many positionals or options are found 132 /// Thrown when too many positionals or options are found
99 struct ExtrasError : public ParseError { 133 struct ExtrasError : public ParseError {
100 - ExtrasError(std::string name) : ParseError("ExtrasError", name, 6) {} 134 + ExtrasError(std::string name)
  135 + : ParseError("ExtrasError", name, ErrorCodes::Extras) {}
  136 +};
  137 +
  138 +/// Thrown when extra values are found in an INI file
  139 +struct ExtrasINIError : public ParseError {
  140 + ExtrasINIError(std::string name)
  141 + : ParseError("ExtrasINIError", name, ErrorCodes::ExtrasINI) {}
101 }; 142 };
102 143
103 /// Thrown when validation fails before parsing 144 /// Thrown when validation fails before parsing
104 struct InvalidError : public ParseError { 145 struct InvalidError : public ParseError {
105 - InvalidError(std::string name) : ParseError("InvalidError", name, 15) {} 146 + InvalidError(std::string name)
  147 + : ParseError("InvalidError", name, ErrorCodes::Invalid) {}
106 }; 148 };
107 149
108 /// This is just a safety check to verify selection and parsing match 150 /// This is just a safety check to verify selection and parsing match
109 struct HorribleError : public ParseError { 151 struct HorribleError : public ParseError {
110 - HorribleError(std::string name) : ParseError("HorribleError", "(You should never see this error) " + name, 7) {} 152 + HorribleError(std::string name)
  153 + : ParseError("HorribleError", "(You should never see this error) " + name, ErrorCodes::Horrible) {}
111 }; 154 };
112 155
113 // After parsing 156 // After parsing
114 157
115 /// Thrown when counting a non-existent option 158 /// Thrown when counting a non-existent option
116 struct OptionNotFound : public Error { 159 struct OptionNotFound : public Error {
117 - OptionNotFound(std::string name) : Error("OptionNotFound", name, 4) {} 160 + OptionNotFound(std::string name)
  161 + : Error("OptionNotFound", name, ErrorCodes::OptionNotFound) {}
118 }; 162 };
119 163
120 /// @} 164 /// @}