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_H 17 #define ES2PANDA_UTIL_DIAGNOSTIC_H 18 19 #include <initializer_list> 20 #include <memory> 21 #include <string> 22 #include <vector> 23 #include "util/es2pandaMacros.h" 24 #include "util/ustring.h" 25 #include "generated/tokenType.h" 26 27 namespace ark::es2panda::diagnostic { 28 class DiagnosticKind; 29 } // namespace ark::es2panda::diagnostic 30 31 namespace ark::es2panda::checker { 32 class Type; 33 class Signature; 34 } // namespace ark::es2panda::checker 35 36 namespace ark::es2panda::lexer { 37 class SourcePosition; 38 class SourceLocation; 39 } // namespace ark::es2panda::lexer 40 41 namespace ark::es2panda::util { 42 43 enum DiagnosticType { 44 BEGIN = 0, 45 FATAL = BEGIN, 46 SYNTAX, 47 SEMANTIC, 48 WARNING, 49 PLUGIN_ERROR, 50 PLUGIN_WARNING, 51 DECLGEN_ETS2TS_ERROR, 52 DECLGEN_ETS2TS_WARNING, 53 ARKTS_CONFIG_ERROR, 54 SUGGESTION, 55 ISOLATED_DECLGEN, 56 COUNT, 57 INVALID = COUNT 58 }; 59 60 const char *DiagnosticTypeToString(DiagnosticType type); 61 62 class DiagnosticBase { 63 public: 64 explicit DiagnosticBase(std::string_view file = "", size_t line = 0, size_t offset = 0) file_(file)65 : file_(file), line_(line), offset_(offset) 66 { 67 } 68 69 explicit DiagnosticBase(const lexer::SourcePosition &pos); 70 explicit DiagnosticBase(const lexer::SourceLocation &loc); 71 72 DEFAULT_COPY_SEMANTIC(DiagnosticBase); 73 DEFAULT_MOVE_SEMANTIC(DiagnosticBase); 74 virtual ~DiagnosticBase() = default; 75 76 virtual DiagnosticType Type() const = 0; 77 virtual std::string Message() const = 0; 78 79 bool operator<(const DiagnosticBase &rhs) const; 80 bool operator==(const DiagnosticBase &rhs) const; 81 File()82 const std::string &File() const 83 { 84 return file_; 85 } 86 GetLoc()87 std::pair<size_t, size_t> GetLoc() const 88 { 89 return {line_, offset_}; 90 } 91 Line()92 size_t Line() const 93 { 94 return line_; 95 } 96 Offset()97 size_t Offset() const 98 { 99 return offset_; 100 } 101 102 private: 103 std::string file_; 104 size_t line_ {}; 105 size_t offset_ {}; 106 }; 107 108 class AsSrc { 109 public: AsSrc(const checker::Type * type)110 explicit AsSrc(const checker::Type *type) : type_(const_cast<checker::Type *>(type)) {} 111 GetType()112 const checker::Type *GetType() const 113 { 114 return type_; 115 } 116 117 private: 118 checker::Type *type_; 119 }; 120 121 using DiagnosticMessageElement = 122 std::variant<std::string, std::string_view, const char *const, StringView, size_t, lexer::TokenType, AsSrc, 123 const checker::Type *const, const checker::Signature *const>; 124 using DiagnosticMessageParams = std::vector<DiagnosticMessageElement>; 125 126 struct DiagnosticWithParams { 127 const diagnostic::DiagnosticKind &kind; // NOLINT(readability-identifier-naming) 128 const DiagnosticMessageParams params = {}; // NOLINT(readability-identifier-naming) 129 }; 130 131 // NOLINTNEXTLINE(fuchsia-multiple-inheritance) 132 class ThrowableDiagnostic : public DiagnosticBase, public std::exception { 133 public: 134 ThrowableDiagnostic() = default; 135 ThrowableDiagnostic(DiagnosticType type, std::string_view message, std::string_view file = "", size_t line = 0, 136 size_t offset = 0) DiagnosticBase(file,line,offset)137 : DiagnosticBase(file, line, offset), type_(type), message_(message) 138 { 139 } ThrowableDiagnostic(DiagnosticType type,std::string_view message,const lexer::SourcePosition & pos)140 ThrowableDiagnostic(DiagnosticType type, std::string_view message, const lexer::SourcePosition &pos) 141 : DiagnosticBase(pos), type_(type), message_(message) 142 { 143 } ThrowableDiagnostic(DiagnosticType type,std::string_view message,const lexer::SourceLocation & loc)144 ThrowableDiagnostic(DiagnosticType type, std::string_view message, const lexer::SourceLocation &loc) 145 : DiagnosticBase(loc), type_(type), message_(message) 146 { 147 } 148 ThrowableDiagnostic(DiagnosticType type, const DiagnosticMessageParams ¶ms, const lexer::SourcePosition &pos); 149 ThrowableDiagnostic(DiagnosticType type, const DiagnosticMessageParams ¶ms, const lexer::SourceLocation &loc); 150 ThrowableDiagnostic(DiagnosticType type, const DiagnosticMessageParams ¶ms, std::string_view file = "", 151 size_t line = 0, size_t offset = 0); 152 ThrowableDiagnostic(DiagnosticType type, const diagnostic::DiagnosticKind &diagnosticKind, 153 const util::DiagnosticMessageParams &diagnosticParams, const lexer::SourcePosition &pos); 154 155 DEFAULT_COPY_SEMANTIC(ThrowableDiagnostic); 156 DEFAULT_MOVE_SEMANTIC(ThrowableDiagnostic); 157 ~ThrowableDiagnostic() override = default; 158 Type()159 DiagnosticType Type() const override 160 { 161 return type_; 162 } 163 Message()164 std::string Message() const override 165 { 166 return message_; 167 } 168 169 private: 170 DiagnosticType type_ {DiagnosticType::INVALID}; 171 std::string message_ {}; 172 }; 173 174 class Suggestion : public DiagnosticBase { 175 public: 176 explicit Suggestion(const diagnostic::DiagnosticKind *kind, std::vector<std::string> ¶ms, 177 const char *substitutionCode, const lexer::SourceRange *range); 178 SourceRange()179 const lexer::SourceRange *SourceRange() const 180 { 181 return range_; 182 } 183 SubstitutionCode()184 std::string SubstitutionCode() const 185 { 186 return substitutionCode_; 187 } 188 Message()189 std::string Message() const override 190 { 191 return message_; 192 } 193 194 DiagnosticType Type() const override; 195 196 private: 197 const diagnostic::DiagnosticKind *kind_; 198 const std::string substitutionCode_; 199 const std::string message_; 200 const lexer::SourceRange *range_; 201 }; 202 203 class Diagnostic : public DiagnosticBase { 204 public: 205 explicit Diagnostic(const diagnostic::DiagnosticKind &diagnosticKind, 206 const util::DiagnosticMessageParams &diagnosticParams); 207 explicit Diagnostic(const diagnostic::DiagnosticKind &diagnosticKind, 208 const util::DiagnosticMessageParams &diagnosticParams, const lexer::SourcePosition &pos); 209 explicit Diagnostic(const diagnostic::DiagnosticKind &diagnosticKind, 210 const util::DiagnosticMessageParams &diagnosticParams, const lexer::SourcePosition &pos, 211 Suggestion *suggestion); 212 explicit Diagnostic(const diagnostic::DiagnosticKind &diagnosticKind, 213 const util::DiagnosticMessageParams &diagnosticParams, const lexer::SourcePosition &pos, 214 std::initializer_list<Suggestion *> suggestions); 215 216 NO_COPY_SEMANTIC(Diagnostic); 217 DEFAULT_MOVE_SEMANTIC(Diagnostic); 218 ~Diagnostic() override = default; 219 220 DiagnosticType Type() const override; 221 std::string Message() const override; 222 HasSuggestions()223 bool HasSuggestions() const 224 { 225 return suggestions_ != nullptr; 226 } 227 Suggestion()228 const std::vector<class Suggestion *> &Suggestion() const 229 { 230 return *suggestions_; 231 } 232 233 private: 234 const diagnostic::DiagnosticKind *diagnosticKind_; 235 std::vector<std::string> diagnosticParams_ {}; 236 std::unique_ptr<std::vector<class Suggestion *>> suggestions_ {}; 237 }; 238 } // namespace ark::es2panda::util 239 240 #endif // ES2PANDA_UTIL_DIAGNOSTICE_H 241