7#include <fmt/ostream.h>
25 void hintWithContext(std::ostream& os,
const std::optional<CodeErrorContext>& maybe_context,
const bool colorize,
const bool start)
36 std::max(1_z, maybe_context->at.start.column),
40 ? (maybe_context->is_macro_expansion ?
"┌─ macro expansion started here" :
"┌─ expression started here")
41 :
"└─ ... and ended here",
42 colorize ? fmt::fg(fmt::color::red) : fmt::text_style()));
48 const std::optional<CodeErrorContext>& maybe_context,
51 assert(!(maybe_context && loc.
wholeLineIsError()) &&
"Can not create error context when a context is given AND the whole line has to be underlined");
60 const bool ctx_same_file = maybe_context && maybe_context->filename == loc.
filename;
61 const bool ctx_in_window = ctx_same_file && maybe_context && source_printer.
coversLine(maybe_context->at.start.line);
63 if (ctx_same_file && !ctx_in_window)
64 source_printer.
extendWindow(maybe_context->at.start.line);
65 else if (maybe_context && !ctx_same_file && !maybe_context->filename.empty())
68 std::string uniformised_filename;
69 std::ranges::replace_copy(maybe_context->filename, std::back_inserter(uniformised_filename),
'\\',
'/');
70 fmt::print(os,
"Error originated from file {}:{}\n", uniformised_filename, maybe_context->at.start.line + 1);
73 if (maybe_context->at.end)
74 maybe_end_line = maybe_context->at.end->line;
75 Printer printer(maybe_context->filename, maybe_context->at.start.line, maybe_end_line, colorize);
93 const std::size_t i = source_printer.
current();
94 const std::string& line = source_printer.
currentLine();
97 if (ctx_same_file && i == maybe_context->at.start.line && i < loc.
start.
line)
106 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");
110 const std::size_t col_end = (i == loc.
end->line) ? loc.
end->column : line.size();
113 if (i == loc.
end->line && loc.
end->line != loc.
start.
line && col_start >= col_end)
119 if (!maybe_context || maybe_context->at.start.line != loc.
start.
line)
125 std::max(1_z, std::min(col_start, col_end)),
127 fmt::styled(
"^", colorize ? fmt::fg(fmt::color::red) : fmt::text_style()),
128 col_start < col_end ? col_end - col_start : 1);
130 else if (maybe_context && maybe_context->at.start.line == loc.
start.
line && i == loc.
start.
line)
132 const auto padding_size = std::max(1_z, maybe_context->at.start.column);
133 const std::string inner_padding =
137 : std::string(std::max(1_z, loc.
start.
column - padding_size - 1),
' ');
146 fmt::styled(
"│", colorize ? fmt::fg(fmt::color::red) : fmt::text_style()),
150 fmt::styled(
"└─ error", colorize ? fmt::fg(fmt::color::red) : fmt::text_style()));
157 fmt::styled(
"│", colorize ? fmt::fg(fmt::color::red) : fmt::text_style()));
167 maybe_context->is_macro_expansion ?
"└─ macro expansion started here" :
"└─ expression started here",
168 colorize ? fmt::fg(fmt::color::red) : fmt::text_style()));
177 const std::size_t col_start = line.find_first_not_of(
" \t\v") + 1;
187 fmt::styled(
"^", colorize ? fmt::fg(fmt::color::red) : fmt::text_style()),
188 line.size() - col_start);
194 void helper(std::ostream& os,
const std::string& message,
const bool colorize,
196 const std::optional<CodeErrorContext>& maybe_context = std::nullopt,
197 const std::optional<std::string>& maybe_file_content = std::nullopt)
199 std::string uniformised_filename;
200 std::ranges::replace_copy(filename, std::back_inserter(uniformised_filename),
'\\',
'/');
203 .filename = uniformised_filename,
206 .maybe_content = maybe_file_content },
207 os, maybe_context, colorize);
210 fmt::print(os,
" {}\n", text);
215 std::stringstream ss;
230 if (
const char* nocolor = std::getenv(
"NOCOLOR"); nocolor !=
nullptr)
247 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
bool isLastLineOfTarget() 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.
bool isNextLineTheFirstLineOfTarget() const
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)
ARK_API void generateWithCode(const CodeError &e, const std::string &code, std::ostream &os=std::cerr, bool colorize=true)
std::string makeContextWithNode(const std::string &message, const internal::Node &node, bool colorize=true)
Helper used by the compiler to generate a colorized context from a node.
ARK_API void generate(const CodeError &e, std::ostream &os=std::cerr, bool colorize=true)
Generate a diagnostic from an error and print it to the standard error output.
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, const std::optional< std::string > &maybe_file_content=std::nullopt)
void showFileLocation(std::ostream &os, const ErrorLocation &loc)
void hintWithContext(std::ostream &os, const std::optional< CodeErrorContext > &maybe_context, const bool colorize, const bool start)
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.
std::optional< std::string > maybe_content
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.