-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'error-format' of https://github.com/bburdette/nix
- Loading branch information
Showing
9 changed files
with
370 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
#include "error.hh" | ||
#include "nixexpr.hh" | ||
|
||
#include <iostream> | ||
#include <optional> | ||
|
||
int main() | ||
{ | ||
using namespace nix; | ||
|
||
// In each program where errors occur, this has to be set. | ||
ErrorInfo::programName = std::optional("error-demo"); | ||
|
||
// Error in a program; no hint and no nix code. | ||
printErrorInfo( | ||
ErrorInfo { .level = elError, | ||
.name = "name", | ||
.description = "error description", | ||
}); | ||
|
||
// 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")), | ||
}); | ||
|
||
|
||
// Warning with nix file, line number, column, and the lines of | ||
// code where a warning occurred. | ||
SymbolTable testTable; | ||
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 | ||
}}); | ||
|
||
// 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"), | ||
}}); | ||
|
||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
programs += error-demo | ||
|
||
error-demo_DIR := $(d) | ||
|
||
error-demo_SOURCES := \ | ||
$(wildcard $(d)/*.cc) \ | ||
|
||
error-demo_CXXFLAGS += -I src/libutil -I src/libexpr | ||
|
||
error-demo_LIBS = libutil libexpr | ||
|
||
error-demo_LDFLAGS = -pthread $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) -lboost_context -lboost_thread -lboost_system |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#pragma once | ||
|
||
namespace nix | ||
{ | ||
/* Some ANSI escape sequences. */ | ||
#define ANSI_NORMAL "\e[0m" | ||
#define ANSI_BOLD "\e[1m" | ||
#define ANSI_FAINT "\e[2m" | ||
#define ANSI_RED "\e[31;1m" | ||
#define ANSI_GREEN "\e[32;1m" | ||
#define ANSI_YELLOW "\e[33;1m" | ||
#define ANSI_BLUE "\e[34;1m" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
#include "error.hh" | ||
|
||
#include <iostream> | ||
#include <optional> | ||
|
||
namespace nix | ||
{ | ||
|
||
std::optional<string> ErrorInfo::programName = std::nullopt; | ||
|
||
std::ostream& operator<<(std::ostream &os, const hintformat &hf) | ||
{ | ||
return os << hf.str(); | ||
} | ||
|
||
string showErrPos(const ErrPos &errPos) | ||
{ | ||
if (errPos.column > 0) { | ||
return fmt("(%1%:%2%)", errPos.lineNumber, errPos.column); | ||
} else { | ||
return fmt("(%1%)", errPos.lineNumber); | ||
}; | ||
} | ||
|
||
void printCodeLines(const string &prefix, const NixCode &nixCode) | ||
{ | ||
// previous line of code. | ||
if (nixCode.prevLineOfCode.has_value()) { | ||
std::cout << fmt("%1% %|2$5d|| %3%", | ||
prefix, | ||
(nixCode.errPos.lineNumber - 1), | ||
*nixCode.prevLineOfCode) | ||
<< 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; | ||
|
||
// 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(const ErrorInfo &einfo) | ||
{ | ||
int errwidth = 80; | ||
string prefix = " "; | ||
|
||
string levelString; | ||
switch (einfo.level) { | ||
case ErrLevel::elError: { | ||
levelString = ANSI_RED; | ||
levelString += "error:"; | ||
levelString += ANSI_NORMAL; | ||
break; | ||
} | ||
case ErrLevel::elWarning: { | ||
levelString = ANSI_YELLOW; | ||
levelString += "warning:"; | ||
levelString += ANSI_NORMAL; | ||
break; | ||
} | ||
default: { | ||
levelString = fmt("invalid error level: %1%", einfo.level); | ||
break; | ||
} | ||
} | ||
|
||
int ndl = prefix.length() + levelString.length() + 3 + einfo.name.length() + einfo.programName.value_or("").length(); | ||
int dashwidth = ndl > (errwidth - 3) ? 3 : errwidth - ndl; | ||
|
||
string dashes; | ||
for (int i = 0; i < dashwidth; ++i) | ||
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::endl; | ||
|
||
// filename. | ||
if (einfo.nixCode.has_value()) { | ||
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->errPos.nixFile, | ||
eline) << std::endl; | ||
std::cout << prefix << std::endl; | ||
} else { | ||
std::cout << fmt("%1%from command line argument", prefix) << std::endl; | ||
std::cout << prefix << std::endl; | ||
} | ||
} | ||
|
||
// description | ||
std::cout << prefix << einfo.description << std::endl; | ||
std::cout << prefix << std::endl; | ||
|
||
// lines of code. | ||
if (einfo.nixCode->errLineOfCode != "") { | ||
printCodeLines(prefix, *einfo.nixCode); | ||
std::cout << prefix << std::endl; | ||
} | ||
|
||
// hint | ||
if (einfo.hint.has_value()) { | ||
std::cout << prefix << *einfo.hint << std::endl; | ||
std::cout << prefix << std::endl; | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
#ifndef error_hh | ||
#define error_hh | ||
|
||
#include "ansicolor.hh" | ||
#include <string> | ||
#include <optional> | ||
#include <iostream> | ||
#include "types.hh" | ||
|
||
namespace nix | ||
{ | ||
|
||
typedef enum { | ||
elWarning, | ||
elError | ||
} ErrLevel; | ||
|
||
struct ErrPos | ||
{ | ||
int lineNumber; | ||
int column; | ||
string nixFile; | ||
|
||
template <class P> | ||
ErrPos& operator=(const P &pos) | ||
{ | ||
lineNumber = pos.line; | ||
column = pos.column; | ||
nixFile = pos.file; | ||
return *this; | ||
} | ||
|
||
template <class P> | ||
ErrPos(const P &p) | ||
{ | ||
*this = p; | ||
} | ||
}; | ||
|
||
struct NixCode | ||
{ | ||
ErrPos errPos; | ||
std::optional<string> prevLineOfCode; | ||
string errLineOfCode; | ||
std::optional<string> nextLineOfCode; | ||
}; | ||
|
||
// ---------------------------------------------------------------- | ||
// format function for hints. same as fmt, except templated values | ||
// are always in yellow. | ||
|
||
template <class T> | ||
struct yellowify | ||
{ | ||
yellowify(T &s) : value(s) {} | ||
T &value; | ||
}; | ||
|
||
template <class T> | ||
std::ostream& operator<<(std::ostream &out, const yellowify<T> &y) | ||
{ | ||
return out << ANSI_YELLOW << y.value << ANSI_NORMAL; | ||
} | ||
|
||
class hintformat | ||
{ | ||
public: | ||
hintformat(string format) :fmt(format) | ||
{ | ||
fmt.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit); | ||
} | ||
template<class T> | ||
hintformat& operator%(const T &value) | ||
{ | ||
fmt % yellowify(value); | ||
return *this; | ||
} | ||
|
||
std::string str() const | ||
{ | ||
return fmt.str(); | ||
} | ||
|
||
template <typename U> | ||
friend class AddHint; | ||
private: | ||
format fmt; | ||
}; | ||
|
||
std::ostream& operator<<(std::ostream &os, const hintformat &hf); | ||
|
||
template<typename... Args> | ||
inline hintformat hintfmt(const std::string & fs, const Args & ... args) | ||
{ | ||
hintformat f(fs); | ||
formatHelper(f, args...); | ||
return f; | ||
} | ||
|
||
// ------------------------------------------------- | ||
// ErrorInfo. | ||
struct ErrorInfo | ||
{ | ||
ErrLevel level; | ||
string name; | ||
string description; | ||
std::optional<hintformat> hint; | ||
std::optional<NixCode> nixCode; | ||
|
||
static std::optional<string> programName; | ||
}; | ||
|
||
// -------------------------------------------------------- | ||
// error printing | ||
|
||
// just to cout for now. | ||
void printErrorInfo(const ErrorInfo &einfo); | ||
|
||
} | ||
|
||
#endif |
Oops, something went wrong.