Porytiles
Loading...
Searching...
No Matches
user_diagnostics.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <ranges>
4#include <string>
5#include <type_traits>
6
7#include "gsl/pointers"
8
14
15namespace porytiles {
16
34 public:
35 virtual ~UserDiagnostics() = default;
36
37 explicit UserDiagnostics(gsl::not_null<const TextFormatter *> format) : format_(format) {}
38
52 virtual void remark(const std::string &tag, const std::vector<std::string> &lines) const = 0;
53
55 void remark(const std::string &tag, const std::string &msg) const
56 {
57 remark(tag, std::vector{msg});
58 }
59
77 template <typename FirstParam, typename... RestParams>
78 requires(
79 !std::is_same_v<std::decay_t<FirstParam>, std::vector<FormatParam>> &&
80 std::is_constructible_v<FormatParam, FirstParam> &&
81 (std::is_constructible_v<FormatParam, RestParams> && ...))
82 void remark(const std::string &tag, const std::string &format_str, FirstParam &&first, RestParams &&...rest) const
83 {
84 remark(tag, formatter().format(format_str, std::forward<FirstParam>(first), std::forward<RestParams>(rest)...));
85 }
86
98 virtual void warning(const std::string &tag, const std::vector<std::string> &lines) const = 0;
99
101 void warning(const std::string &tag, const std::string &msg) const
102 {
103 warning(tag, std::vector{msg});
104 }
105
123 template <typename FirstParam, typename... RestParams>
124 requires(
125 !std::is_same_v<std::decay_t<FirstParam>, std::vector<FormatParam>> &&
126 std::is_constructible_v<FormatParam, FirstParam> &&
127 (std::is_constructible_v<FormatParam, RestParams> && ...))
128 void warning(const std::string &tag, const std::string &format_str, FirstParam &&first, RestParams &&...rest) const
129 {
130 warning(
131 tag, formatter().format(format_str, std::forward<FirstParam>(first), std::forward<RestParams>(rest)...));
132 }
133
146 virtual void error(const std::string &tag, const std::vector<std::string> &lines) const = 0;
147
149 void error(const std::string &tag, const std::string &msg) const
150 {
151 error(tag, std::vector{msg});
152 }
153
171 template <typename FirstParam, typename... RestParams>
172 requires(
173 !std::is_same_v<std::decay_t<FirstParam>, std::vector<FormatParam>> &&
174 std::is_constructible_v<FormatParam, FirstParam> &&
175 (std::is_constructible_v<FormatParam, RestParams> && ...))
176 void error(const std::string &tag, const std::string &format_str, FirstParam &&first, RestParams &&...rest) const
177 {
178 error(tag, formatter().format(format_str, std::forward<FirstParam>(first), std::forward<RestParams>(rest)...));
179 }
180
193 virtual void remark_note(const std::string &tag, const std::vector<std::string> &lines) const = 0;
194
196 void remark_note(const std::string &tag, const std::string &msg) const
197 {
198 remark_note(tag, std::vector{msg});
199 }
200
218 template <typename FirstParam, typename... RestParams>
219 requires(
220 !std::is_same_v<std::decay_t<FirstParam>, std::vector<FormatParam>> &&
221 std::is_constructible_v<FormatParam, FirstParam> &&
222 (std::is_constructible_v<FormatParam, RestParams> && ...))
223 void
224 remark_note(const std::string &tag, const std::string &format_str, FirstParam &&first, RestParams &&...rest) const
225 {
227 tag, formatter().format(format_str, std::forward<FirstParam>(first), std::forward<RestParams>(rest)...));
228 }
229
242 virtual void warning_note(const std::string &tag, const std::vector<std::string> &lines) const = 0;
243
245 void warning_note(const std::string &tag, const std::string &msg) const
246 {
247 warning_note(tag, std::vector{msg});
248 }
249
267 template <typename FirstParam, typename... RestParams>
268 requires(
269 !std::is_same_v<std::decay_t<FirstParam>, std::vector<FormatParam>> &&
270 std::is_constructible_v<FormatParam, FirstParam> &&
271 (std::is_constructible_v<FormatParam, RestParams> && ...))
272 void
273 warning_note(const std::string &tag, const std::string &format_str, FirstParam &&first, RestParams &&...rest) const
274 {
276 tag, formatter().format(format_str, std::forward<FirstParam>(first), std::forward<RestParams>(rest)...));
277 }
278
291 virtual void error_note(const std::string &tag, const std::vector<std::string> &lines) const = 0;
292
294 void error_note(const std::string &tag, const std::string &msg) const
295 {
296 error_note(tag, std::vector{msg});
297 }
298
316 template <typename FirstParam, typename... RestParams>
317 requires(
318 !std::is_same_v<std::decay_t<FirstParam>, std::vector<FormatParam>> &&
319 std::is_constructible_v<FormatParam, FirstParam> &&
320 (std::is_constructible_v<FormatParam, RestParams> && ...))
321 void
322 error_note(const std::string &tag, const std::string &format_str, FirstParam &&first, RestParams &&...rest) const
323 {
325 tag, formatter().format(format_str, std::forward<FirstParam>(first), std::forward<RestParams>(rest)...));
326 }
327
335 virtual void emit_fatal_proximate(const Error &err) const = 0;
336
344 virtual void emit_fatal_step(const Error &err) const = 0;
345
353 virtual void emit_fatal_root(const Error &err) const = 0;
354
374 template <typename T, typename E>
375 void fatal(const ChainableResult<T, E> &result) const
376 {
377 // Preconditions
378 const auto &chain = result.chain();
379 assert_or_panic(!result.has_value(), "result was not of error type");
380 assert_or_panic(!chain.empty(), "error chain was empty");
381
382 // filter out FormattableErrors with no details
383 auto filtered_view = chain | std::views::filter([](const auto &err) {
384 const auto formattable_err = dynamic_cast<const FormattableError *>(err.get());
385 if (formattable_err == nullptr) {
386 return true;
387 }
388 return formattable_err->has_details();
389 });
390
391 std::vector<const Error *> filtered_chain;
392 for (const auto &err : filtered_view) {
393 filtered_chain.push_back(err.get());
394 }
395
396 // Unreachable.
397 if (filtered_chain.empty()) {
398 panic("filtered error chain was empty, there should always be at least one FormattableError with details");
399 }
400
401 emit_fatal_proximate(*filtered_chain.at(0));
402 if (filtered_chain.size() > 1) {
403 // Emit steps for all but the first and last
404 const auto middle_range =
405 std::ranges::views::drop(filtered_chain, 1) | std::ranges::views::take(filtered_chain.size() - 2);
406 for (const auto *err : middle_range) {
407 emit_fatal_step(*err);
408 }
409 // Emit the last one as root
410 emit_fatal_root(*filtered_chain.back());
411 }
412 }
413
414 [[nodiscard]] const TextFormatter &formatter() const
415 {
416 return *format_;
417 }
418
419 private:
420 const TextFormatter *format_;
421};
422
423} // namespace porytiles
A result type that maintains a chainable sequence of errors for debugging and error reporting.
const std::vector< std::unique_ptr< Error > > & chain() const
Returns the complete error chain.
bool has_value() const
Checks whether the result contains a success value.
Abstract interface for all error types used in ChainableResult error chains.
Definition error.hpp:17
General-purpose error implementation with formatted message support.
Definition error.hpp:57
Abstract base class for applying text styling with context-aware formatting.
Abstract class for structured error reporting and diagnostic output.
virtual void emit_fatal_proximate(const Error &err) const =0
Emit the proximate (immediate) error in a fatal error chain.
void warning(const std::string &tag, const std::string &format_str, FirstParam &&first, RestParams &&...rest) const
Variadic template overload for formatted warning messages.
void remark_note(const std::string &tag, const std::string &format_str, FirstParam &&first, RestParams &&...rest) const
Variadic template overload for formatted remark note messages.
virtual ~UserDiagnostics()=default
void error(const std::string &tag, const std::string &format_str, FirstParam &&first, RestParams &&...rest) const
Variadic template overload for formatted error messages.
virtual void warning_note(const std::string &tag, const std::vector< std::string > &lines) const =0
Display a tagged note message associated with a warning.
virtual void remark(const std::string &tag, const std::vector< std::string > &lines) const =0
Display a tagged remark message.
void error_note(const std::string &tag, const std::string &msg) const
Convenience overload for single line messages.
void error(const std::string &tag, const std::string &msg) const
Convenience overload for single line messages.
void fatal(const ChainableResult< T, E > &result) const
Display a fatal error with complete error chain visualization.
void error_note(const std::string &tag, const std::string &format_str, FirstParam &&first, RestParams &&...rest) const
Variadic template overload for formatted error note messages.
const TextFormatter & formatter() const
void warning_note(const std::string &tag, const std::string &format_str, FirstParam &&first, RestParams &&...rest) const
Variadic template overload for formatted warning note messages.
virtual void emit_fatal_step(const Error &err) const =0
Emit an intermediate step error in a fatal error chain.
void remark_note(const std::string &tag, const std::string &msg) const
Convenience overload for single line messages.
void remark(const std::string &tag, const std::string &format_str, FirstParam &&first, RestParams &&...rest) const
Variadic template overload for formatted remark messages.
virtual void warning(const std::string &tag, const std::vector< std::string > &lines) const =0
Display a tagged warning message.
virtual void error(const std::string &tag, const std::vector< std::string > &lines) const =0
Display a tagged error message.
UserDiagnostics(gsl::not_null< const TextFormatter * > format)
virtual void emit_fatal_root(const Error &err) const =0
Emit the root cause error in a fatal error chain.
virtual void remark_note(const std::string &tag, const std::vector< std::string > &lines) const =0
Display a tagged note message associated with a remark.
void remark(const std::string &tag, const std::string &msg) const
Convenience overload for single line messages.
void warning_note(const std::string &tag, const std::string &msg) const
Convenience overload for single line messages.
void warning(const std::string &tag, const std::string &msg) const
Convenience overload for single line messages.
virtual void error_note(const std::string &tag, const std::vector< std::string > &lines) const =0
Display a tagged note message associated with an error.
void panic(const StringViewSourceLoc &s)
Unconditionally terminates the program with a panic message.
Definition panic.cpp:43
void assert_or_panic(bool condition, const StringViewSourceLoc &s)
Conditionally panics if the given condition is false.
Definition panic.cpp:53
@ warning
Emit a warning and continue decompilation.
@ error
Emit a formatted error and fail decompilation.