aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/error-demo/error-demo.cc107
-rw-r--r--src/libutil/error.cc110
-rw-r--r--src/libutil/error.hh226
3 files changed, 127 insertions, 316 deletions
diff --git a/src/error-demo/error-demo.cc b/src/error-demo/error-demo.cc
index 8fb20d38c..a9ff6057c 100644
--- a/src/error-demo/error-demo.cc
+++ b/src/error-demo/error-demo.cc
@@ -11,77 +11,56 @@ int main()
// In each program where errors occur, this has to be set.
ErrorInfo::programName = std::optional("error-demo");
- // There are currently four error types:
- //
- // ProgramError, ProgramWarning, NixLangError, NixLangWarning.
- //
- // Each error type is created with a specific sequence of builder functions.
- // Unlike with a constructor, each parameter is clearly named.
- // If the sequence of function calls isn't followed, then there's a type
- // error. This should make for a consistent look in the code when errors are
- // created.
+ // Error in a program; no hint and no nix code.
+ printErrorInfo(
+ ErrorInfo { .level = elError,
+ .name = "name",
+ .description = "error description",
+ });
- // ProgramError takes name, description, and an optional hint.
- printErrorInfo( ProgramError()
- .name("name")
- .description("error description")
- .nohint()
- );
+ // Warning with name, description, and hint.
+ // The hintfmt function makes all the substituted text yellow.
+ printErrorInfo(
+ ErrorInfo { .level = elWarning,
+ .name = "name",
+ .description = "error description",
+ .hint = std::optional(
+ hintfmt("there was a %1%", "warning")),
+ });
- // ProgramWarning takes name, description, and an optional hint.
- // The hint is in the form of a hintfmt class, which wraps boost::format(),
- // and makes all the substituted text yellow.
- printErrorInfo( ProgramWarning()
- .name("warning name")
- .description("warning description")
- // the templated value, 'warning', is automatically colored yellow.
- .hint(hintfmt("there was a %1%", "warning"))
- );
- /*
- // some invalid errors:
-
- // type error: no hint function.
- ProgramError()
- .name("name")
- .description("error description");
-
- // type error: description before name.
- ProgramError()
- .description("error description")
- .name("name")
- .nohint();
-
- // type error: hint function with regular boost format, not special
- hintfmt. ProgramError() .description("error description") .name("name")
- .hint(format("there was a %1%") % "warning");
- */
-
- // NixLangWarning adds nix file, line number, column range, and the lines of
+ // Warning with nix file, line number, column, and the lines of
// code where a warning occurred.
-
SymbolTable testTable;
- auto problem_symbol = testTable.create("problem");
+ auto problem_file = testTable.create("myfile.nix");
+
+ printErrorInfo(
+ ErrorInfo{
+ .level = elWarning,
+ .name = "warning name",
+ .description = "warning description",
+ .hint = hintfmt("this hint has %1% templated %2%!!", "yellow", "values"),
+ .nixCode = NixCode {
+ .errPos = Pos(problem_file, 40, 13),
+ .prevLineOfCode = std::nullopt,
+ .errLineOfCode = "this is the problem line of code",
+ .nextLineOfCode = std::nullopt
+ }});
- printErrorInfo(NixLangWarning()
- .name("warning name")
- .description("warning description")
- .pos(Pos(problem_symbol, 40, 13))
- .linesOfCode(std::nullopt,
- "this is the problem line of code",
- std::nullopt)
- .hint(hintfmt("this hint has %1% templated %2%!!", "yellow" , "values")));
+ // Error with previous and next lines of code.
+ printErrorInfo(
+ ErrorInfo{
+ .level = elError,
+ .name = "error name",
+ .description = "error description",
+ .hint = hintfmt("this hint has %1% templated %2%!!", "yellow", "values"),
+ .nixCode = NixCode {
+ .errPos = Pos(problem_file, 40, 13),
+ .prevLineOfCode = std::optional("previous line of code"),
+ .errLineOfCode = "this is the problem line of code",
+ .nextLineOfCode = std::optional("next line of code"),
+ }});
- // NixLangError is just the same as NixLangWarning, except for the Error
- // flag.
- printErrorInfo(NixLangError()
- .name("error name")
- .description("error description")
- .pos(Pos(problem_symbol, 40, 13))
- .linesOfCode(std::optional("previous line of code"),
- "this is the problem line of code",
- std::optional("next line of code"))
- .hint(hintfmt("this hint has %1% templated %2%!!", "yellow", "values")));
return 0;
}
diff --git a/src/libutil/error.cc b/src/libutil/error.cc
index 106ea127e..40354cc87 100644
--- a/src/libutil/error.cc
+++ b/src/libutil/error.cc
@@ -8,68 +8,60 @@ namespace nix
std::optional<string> ErrorInfo::programName = std::nullopt;
-string showErrLine(ErrLine &errLine)
+string showErrPos(const ErrPos &errPos)
{
- if (errLine.column > 0) {
- return fmt("(%1%:%2%)", errLine.lineNumber, errLine.column);
+ if (errPos.column > 0) {
+ return fmt("(%1%:%2%)", errPos.lineNumber, errPos.column);
} else {
- return fmt("(%1%)", errLine.lineNumber);
+ return fmt("(%1%)", errPos.lineNumber);
};
}
-void printCodeLines(string &prefix, NixCode &nixCode)
+void printCodeLines(const string &prefix, const NixCode &nixCode)
{
-
- if (nixCode.errLine.has_value()) {
- // previous line of code.
- if (nixCode.errLine->prevLineOfCode.has_value()) {
- std::cout << fmt("%1% %|2$5d|| %3%",
- prefix,
- (nixCode.errLine->lineNumber - 1),
- *nixCode.errLine->prevLineOfCode)
- << std::endl;
- }
-
- // line of code containing the error.%2$+5d%
+ // previous line of code.
+ if (nixCode.prevLineOfCode.has_value()) {
std::cout << fmt("%1% %|2$5d|| %3%",
prefix,
- (nixCode.errLine->lineNumber),
- nixCode.errLine->errLineOfCode)
+ (nixCode.errPos.lineNumber - 1),
+ *nixCode.prevLineOfCode)
<< std::endl;
+ }
- // error arrows for the column range.
- if (nixCode.errLine->column > 0) {
- int start = nixCode.errLine->column;
- std::string spaces;
- for (int i = 0; i < start; ++i) {
- spaces.append(" ");
- }
-
- // for now, length of 1.
- std::string arrows("^");
-
- std::cout << fmt("%1% |%2%" ANSI_RED "%3%" ANSI_NORMAL,
- prefix,
- spaces,
- arrows) << std::endl;
- }
-
-
+ // line of code containing the error.%2$+5d%
+ std::cout << fmt("%1% %|2$5d|| %3%",
+ prefix,
+ (nixCode.errPos.lineNumber),
+ nixCode.errLineOfCode)
+ << std::endl;
- // next line of code.
- if (nixCode.errLine->nextLineOfCode.has_value()) {
- std::cout << fmt("%1% %|2$5d|| %3%",
- prefix,
- (nixCode.errLine->lineNumber + 1),
- *nixCode.errLine->nextLineOfCode)
- << std::endl;
+ // error arrows for the column range.
+ if (nixCode.errPos.column > 0) {
+ int start = nixCode.errPos.column;
+ std::string spaces;
+ for (int i = 0; i < start; ++i) {
+ spaces.append(" ");
}
+ std::string arrows("^");
+
+ std::cout << fmt("%1% |%2%" ANSI_RED "%3%" ANSI_NORMAL,
+ prefix,
+ spaces,
+ arrows) << std::endl;
}
+ // next line of code.
+ if (nixCode.nextLineOfCode.has_value()) {
+ std::cout << fmt("%1% %|2$5d|| %3%",
+ prefix,
+ (nixCode.errPos.lineNumber + 1),
+ *nixCode.nextLineOfCode)
+ << std::endl;
+ }
}
-void printErrorInfo(ErrorInfo &einfo)
+void printErrorInfo(const ErrorInfo &einfo)
{
int errwidth = 80;
string prefix = " ";
@@ -102,24 +94,26 @@ void printErrorInfo(ErrorInfo &einfo)
dashes.append("-");
// divider.
- std::cout << fmt("%1%%2%" ANSI_BLUE " %3% %4% %5% %6%" ANSI_NORMAL
- , prefix
- , levelString
- , "---"
- , einfo.name
- , dashes
- , einfo.programName.value_or(""))
+ std::cout << fmt("%1%%2%" ANSI_BLUE " %3% %4% %5% %6%" ANSI_NORMAL,
+ prefix,
+ levelString,
+ "---",
+ einfo.name,
+ dashes,
+ einfo.programName.value_or(""))
<< std::endl;
// filename.
if (einfo.nixCode.has_value()) {
- if (einfo.nixCode->nixFile.has_value()) {
- string eline = einfo.nixCode->errLine.has_value()
- ? string(" ") + showErrLine(*einfo.nixCode->errLine)
+ if (einfo.nixCode->errPos.nixFile != "") {
+ string eline = einfo.nixCode->errLineOfCode != ""
+ ? string(" ") + showErrPos(einfo.nixCode->errPos)
: "";
- std::cout << fmt("%1%in file: " ANSI_BLUE "%2%%3%" ANSI_NORMAL
- , prefix, *einfo.nixCode->nixFile, eline) << std::endl;
+ std::cout << fmt("%1%in file: " ANSI_BLUE "%2%%3%" ANSI_NORMAL,
+ prefix,
+ einfo.nixCode->errPos.nixFile,
+ eline) << std::endl;
std::cout << prefix << std::endl;
} else {
std::cout << fmt("%1%from command line argument", prefix) << std::endl;
@@ -132,7 +126,7 @@ void printErrorInfo(ErrorInfo &einfo)
std::cout << prefix << std::endl;
// lines of code.
- if (einfo.nixCode.has_value()) {
+ if (einfo.nixCode->errLineOfCode != "") {
printCodeLines(prefix, *einfo.nixCode);
std::cout << prefix << std::endl;
}
diff --git a/src/libutil/error.hh b/src/libutil/error.hh
index 664bfbb5a..8286eaab1 100644
--- a/src/libutil/error.hh
+++ b/src/libutil/error.hh
@@ -17,172 +17,40 @@ typedef enum {
elError
} ErrLevel;
-class ErrorInfo;
-
-class ErrLine
+class ErrPos
{
public:
int lineNumber;
int column;
- std::optional<string> prevLineOfCode;
- string errLineOfCode;
- std::optional<string> nextLineOfCode;
-};
+ string nixFile;
-class NixCode
-{
-public:
- std::optional<string> nixFile;
- std::optional<ErrLine> errLine;
-
- ErrLine& ensureErrLine()
- {
- if (!this->errLine.has_value())
- this->errLine = std::optional(ErrLine());
- return *this->errLine;
- }
-};
-
-// -------------------------------------------------
-// ErrorInfo.
-
-// Forward friend class declarations. "builder classes"
-template <class T>
-class AddName;
-
-template <class T>
-class AddDescription;
-
-template <class T>
-class AddPos;
-
-template <class T>
-class AddLOC;
-
-// The error info class itself.
-class ErrorInfo
-{
-public:
- ErrLevel level;
- string name;
- string description;
- std::optional<NixCode> nixCode;
- std::optional<string> hint;
- ErrorInfo& GetEI()
- {
- return *this;
- }
-
- static std::optional<string> programName;
-
- // give these access to the private constructor,
- // when they are direct descendants (children but not grandchildren).
- friend AddName<ErrorInfo>;
- friend AddDescription<ErrorInfo>;
- friend AddPos<ErrorInfo>;
- friend AddLOC<ErrorInfo>;
-
- NixCode& ensureNixCode()
- {
- if (!this->nixCode.has_value())
- this->nixCode = std::optional(NixCode());
- return *this->nixCode;
- }
-protected:
- // constructor is protected, so only the builder classes can create an ErrorInfo.
- ErrorInfo(ErrLevel level)
- {
- this->level = level;
- }
-};
-
-// Init as error
-class EIError : public ErrorInfo
-{
-protected:
- EIError() : ErrorInfo(elError) {}
-};
-
-// Init as warning
-class EIWarning : public ErrorInfo
-{
-protected:
- EIWarning() : ErrorInfo(elWarning) {}
-};
-
-// Builder class definitions.
-template <class T>
-class AddName : private T
-{
-public:
- T& name(const std::string &name)
- {
- GetEI().name = name;
- return *this;
- }
-protected:
- ErrorInfo& GetEI()
- {
- return T::GetEI();
- }
-};
-
-template <class T>
-class AddDescription : private T
-{
-public:
- T& description(const std::string &description)
+ template <class P>
+ ErrPos& operator=(const P &pos)
{
- GetEI().description = description;
+ lineNumber = pos.line;
+ column = pos.column;
+ nixFile = pos.file;
return *this;
}
-protected:
- ErrorInfo& GetEI()
- {
- return T::GetEI();
- }
-};
-template <class T>
-class AddPos : private T
-{
-public:
template <class P>
- T& pos(const P &aPos)
- {
- GetEI().ensureNixCode().nixFile = aPos.file;
- GetEI().ensureNixCode().ensureErrLine().lineNumber = aPos.line;
- GetEI().ensureNixCode().ensureErrLine().column = aPos.column;
- return *this;
- }
-protected:
- ErrorInfo& GetEI()
+ ErrPos(const P &p)
{
- return T::GetEI();
+ *this = p;
}
};
-template <class T>
-class AddLOC : private T
+class NixCode
{
public:
- T& linesOfCode(std::optional<string> prevloc, string loc, std::optional<string> nextloc)
- {
- GetEI().ensureNixCode().ensureErrLine().prevLineOfCode = prevloc;
- GetEI().ensureNixCode().ensureErrLine().errLineOfCode = loc;
- GetEI().ensureNixCode().ensureErrLine().nextLineOfCode = nextloc;
- return *this;
- }
-protected:
- ErrorInfo& GetEI()
- {
- return T::GetEI();
- }
+ ErrPos errPos;
+ std::optional<string> prevLineOfCode;
+ string errLineOfCode;
+ std::optional<string> nextLineOfCode;
};
-
// ----------------------------------------------------------------
-// format for hints. same as fmt, except templated values
+// format function for hints. same as fmt, except templated values
// are always in yellow.
template <class T>
@@ -222,9 +90,13 @@ public:
friend class AddHint;
private:
format fmt;
-
};
+std::ostream& operator<<(std::ostream &os, const hintformat &hf)
+{
+ return os << hf.str();
+}
+
template<typename... Args>
inline hintformat hintfmt(const std::string & fs, const Args & ... args)
{
@@ -233,61 +105,27 @@ inline hintformat hintfmt(const std::string & fs, const Args & ... args)
return f;
}
-// the template layer for adding a hint.
-template <class T>
-class AddHint : private T
+// -------------------------------------------------
+// ErrorInfo.
+class ErrorInfo
{
public:
- T& hint(const hintformat &hf)
- {
- GetEI().hint = std::optional(hf.str());
- return *this;
- }
- T& nohint()
- {
- GetEI().hint = std::nullopt;
- return *this;
- }
-protected:
- ErrorInfo& GetEI()
- {
- return T::GetEI();
- }
-};
-
-// --------------------------------------------------------
-// error types
-
-typedef AddName<
- AddDescription<
- AddHint<
- EIError>>> ProgramError;
-
-typedef AddName<
- AddDescription<
- AddHint<
- EIWarning>>> ProgramWarning;
-
-typedef AddName<
- AddDescription<
- AddPos<
- AddLOC<
- AddHint<
- EIError>>>>> NixLangError;
+ ErrLevel level;
+ string name;
+ string description;
+ std::optional<hintformat> hint;
+ std::optional<NixCode> nixCode;
-typedef AddName<
- AddDescription<
- AddPos<
- AddLOC<
- AddHint<
- EIWarning>>>>> NixLangWarning;
+ static std::optional<string> programName;
+private:
+};
// --------------------------------------------------------
// error printing
// just to cout for now.
-void printErrorInfo(ErrorInfo &einfo);
+void printErrorInfo(const ErrorInfo &einfo);
}