From d3052197feababc312fd874e08ae48050d985eb3 Mon Sep 17 00:00:00 2001 From: Ben Burdette Date: Tue, 21 Apr 2020 13:25:41 -0600 Subject: [PATCH] add ErrorInfo to BaseError --- src/libutil/error.cc | 2 +- src/libutil/error.hh | 122 --------------------------------------- src/libutil/fmt.hh | 127 +++++++++++++++++++++++++++++++++++++++++ src/libutil/logging.hh | 1 - src/libutil/types.hh | 125 ++++++++++++++++++++-------------------- src/libutil/util.hh | 1 - 6 files changed, 192 insertions(+), 186 deletions(-) delete mode 100644 src/libutil/error.hh create mode 100644 src/libutil/fmt.hh diff --git a/src/libutil/error.cc b/src/libutil/error.cc index 0e07c0d98..41595b0df 100644 --- a/src/libutil/error.cc +++ b/src/libutil/error.cc @@ -1,4 +1,4 @@ -#include "error.hh" +#include "types.hh" #include #include diff --git a/src/libutil/error.hh b/src/libutil/error.hh deleted file mode 100644 index 63778ebda..000000000 --- a/src/libutil/error.hh +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef error_hh -#define error_hh - -#include "ansicolor.hh" -#include -#include -#include -#include "types.hh" - -namespace nix -{ - -typedef enum { - lvlError = 0, - lvlWarn, - lvlInfo, - lvlTalkative, - lvlChatty, - lvlDebug, - lvlVomit -} Verbosity; - -struct ErrPos -{ - int line; - int column; - string file; - - template - ErrPos& operator=(const P &pos) - { - line = pos.line; - column = pos.column; - file = pos.file; - return *this; - } - - template - ErrPos(const P &p) - { - *this = p; - } -}; - -struct NixCode -{ - ErrPos errPos; - std::optional prevLineOfCode; - string errLineOfCode; - std::optional nextLineOfCode; -}; - -// ---------------------------------------------------------------- -// format function for hints. same as fmt, except templated values -// are always in yellow. - -template -struct yellowify -{ - yellowify(T &s) : value(s) {} - T &value; -}; - -template -std::ostream& operator<<(std::ostream &out, const yellowify &y) -{ - return out << ANSI_YELLOW << y.value << ANSI_NORMAL; -} - -class hintformat -{ -public: - hintformat(string format) :fmt(format) - { - fmt.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit); - } - template - hintformat& operator%(const T &value) - { - fmt % yellowify(value); - return *this; - } - - std::string str() const - { - return fmt.str(); - } - - template - friend class AddHint; -private: - format fmt; -}; - -std::ostream& operator<<(std::ostream &os, const hintformat &hf); - -template -inline hintformat hintfmt(const std::string & fs, const Args & ... args) -{ - hintformat f(fs); - formatHelper(f, args...); - return f; -} - -// ------------------------------------------------- -// ErrorInfo. -struct ErrorInfo -{ - Verbosity level; - string name; - string description; - std::optional hint; - std::optional nixCode; - - static std::optional programName; -}; - -std::ostream& operator<<(std::ostream &out, const ErrorInfo &einfo); - -} - -#endif diff --git a/src/libutil/fmt.hh b/src/libutil/fmt.hh new file mode 100644 index 000000000..08edffee0 --- /dev/null +++ b/src/libutil/fmt.hh @@ -0,0 +1,127 @@ +#pragma once + +#include +#include +#include "ansicolor.hh" + + +namespace nix { + + +/* Inherit some names from other namespaces for convenience. */ +using std::string; +using boost::format; + + +/* A variadic template that does nothing. Useful to call a function + for all variadic arguments but ignoring the result. */ +struct nop { template nop(T...) {} }; + + +struct FormatOrString +{ + string s; + FormatOrString(const string & s) : s(s) { }; + template + FormatOrString(const F & f) : s(f.str()) { }; + FormatOrString(const char * s) : s(s) { }; +}; + + +/* A helper for formatting strings. ‘fmt(format, a_0, ..., a_n)’ is + equivalent to ‘boost::format(format) % a_0 % ... % + ... a_n’. However, ‘fmt(s)’ is equivalent to ‘s’ (so no %-expansion + takes place). */ + +template +inline void formatHelper(F & f) +{ +} + +template +inline void formatHelper(F & f, const T & x, const Args & ... args) +{ + formatHelper(f % x, args...); +} + +inline std::string fmt(const std::string & s) +{ + return s; +} + +inline std::string fmt(const char * s) +{ + return s; +} + +inline std::string fmt(const FormatOrString & fs) +{ + return fs.s; +} + +template +inline std::string fmt(const std::string & fs, const Args & ... args) +{ + boost::format f(fs); + f.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit); + formatHelper(f, args...); + return f.str(); +} + +// ----------------------------------------------------------------------------- +// format function for hints in errors. same as fmt, except templated values +// are always in yellow. + +template +struct yellowify +{ + yellowify(T &s) : value(s) {} + T &value; +}; + +template +std::ostream& operator<<(std::ostream &out, const yellowify &y) +{ + return out << ANSI_YELLOW << y.value << ANSI_NORMAL; +} + +class hintformat +{ +public: + hintformat(const string &format) :fmt(format) + { + fmt.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit); + } + template + hintformat& operator%(const T &value) + { + fmt % yellowify(value); + return *this; + } + hintformat(const hintformat &hf) + : fmt(hf.fmt) + {} + + + std::string str() const + { + return fmt.str(); + } + + template + friend class AddHint; +private: + format fmt; +}; + +std::ostream& operator<<(std::ostream &os, const hintformat &hf); + +template +inline hintformat hintfmt(const std::string & fs, const Args & ... args) +{ + hintformat f(fs); + formatHelper(f, args...); + return f; +} + +} diff --git a/src/libutil/logging.hh b/src/libutil/logging.hh index ba6f39ac9..8269e2e1a 100644 --- a/src/libutil/logging.hh +++ b/src/libutil/logging.hh @@ -1,7 +1,6 @@ #pragma once #include "types.hh" -#include "error.hh" namespace nix { diff --git a/src/libutil/types.hh b/src/libutil/types.hh index 981af528b..633c6bdf7 100644 --- a/src/libutil/types.hh +++ b/src/libutil/types.hh @@ -3,13 +3,13 @@ #include "ref.hh" -#include #include #include #include #include +#include -#include +#include "fmt.hh" /* Before 4.7, gcc's std::exception uses empty throw() specifiers for * its (virtual) destructor and what() in c++11 mode, in violation of spec @@ -20,73 +20,66 @@ #endif #endif - namespace nix { - -/* Inherit some names from other namespaces for convenience. */ -using std::string; using std::list; using std::set; using std::vector; -using boost::format; +typedef enum { + lvlError = 0, + lvlWarn, + lvlInfo, + lvlTalkative, + lvlChatty, + lvlDebug, + lvlVomit +} Verbosity; -/* A variadic template that does nothing. Useful to call a function - for all variadic arguments but ignoring the result. */ -struct nop { template nop(T...) {} }; - - -struct FormatOrString +struct ErrPos { - string s; - FormatOrString(const string & s) : s(s) { }; - template - FormatOrString(const F & f) : s(f.str()) { }; - FormatOrString(const char * s) : s(s) { }; + int line; + int column; + string file; + + template + ErrPos& operator=(const P &pos) + { + line = pos.line; + column = pos.column; + file = pos.file; + return *this; + } + + template + ErrPos(const P &p) + { + *this = p; + } }; - -/* A helper for formatting strings. ‘fmt(format, a_0, ..., a_n)’ is - equivalent to ‘boost::format(format) % a_0 % ... % - ... a_n’. However, ‘fmt(s)’ is equivalent to ‘s’ (so no %-expansion - takes place). */ - -template -inline void formatHelper(F & f) +struct NixCode { -} + ErrPos errPos; + std::optional prevLineOfCode; + string errLineOfCode; + std::optional nextLineOfCode; +}; -template -inline void formatHelper(F & f, const T & x, const Args & ... args) +// ------------------------------------------------- +// ErrorInfo. +struct ErrorInfo { - formatHelper(f % x, args...); -} + Verbosity level; + string name; + string description; + std::optional hint; + std::optional nixCode; -inline std::string fmt(const std::string & s) -{ - return s; -} - -inline std::string fmt(const char * s) -{ - return s; -} - -inline std::string fmt(const FormatOrString & fs) -{ - return fs.s; -} - -template -inline std::string fmt(const std::string & fs, const Args & ... args) -{ - boost::format f(fs); - f.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit); - formatHelper(f, args...); - return f.str(); -} + static std::optional programName; +}; +std::ostream& operator<<(std::ostream &out, const ErrorInfo &einfo); /* BaseError should generally not be caught, as it has Interrupted as a subclass. Catch Error instead. */ @@ -94,33 +87,42 @@ class BaseError : public std::exception { protected: string prefix_; // used for location traces etc. - string err; + ErrorInfo err; public: unsigned int status = 1; // exit status template BaseError(unsigned int status, const Args & ... args) - : err(fmt(args...)) + : err(hintfmt(args...)) , status(status) { } template BaseError(const Args & ... args) - : err(fmt(args...)) + : err { .level = lvlError, + .hint = hintfmt(args...) + } + { + } + + BaseError(ErrorInfo e) + : err(e) { } #ifdef EXCEPTION_NEEDS_THROW_SPEC ~BaseError() throw () { }; - const char * what() const throw () { return err.c_str(); } + const char * what() const throw () { return err.description.c_str(); } #else - const char * what() const noexcept { return err.c_str(); } + const char * what() const noexcept { return err.description.c_str(); } #endif - const string & msg() const { return err; } + const string & msg() const { return err.description; } const string & prefix() const { return prefix_; } BaseError & addPrefix(const FormatOrString & fs); + + const ErrorInfo & info() const { return err; } }; #define MakeError(newClass, superClass) \ @@ -139,7 +141,8 @@ public: template SysError(const Args & ... args) - : Error(addErrno(fmt(args...))) + : Error(args...) // TODO addErrNo for hintfmt + // : Error(addErrno(hintfmt(args...))) { } private: diff --git a/src/libutil/util.hh b/src/libutil/util.hh index fb9a7ed38..636f3ba6c 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -3,7 +3,6 @@ #include "types.hh" #include "logging.hh" #include "ansicolor.hh" -#include "error.hh" #include #include