完成 Error定义和ErrorLog. 以及一些相关的东西
This commit is contained in:
149
src/Error/Error.cpp
Normal file
149
src/Error/Error.cpp
Normal file
@@ -0,0 +1,149 @@
|
||||
#include <Core/Core.hpp>
|
||||
#include <Error/Error.hpp>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace Fig
|
||||
{
|
||||
void ColoredPrint(const char *color, const char *msg, std::ostream &ost = CoreIO::GetStdErr())
|
||||
{
|
||||
ost << color << msg << TerminalColors::Reset;
|
||||
}
|
||||
|
||||
void ColoredPrint(const char *color, const std::string &msg, std::ostream &ost = CoreIO::GetStdErr())
|
||||
{
|
||||
ost << color << msg << TerminalColors::Reset;
|
||||
}
|
||||
|
||||
void ColoredPrint(const char *color, const String &msg, std::ostream &ost = CoreIO::GetStdErr())
|
||||
{
|
||||
ost << color << msg << TerminalColors::Reset;
|
||||
}
|
||||
|
||||
std::string MultipleStr(const char *c, size_t n)
|
||||
{
|
||||
std::string buf;
|
||||
for (size_t i = 0; i < n; ++i) { buf += c; }
|
||||
return buf;
|
||||
}
|
||||
|
||||
const char *ErrorTypeToString(ErrorType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ErrorType::UnusedSymbol: return "UnusedSymbol";
|
||||
|
||||
case ErrorType::MayBeNull: return "MaybeNull";
|
||||
|
||||
case ErrorType::UnterminatedString: return "UnterminatedString";
|
||||
case ErrorType::SyntaxError: return "SyntaxError";
|
||||
default: return "Some one forgot to add case to `ErrorTypeToString`";
|
||||
}
|
||||
}
|
||||
|
||||
void PrintSystemInfos()
|
||||
{
|
||||
std::ostream &err = CoreIO::GetStdErr();
|
||||
std::stringstream build_info;
|
||||
build_info << "\r🌘 Fig v" << Core::VERSION << " on " << Core::PLATFORM << ' ' << Core::ARCH << '['
|
||||
<< Core::COMPILER << ']' << '\n'
|
||||
<< " Build Time: " << Core::COMPILE_TIME;
|
||||
|
||||
const std::string &build_info_str = build_info.str();
|
||||
err << MultipleStr("─", build_info_str.size()) << '\n';
|
||||
err << build_info_str << '\n';
|
||||
err << MultipleStr("─", build_info_str.size()) << '\n';
|
||||
}
|
||||
|
||||
void PrintErrorInfo(const Error &error, const SourceManager &srcManager)
|
||||
{
|
||||
static constexpr const char *MinorColor = "\033[38;2;138;227;198m";
|
||||
static constexpr const char *MediumColor = "\033[38;2;255;199;95m";
|
||||
static constexpr const char *CriticalColor = "\033[38;2;255;107;107m";
|
||||
|
||||
namespace TC = TerminalColors;
|
||||
std::ostream &err = CoreIO::GetStdErr();
|
||||
|
||||
uint8_t level = ErrorLevel(error.type);
|
||||
// const char *level_name = (level == 1 ? "Minor" : (level == 2 ? "Medium" : "Critical"));
|
||||
const char *level_color = (level == 1 ? MinorColor : (level == 2 ? MediumColor : CriticalColor));
|
||||
|
||||
err << "🔥 "
|
||||
<< level_color
|
||||
//<< '(' << level_name << ')'
|
||||
<< 'E' << static_cast<int>(error.type) << TC::Reset << ": " << level_color << ErrorTypeToString(error.type)
|
||||
<< TC::Reset << '\n';
|
||||
|
||||
const SourceLocation &location = error.location;
|
||||
|
||||
err << TC::DarkGray << " ┌─> " << TC::Cyan << location.fileName << " " << TC::DarkGray << location.sp.line
|
||||
<< ":" << location.sp.column << '\n';
|
||||
err << TC::DarkGray << " │" << '\n' << " │" << TC::Reset << '\n';
|
||||
|
||||
// 尝试打印上3行 下2行
|
||||
|
||||
int64_t line_start = location.sp.line - 3, line_end = location.sp.line + 2;
|
||||
while (!srcManager.HasLine(line_end)) { --line_end; }
|
||||
while (!srcManager.HasLine(line_start)) { ++line_start; }
|
||||
|
||||
const auto &getLineNumWidth = [](size_t l) {
|
||||
unsigned int cnt = 0;
|
||||
while (l != 0)
|
||||
{
|
||||
l = l / 10;
|
||||
cnt++;
|
||||
}
|
||||
return cnt;
|
||||
};
|
||||
unsigned int max_line_number_width = getLineNumWidth(line_end);
|
||||
for (size_t i = line_start; i <= line_end; ++i)
|
||||
{
|
||||
unsigned int offset = 2 + 2 + 1;
|
||||
// ' └─ '
|
||||
if (i == location.sp.line) { err << TC::DarkGray << " └─ " << TC::Reset; }
|
||||
else if (i < location.sp.line) { err << TC::DarkGray << " │ " << TC::Reset; }
|
||||
else
|
||||
{
|
||||
err << MultipleStr(" ", offset);
|
||||
}
|
||||
unsigned int cur_line_number_width = getLineNumWidth(i);
|
||||
|
||||
err << MultipleStr(" ", max_line_number_width - cur_line_number_width) << TC::Yellow << i << TC::Reset;
|
||||
err << " │ " << srcManager.GetLine(i) << '\n';
|
||||
if (i == location.sp.line)
|
||||
{
|
||||
unsigned int error_col_offset = offset + 1 + max_line_number_width + 2;
|
||||
err << MultipleStr(" ", error_col_offset) << MultipleStr(" ", location.sp.column - 1) << TC::LightGreen
|
||||
<< MultipleStr("^", location.sp.tok_length) << TC::Reset << '\n';
|
||||
|
||||
err << MultipleStr(" ", error_col_offset)
|
||||
<< MultipleStr(" ", location.sp.column - 1 + location.sp.tok_length / 2) << "╰─ " << level_color
|
||||
<< error.message << TC::Reset << "\n\n";
|
||||
}
|
||||
}
|
||||
err << "\n";
|
||||
err << "❓ " << TC::DarkGray << "Thrower: " << error.thrower_loc.function_name() << " ("
|
||||
<< error.thrower_loc.file_name() << ":" << error.thrower_loc.line() << ")" << TC::Reset << "\n";
|
||||
err << "💡 " << TC::Blue << "Suggestion: " << error.suggestion << TC::Reset;
|
||||
}
|
||||
|
||||
void ReportError(const Error &error, const SourceManager &srcManager)
|
||||
{
|
||||
assert(srcManager.read && "ReportError: srcManager doesn't read source");
|
||||
assert(srcManager.HasLine(error.location.sp.line));
|
||||
|
||||
PrintSystemInfos();
|
||||
PrintErrorInfo(error, srcManager);
|
||||
}
|
||||
|
||||
void ReportErrors(const std::vector<Error> &errors, const SourceManager &srcManager)
|
||||
{
|
||||
std::ostream &ost = CoreIO::GetStdErr();
|
||||
PrintSystemInfos();
|
||||
for (const auto &err : errors)
|
||||
{
|
||||
PrintErrorInfo(err, srcManager);
|
||||
ost << '\n';
|
||||
}
|
||||
}
|
||||
}; // namespace Fig
|
||||
Reference in New Issue
Block a user