diff --git a/src/libutil/error.cc b/src/libutil/error.cc index 81c1f1805..f258d6a83 100644 --- a/src/libutil/error.cc +++ b/src/libutil/error.cc @@ -94,7 +94,11 @@ void print_error(ErrorInfo &einfo) level_string = "warning:"; // TODO make yellow. break; } - } + default: + { + level_string = "wat:"; + break; + }} int ndl = level_string.length() + 3 + einfo.name.length() + einfo.program.length(); int dashwidth = errwidth - 3 ? 3 : 80 - ndl; diff --git a/src/libutil/error.hh b/src/libutil/error.hh index 69776eb8c..9449540af 100644 --- a/src/libutil/error.hh +++ b/src/libutil/error.hh @@ -3,6 +3,7 @@ #include "types.hh" #include #include +#include using std::string; using std::optional; @@ -16,35 +17,171 @@ enum ErrLevel class ColumnRange { public: - unsigned int start; - unsigned int len; + unsigned int start; + unsigned int len; }; +class ErrorInfo; + +// ------------------------------------------------- +// forward declarations before ErrLine. +template +class AddLineNumber; + +template +class AddColumnRange; + +template +class AddLOC; + class ErrLine { public: - int lineNumber; - optional columnRange; - optional prevLineOfCode; - string errLineOfCode; - optional nextLineOfCode; + int lineNumber; + optional columnRange; + optional prevLineOfCode; + string errLineOfCode; + optional nextLineOfCode; + + friend AddLineNumber; + friend AddColumnRange; + friend AddLOC; + ErrLine& GetEL() { return *this; } + private: + ErrLine() {} }; +template +class AddLineNumber : public T +{ + public: + T& lineNumber(int lineNumber) { + GetEL().lineNumber = lineNumber; + return *this; + } + protected: + ErrLine& GetEL() { return T::GetEL(); } +}; + +template +class AddColumnRange : public T +{ + public: + T& columnRange(unsigned int start, unsigned int len) { + GetEL().columnRange = { start, len }; + return *this; + } + protected: + ErrLine& GetEL() { return T::GetEL(); } +}; + +template +class AddLOC : public T +{ + public: + T& linesOfCode(optional prevloc, string loc, optional nextloc) { + GetEL().prevLineOfCode = prevloc; + GetEL().errLineOfCode = loc; + GetEL().nextLineOfCode = nextloc; + return *this; + } + protected: + ErrLine& GetEL() { return T::GetEL(); } +}; + +typedef AddLineNumber>> MkErrLine; +MkErrLine mkErrLine; + + +// ------------------------------------------------- +// NixCode. + +template +class AddNixFile; + +template +class AddErrLine; + class NixCode { public: - optional nixFile; - optional errLine; + optional nixFile; + optional errLine; + + friend AddNixFile; + friend AddErrLine; + friend ErrorInfo; + NixCode& GetNC() { return *this; } + private: + NixCode() {} }; +template +class AddNixFile : public T +{ + public: + T& nixFile(string filename) { + GetNC().nixFile = filename; + return *this; + } + protected: + NixCode& GetNC() { return T::GetNC(); } +}; + +template +class AddErrLine : public T +{ + public: + T& errLine(ErrLine errline) { + GetNC().errLine = errline; + return *this; + } + protected: + NixCode& GetNC() { return T::GetNC(); } +}; + +typedef AddNixFile> MkNixCode; + +// ------------------------------------------------- +// ErrorInfo. + +template +class AddName; + +template +class AddDescription; + +template +class AddNixCode; class ErrorInfo { public: - ErrLevel level; - string name; - string description; - string program; - optional nixCode; - string hint; - ErrorInfo& GetEI() { return *this; } + ErrLevel level; + string name; + string description; + string program; + optional nixCode; + string hint; + ErrorInfo& GetEI() { return *this; } + + // give these access to the private constructor, + // when they are direct descendants. + friend AddName; + friend AddDescription; + friend AddNixCode; + + protected: + ErrorInfo(ErrLevel level) { this->level = level; } +}; + +class EIError : public ErrorInfo +{ + protected: + EIError() : ErrorInfo(elError) {} +}; + +class EIWarning : public ErrorInfo +{ + protected: + EIWarning() : ErrorInfo(elWarning) {} }; template @@ -71,7 +208,23 @@ class AddDescription : private T ErrorInfo& GetEI() { return T::GetEI(); } }; -typedef AddName> StandardError; +template +class AddNixCode : private T +{ + public: + T& nixcode(const NixCode &nixcode){ + GetEI().nixCode = nixcode; + return *this; + } + protected: + ErrorInfo& GetEI() { return T::GetEI(); } +}; + +typedef AddName> StandardError; +typedef AddName> StandardWarning; + +typedef AddName>> MkNixError; +typedef AddName>> MkNixWarning; string showErrLine(ErrLine &errLine); diff --git a/tests/errors/main.cc b/tests/errors/main.cc index 0e6d781c9..20dba046b 100644 --- a/tests/errors/main.cc +++ b/tests/errors/main.cc @@ -4,11 +4,13 @@ #include using std::optional; +using std::nullopt; int main() { using namespace nix; + /* ColumnRange columnRange; columnRange.start = 24; columnRange.len = 14; @@ -30,11 +32,43 @@ using namespace nix; generic.nixCode = nixcode; print_error(generic); - + */ StandardError standardError; - print_error(standardError.name("blah").description("blah")); + print_error(standardError + .name("name") + .description("description")); + + StandardWarning standardWarning; + + print_error(standardWarning + .name("warning name") + .description("warning description")); + + print_error(MkNixError() + .name("name") + .description("description") + .nixcode( + MkNixCode() + .nixFile("myfile.nix") + .errLine(MkErrLine().lineNumber(40) + .columnRange(50,10) + .linesOfCode(nullopt + ,"this is the problem line of code" + ,nullopt)))); + + print_error(MkNixWarning() + .name("name") + .description("description") + .nixcode( + MkNixCode() + .nixFile("myfile.nix") + .errLine(MkErrLine().lineNumber(40) + .columnRange(50,10) + .linesOfCode(nullopt + ,"this is the problem line of code" + ,nullopt)))); return 0; }