#pragma once #include "types.hh" #include #include #include using std::string; using std::optional; namespace nix { enum ErrLevel { elWarning , elError }; class ColumnRange { public: 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; 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; 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; } // 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 class AddName : private T { public: T& name(const std::string &name){ GetEI().name = name; return *this; } protected: ErrorInfo& GetEI() { return T::GetEI(); } }; template class AddDescription : private T { public: T& description(const std::string &description){ GetEI().description = description; return *this; } protected: ErrorInfo& GetEI() { return T::GetEI(); } }; 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); void print_code_lines(string &prefix, NixCode &nix_code); void print_error(ErrorInfo &einfo); }