Commit 17564cec05d862b79643092b876036186005a050

Authored by Henry Fredrick Schreiner
1 parent e49cc11f

Scoped enum for errors

CHANGELOG.md
... ... @@ -3,7 +3,9 @@
3 3 * Ini files support flags (only read)
4 4 * Ini files support subcommands (only read)
5 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 10 ## Version 0.6
9 11  
... ...
include/CLI/App.hpp
... ... @@ -482,7 +482,7 @@ public:
482 482  
483 483 /// Print a nice error message and return the exit code
484 484 int exit(const Error& e) const {
485   - if(e.exit_code != 0) {
  485 + if(e.exit_code != ErrorCodes::Success) {
486 486 std::cerr << "ERROR: ";
487 487 std::cerr << e.what() << std::endl;
488 488 if(e.print_help)
... ... @@ -491,7 +491,7 @@ public:
491 491 if(e.print_help)
492 492 std::cout << help();
493 493 }
494   - return e.exit_code;
  494 + return e.get_exit_code();
495 495 }
496 496  
497 497 /// Reset the parsed data
... ... @@ -757,7 +757,7 @@ protected:
757 757 try {
758 758 std::vector<detail::ini_ret_t> values = detail::parse_ini(config_name_);
759 759 while(values.size() > 0) {
760   - if(!_parse_env(values)) {
  760 + if(!_parse_ini(values)) {
761 761 throw ExtrasError(values.back().name());
762 762 }
763 763 }
... ... @@ -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 826 /// If this has more than one dot.separated.name, go into the subcommand matching it
827 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 829 detail::ini_ret_t& current = args.back();
830 830 std::string parent = current.parent();
831 831 std::string name = current.name();
... ... @@ -833,8 +833,9 @@ protected:
833 833 current.level++;
834 834 for(const App_p &com : subcommands_)
835 835 if(com->check_name(parent))
836   - return com->_parse_env(args);
  836 + return com->_parse_ini(args);
837 837 return false;
  838 + //throw CLI::ExtraINIError(current.fullname);
838 839 }
839 840  
840 841 auto op_ptr = std::find_if(std::begin(options_), std::end(options_),
... ...
include/CLI/Error.hpp
... ... @@ -9,6 +9,25 @@
9 9  
10 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 31 // Error definitions
13 32  
14 33 /// @defgroup error_group Errors
... ... @@ -19,102 +38,127 @@ namespace CLI {
19 38  
20 39 /// All errors derive from this one
21 40 struct Error : public std::runtime_error {
22   - int exit_code;
  41 + ErrorCodes exit_code;
23 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 48 /// Construction errors (not in parsing)
28 49 struct ConstructionError : public Error {
29 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 55 /// Thrown when an option is set to conflicting values (non-vector and multi args, for example)
34 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 61 /// Thrown on construction of a bad name
39 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 67 /// Thrown when an option already exists
44 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 73 // Parsing errors
49 74  
50 75 /// Anything that can error in Parse
51 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 81 // Not really "errors"
56 82  
57 83 /// This is a successful completion on parsing, supposed to exit
58 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 89 /// -h or --help on command line
63 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 96 /// Thrown when parsing an INI file and it is missing
69 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 102 /// Thrown when conversion call back fails, such as when an int fails to coerse to a string
74 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 108 /// Thrown when validation of results fails
79 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 114 /// Thrown when a required option is missing
84 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 120 /// Thrown when a requires option is missing
89 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 126 /// Thrown when a exludes option is present
94 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 132 /// Thrown when too many positionals or options are found
99 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 144 /// Thrown when validation fails before parsing
104 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 150 /// This is just a safety check to verify selection and parsing match
109 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 156 // After parsing
114 157  
115 158 /// Thrown when counting a non-existent option
116 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 /// @}
... ...