1 /** 2 * Copyright (c) 2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ES2PANDA_UTIL_DIAGNOSTIC_ENGINE_H 17 #define ES2PANDA_UTIL_DIAGNOSTIC_ENGINE_H 18 19 #include <memory> 20 #include <utility> 21 #include "es2panda.h" 22 #include "util/es2pandaMacros.h" 23 #include "generated/diagnostic.h" 24 #include "util/diagnostic.h" 25 #include "lexer/token/sourceLocation.h" 26 27 namespace ark::es2panda::util { 28 29 class DiagnosticPrinter { 30 public: 31 DiagnosticPrinter() = default; 32 NO_COPY_SEMANTIC(DiagnosticPrinter); 33 NO_MOVE_SEMANTIC(DiagnosticPrinter); 34 virtual ~DiagnosticPrinter() = default; 35 36 virtual void Print(const DiagnosticBase &diagnostic) const = 0; 37 virtual void Print(const DiagnosticBase &diagnostic, std::ostream &out) const = 0; 38 }; 39 40 class CLIDiagnosticPrinter : public DiagnosticPrinter { 41 public: 42 CLIDiagnosticPrinter() = default; 43 NO_COPY_SEMANTIC(CLIDiagnosticPrinter); 44 NO_MOVE_SEMANTIC(CLIDiagnosticPrinter); 45 ~CLIDiagnosticPrinter() override = default; 46 47 void Print(const DiagnosticBase &diagnostic) const override; 48 void Print(const DiagnosticBase &diagnostic, std::ostream &out) const override; 49 }; 50 51 using DiagnosticStorage = std::vector<std::shared_ptr<DiagnosticBase>>; 52 53 class DiagnosticEngine { 54 public: DiagnosticEngine()55 explicit DiagnosticEngine() : printer_(std::make_unique<CLIDiagnosticPrinter>()) 56 { 57 g_diagnosticEngine = this; 58 } 59 NO_COPY_SEMANTIC(DiagnosticEngine); 60 NO_MOVE_SEMANTIC(DiagnosticEngine); ~DiagnosticEngine()61 ~DiagnosticEngine() 62 { 63 g_diagnosticEngine = nullptr; 64 } 65 66 // NOTE(schernykh): should be removed 67 const DiagnosticBase &GetAnyError() const; 68 69 [[nodiscard]] bool IsAnyError() const noexcept; 70 71 template <typename... T> CreateSuggestion(T &&...args)72 Suggestion *CreateSuggestion(T &&...args) 73 { 74 return CreateDiagnostic<Suggestion>(std::forward<T>(args)...); 75 } 76 77 template <typename... T> LogDiagnostic(T &&...args)78 void LogDiagnostic(T &&...args) 79 { 80 LogDiagnostic<Diagnostic>(std::forward<T>(args)...); 81 } 82 83 // NOTE(schernykh): should be removed Log(const ThrowableDiagnostic & error)84 void Log([[maybe_unused]] const ThrowableDiagnostic &error) 85 { 86 printer_->Print(error); 87 }; 88 89 template <typename... T> LogSyntaxError(T &&...args)90 void LogSyntaxError(T &&...args) 91 { 92 LogThrowableDiagnostic(DiagnosticType::SYNTAX, std::forward<T>(args)...); 93 } 94 template <typename... T> LogSemanticError(T &&...args)95 void LogSemanticError(T &&...args) 96 { 97 LogThrowableDiagnostic(DiagnosticType::SEMANTIC, std::forward<T>(args)...); 98 } 99 template <typename... T> LogFatalError(T &&...args)100 void LogFatalError(T &&...args) 101 { 102 LogThrowableDiagnostic(DiagnosticType::FATAL, std::forward<T>(args)...); 103 } 104 105 // NOTE(schernykh): should not be able from ETS 106 template <typename... T> ThrowSyntaxError(T &&...args)107 [[noreturn]] void ThrowSyntaxError(T &&...args) 108 { 109 ThrowDiagnostic(DiagnosticType::SYNTAX, std::forward<T>(args)...); 110 } 111 template <typename... T> ThrowSemanticError(T &&...args)112 [[noreturn]] void ThrowSemanticError(T &&...args) 113 { 114 ThrowDiagnostic(DiagnosticType::SEMANTIC, std::forward<T>(args)...); 115 } 116 template <typename... T> ThrowFatalError(T &&...args)117 [[noreturn]] void ThrowFatalError(T &&...args) 118 { 119 ThrowDiagnostic(DiagnosticType::FATAL, std::forward<T>(args)...); 120 } 121 122 void FlushDiagnostic(); 123 std::string PrintAndFlushErrorDiagnostic(); SetWError(bool wError)124 void SetWError(bool wError) 125 { 126 wError_ = wError; 127 } 128 129 const DiagnosticStorage &GetDiagnosticStorage(DiagnosticType type); 130 131 static void InitializeSignalHandlers(); 132 133 private: 134 template <typename DIAGNOSTIC, typename... T> CreateDiagnostic(T &&...args)135 DIAGNOSTIC *CreateDiagnostic(T &&...args) 136 { 137 auto diag = std::make_unique<DIAGNOSTIC>(std::forward<T>(args)...); 138 auto type = diag->Type(); 139 diagnostics_[type].push_back(std::move(diag)); 140 return reinterpret_cast<DIAGNOSTIC *>(diagnostics_[type].back().get()); 141 } 142 143 template <typename DIAGNOSTIC, typename... T> LogDiagnostic(T &&...args)144 void LogDiagnostic(T &&...args) 145 { 146 CreateDiagnostic<DIAGNOSTIC>(std::forward<T>(args)...); 147 } 148 149 template <typename... T> LogThrowableDiagnostic(T &&...args)150 void LogThrowableDiagnostic(T &&...args) 151 { 152 LogDiagnostic<ThrowableDiagnostic>(std::forward<T>(args)...); 153 } 154 155 template <typename... T> ThrowDiagnostic(T &&...args)156 [[noreturn]] void ThrowDiagnostic(T &&...args) const 157 { 158 Throw(ThrowableDiagnostic {std::forward<T>(args)...}); 159 } 160 [[noreturn]] void Throw(ThrowableDiagnostic diag) const; 161 162 bool IsError(DiagnosticType type) const; 163 DiagnosticStorage GetAllDiagnostic(); 164 DiagnosticStorage GetErrorDiagnostic(); 165 void WriteLog(const DiagnosticBase &error); 166 167 private: 168 std::array<DiagnosticStorage, static_cast<size_t>(DiagnosticType::COUNT)> diagnostics_; 169 std::unique_ptr<const DiagnosticPrinter> printer_; 170 bool wError_ {false}; 171 }; 172 173 } // namespace ark::es2panda::util 174 175 #endif // ES2PANDA_UTIL_DIAGNOSTIC_ENGINE_H 176