diff options
Diffstat (limited to 'src/libutil/error.hh')
-rw-r--r-- | src/libutil/error.hh | 111 |
1 files changed, 61 insertions, 50 deletions
diff --git a/src/libutil/error.hh b/src/libutil/error.hh index d55e1d701..eafc6a540 100644 --- a/src/libutil/error.hh +++ b/src/libutil/error.hh @@ -1,5 +1,7 @@ #pragma once +///@file +#include "suggestions.hh" #include "ref.hh" #include "types.hh" #include "fmt.hh" @@ -53,72 +55,66 @@ typedef enum { lvlVomit } Verbosity; -typedef enum { - foFile, - foStdin, - foString -} FileOrigin; - -// the lines of code surrounding an error. +/** + * The lines of code surrounding an error. + */ struct LinesOfCode { std::optional<std::string> prevLineOfCode; std::optional<std::string> errLineOfCode; std::optional<std::string> nextLineOfCode; }; -// ErrPos indicates the location of an error in a nix file. -struct ErrPos { - int line = 0; - int column = 0; - std::string file; - FileOrigin origin; +/** + * An abstract type that represents a location in a source file. + */ +struct AbstractPos +{ + uint32_t line = 0; + uint32_t column = 0; - operator bool() const - { - return line != 0; - } + /** + * Return the contents of the source file. + */ + virtual std::optional<std::string> getSource() const + { return std::nullopt; }; - // convert from the Pos struct, found in libexpr. - template <class P> - ErrPos & operator=(const P & pos) - { - origin = pos.origin; - line = pos.line; - column = pos.column; - // is file symbol null? - if (pos.file.set()) - file = pos.file; - else - file = ""; - return *this; - } + virtual void print(std::ostream & out) const = 0; - template <class P> - ErrPos(const P & p) - { - *this = p; - } + std::optional<LinesOfCode> getCodeLines() const; + + virtual ~AbstractPos() = default; }; +std::ostream & operator << (std::ostream & str, const AbstractPos & pos); + +void printCodeLines(std::ostream & out, + const std::string & prefix, + const AbstractPos & errPos, + const LinesOfCode & loc); + struct Trace { - std::optional<ErrPos> pos; + std::shared_ptr<AbstractPos> pos; hintformat hint; + bool frame; }; struct ErrorInfo { Verbosity level; - std::string name; // FIXME: rename hintformat msg; - std::optional<ErrPos> errPos; + std::shared_ptr<AbstractPos> errPos; std::list<Trace> traces; + Suggestions suggestions; + static std::optional<std::string> programName; }; std::ostream & showErrorInfo(std::ostream & out, const ErrorInfo & einfo, bool showTrace); -/* BaseError should generally not be caught, as it has Interrupted as - a subclass. Catch Error instead. */ +/** + * BaseError should generally not be caught, as it has Interrupted as + * a subclass. Catch Error instead. + */ class BaseError : public std::exception { protected: @@ -130,6 +126,8 @@ protected: public: unsigned int status = 1; // exit status + BaseError(const BaseError &) = default; + template<typename... Args> BaseError(unsigned int status, const Args & ... args) : err { .level = lvlError, .msg = hintfmt(args...) } @@ -141,6 +139,11 @@ public: : err { .level = lvlError, .msg = hintfmt(fs, args...) } { } + template<typename... Args> + BaseError(const Suggestions & sug, const Args & ... args) + : err { .level = lvlError, .msg = hintfmt(args...), .suggestions = sug } + { } + BaseError(hintformat hint) : err { .level = lvlError, .msg = hint } { } @@ -153,8 +156,6 @@ public: : err(e) { } - virtual const char* sname() const { return "BaseError"; } - #ifdef EXCEPTION_NEEDS_THROW_SPEC ~BaseError() throw () { }; const char * what() const throw () { return calcWhat().c_str(); } @@ -165,15 +166,22 @@ public: const std::string & msg() const { return calcWhat(); } const ErrorInfo & info() const { calcWhat(); return err; } + void pushTrace(Trace trace) + { + err.traces.push_front(trace); + } + template<typename... Args> - BaseError & addTrace(std::optional<ErrPos> e, const std::string & fs, const Args & ... args) + void addTrace(std::shared_ptr<AbstractPos> && e, std::string_view fs, const Args & ... args) { - return addTrace(e, hintfmt(fs, args...)); + addTrace(std::move(e), hintfmt(std::string(fs), args...)); } - BaseError & addTrace(std::optional<ErrPos> e, hintformat hint); + void addTrace(std::shared_ptr<AbstractPos> && e, hintformat hint, bool frame = false); bool hasTrace() const { return !err.traces.empty(); } + + const ErrorInfo & info() { return err; }; }; #define MakeError(newClass, superClass) \ @@ -181,7 +189,6 @@ public: { \ public: \ using superClass::superClass; \ - virtual const char* sname() const override { return #newClass; } \ } MakeError(Error, BaseError); @@ -194,15 +201,19 @@ public: int errNo; template<typename... Args> - SysError(const Args & ... args) + SysError(int errNo_, const Args & ... args) : Error("") { - errNo = errno; + errNo = errNo_; auto hf = hintfmt(args...); err.msg = hintfmt("%1%: %2%", normaltxt(hf.str()), strerror(errNo)); } - virtual const char* sname() const override { return "SysError"; } + template<typename... Args> + SysError(const Args & ... args) + : SysError(errno, args ...) + { + } }; } |