/* * Copyright (c) 2024, Dan Klishch * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include namespace JSSpecCompiler { struct LogicalLocation : RefCounted { String section; String step; }; struct Location { StringView filename; size_t line = 0; size_t column = 0; RefPtr logical_location; static Location global_scope() { return {}; } }; class DiagnosticEngine { AK_MAKE_NONCOPYABLE(DiagnosticEngine); AK_MAKE_NONMOVABLE(DiagnosticEngine); public: DiagnosticEngine() = default; #define DEFINE_DIAGNOSTIC_FUNCTION(name_, level_) \ template \ void name_(Location const& location, AK::CheckedFormatString&& fmtstr, Parameters const&... parameters) \ { \ add_diagnostic({ \ .location = location, \ .level = DiagnosticLevel::level_, \ .message = MUST(String::formatted(move(fmtstr), parameters...)), \ }); \ } DEFINE_DIAGNOSTIC_FUNCTION(note, Note) DEFINE_DIAGNOSTIC_FUNCTION(warn, Warning) DEFINE_DIAGNOSTIC_FUNCTION(error, Error) DEFINE_DIAGNOSTIC_FUNCTION(fatal_error, FatalError) #undef DEFINE_DIAGNOSTIC_FUNCTION bool has_fatal_errors() const; void print_diagnostics(); private: enum class DiagnosticLevel { Note, Warning, Error, FatalError, }; enum class UseColor { No, Yes, }; struct Diagnostic { Location location; DiagnosticLevel level; String message; Vector notes; bool operator<(Diagnostic const& other) const; void format_into(StringBuilder& builder, UseColor) const; }; void add_diagnostic(Diagnostic&& diagnostic); Vector m_diagnostics; bool m_has_fatal_errors = false; }; }