aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/error.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/libutil/error.hh')
-rw-r--r--src/libutil/error.hh111
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 ...)
+ {
+ }
};
}