7#include <fmt/ostream.h>
25 void hintWithContext(std::ostream& os,
const std::optional<CodeErrorContext>& maybe_context,
const bool colorize)
36 std::max(1_z, maybe_context->at.start.column),
39 maybe_context->is_macro_expansion ?
"^ macro expansion started here" :
"^ expression started here",
40 colorize ? fmt::fg(fmt::color::red) : fmt::text_style()));
46 const std::optional<CodeErrorContext>& maybe_context,
49 assert(!(maybe_context && loc.
wholeLineIsError()) &&
"Can not create error context when a context is given AND the whole line has to be underlined");
58 const bool ctx_same_file = maybe_context && maybe_context->filename == loc.
filename;
59 const bool ctx_in_window = ctx_same_file && maybe_context && source_printer.
coversLine(maybe_context->at.start.line);
61 if (ctx_same_file && !ctx_in_window)
62 source_printer.
extendWindow(maybe_context->at.start.line);
63 else if (maybe_context && !ctx_same_file && !maybe_context->filename.empty())
66 fmt::print(os,
"Error originated from file {}:{}\n", maybe_context->filename, maybe_context->at.start.line + 1);
69 if (maybe_context->at.end)
70 maybe_end_line = maybe_context->at.end->line;
71 Printer printer(maybe_context->filename, maybe_context->at.start.line, maybe_end_line, colorize);
87 const std::size_t i = source_printer.
current();
88 const std::string& line = source_printer.
currentLine();
93 if (ctx_same_file && i == maybe_context->at.start.line && i != loc.
start.
line)
101 const std::size_t line_first_char = (line.find_first_not_of(
" \t\v") == std::string::npos) ? 0 : line.find_first_not_of(
" \t\v");
105 const std::size_t col_end = (i == loc.
end->line) ? loc.
end->column : line.size();
108 if (i == loc.
end->line && loc.
end->line != loc.
start.
line && col_start >= col_end)
114 if (!maybe_context || maybe_context->at.start.line != loc.
start.
line)
120 std::max(1_z, std::min(col_start, col_end)),
122 fmt::styled(
"^", colorize ? fmt::fg(fmt::color::red) : fmt::text_style()),
123 col_start < col_end ? col_end - col_start : 1);
125 else if (maybe_context && maybe_context->at.start.line == loc.
start.
line && i == loc.
start.
line)
127 const auto padding_size = std::max(1_z, maybe_context->at.start.column);
128 const std::string inner_padding =
132 : std::string(std::max(1_z, loc.
start.
column - padding_size - 1),
' ');
141 fmt::styled(
"│", colorize ? fmt::fg(fmt::color::red) : fmt::text_style()),
145 fmt::styled(
"└─ error", colorize ? fmt::fg(fmt::color::red) : fmt::text_style()));
152 fmt::styled(
"│", colorize ? fmt::fg(fmt::color::red) : fmt::text_style()));
162 maybe_context->is_macro_expansion ?
"└─ macro expansion started here" :
"└─ expression started here",
163 colorize ? fmt::fg(fmt::color::red) : fmt::text_style()));
172 const std::size_t col_start = line.find_first_not_of(
" \t\v") + 1;
182 fmt::styled(
"^", colorize ? fmt::fg(fmt::color::red) : fmt::text_style()),
183 line.size() - col_start);
189 void helper(std::ostream& os,
const std::string& message,
const bool colorize,
191 const std::optional<CodeErrorContext>& maybe_context = std::nullopt)
195 .filename = filename,
198 os, maybe_context, colorize);
201 fmt::print(os,
" {}\n", text);
206 std::stringstream ss;
221 if (
const char* nocolor = std::getenv(
"NOCOLOR"); nocolor !=
nullptr)
Lots of utilities about string, filesystem and more.
Constants used by ArkScript.
Tools to report code errors nicely to the user.
User defined literals for Ark internals.
AST node used by the parser, optimizer and compiler.
Pretty printing utilities for diagnostics.
Source printer for diagnostics.
void extendWindow(std::size_t line_to_include)
Extend the window of lines to show, to include a given line. Useful to display the origin of an error...
const std::string & currentLine() const
static const std::string GhostLinePrefix
bool isTargetLine() const
Check if we printed the target line.
bool coversLine(std::size_t line_number) const
bool hasContent() const
Check if there are lines to print.
std::size_t current() const
void printLine(std::ostream &os)
Print the current line and advance by one.
A node of an Abstract Syntax Tree for ArkScript.
const std::string & filename() const noexcept
Return the filename in which this node was created.
FileSpan position() const noexcept
Get the span of the node (start and end)
void helper(std::ostream &os, const std::string &message, const bool colorize, const std::string &filename, const internal::FileSpan &at, const std::optional< CodeErrorContext > &maybe_context=std::nullopt)
void hintWithContext(std::ostream &os, const std::optional< CodeErrorContext > &maybe_context, const bool colorize)
ARK_API void generate(const CodeError &e, std::ostream &os=std::cout, bool colorize=true)
Generate a diagnostic from an error and print it to the standard output.
std::string makeContextWithNode(const std::string &message, const internal::Node &node)
Helper used by the compiler to generate a colorized context from a node.
void showFileLocation(std::ostream &os, const ErrorLocation &loc)
ARK_API void makeContext(const ErrorLocation &loc, std::ostream &os, const std::optional< CodeErrorContext > &maybe_context, bool colorize)
Helper to create a colorized context to report errors to the user.
std::vector< std::string > splitString(const std::string &source, const char sep)
Cut a string into pieces, given a character separator.
const internal::FileSpan at
const std::string filename
CodeError thrown by the compiler (parser, macro processor, optimizer, and compiler itself)
const std::optional< CodeErrorContext > additional_context
const CodeErrorContext context
std::optional< internal::FilePos > end
std::string filename
Complete path to the file where the error is.
bool wholeLineIsError() const
std::optional< decltype(internal::FilePos::line)> maybeEndLine() const noexcept
std::size_t column
0-indexed column number
std::size_t line
0-indexed line number
Describes a span for a node/atom in a file, its start position and end position.