• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "diagnostic.h"
17 #include <memory>
18 #include <vector>
19 #include "generated/diagnostic.h"
20 #include "lexer/token/sourceLocation.h"
21 #include "parser/program/program.h"
22 #include "checker/types/type.h"
23 #include "checker/types/signature.h"
24 
25 namespace ark::es2panda::util {
26 
Format(const DiagnosticMessageElement & elem)27 std::string Format(const DiagnosticMessageElement &elem)
28 {
29     if (std::holds_alternative<std::string>(elem)) {
30         return std::get<std::string>(elem);
31     }
32     if (std::holds_alternative<std::string_view>(elem)) {
33         return std::string(std::get<std::string_view>(elem));
34     }
35     if (std::holds_alternative<const char *const>(elem)) {
36         return std::get<const char *const>(elem);
37     }
38     if (std::holds_alternative<StringView>(elem)) {
39         return std::string(std::get<StringView>(elem));
40     }
41     if (std::holds_alternative<size_t>(elem)) {
42         return std::to_string(std::get<size_t>(elem));
43     }
44     if (std::holds_alternative<lexer::TokenType>(elem)) {
45         return TokenToString(std::get<lexer::TokenType>(elem));
46     }
47     if (std::holds_alternative<AsSrc>(elem)) {
48         std::stringstream ss;
49         std::get<AsSrc>(elem).GetType()->ToStringAsSrc(ss);
50         return ss.str();
51     }
52     if (std::holds_alternative<const checker::Type *const>(elem)) {
53         std::stringstream ss;
54         std::get<const checker::Type *const>(elem)->ToString(ss);
55         return ss.str();
56     }
57     if (std::holds_alternative<const checker::Signature *const>(elem)) {
58         std::stringstream ss;
59         std::get<const checker::Signature *const>(elem)->ToString(ss, nullptr, true);
60         return ss.str();
61     }
62     ES2PANDA_UNREACHABLE();
63 }
Format(const DiagnosticMessageParams & list)64 std::string Format(const DiagnosticMessageParams &list)
65 {
66     std::stringstream ss;
67     for (const auto &it : list) {
68         ss << Format(it);
69     }
70     return ss.str();
71 }
72 
FormatParams(const DiagnosticMessageParams & list)73 std::vector<std::string> FormatParams(const DiagnosticMessageParams &list)
74 {
75     std::vector<std::string> params;
76     params.reserve(list.size());
77     for (const auto &it : list) {
78         std::stringstream ss;
79         ss << Format(it);
80         params.push_back(ss.str());
81     }
82     return params;
83 }
84 
Format(std::string_view formatString,const std::vector<std::string> & params)85 std::string Format(std::string_view formatString, const std::vector<std::string> &params)
86 {
87     std::string result;
88     size_t pos = 0;
89     size_t paramIndex = 0;
90     while (pos < formatString.size()) {
91         auto nextPos = formatString.find("{}", pos);
92         if (nextPos == std::string::npos) {
93             break;
94         }
95         result.append(formatString.substr(pos, nextPos - pos));
96         ASSERT_PRINT(paramIndex < params.size(),
97                      "Too few params (" + std::to_string(params.size()) + ") given for " + std::string(formatString));
98         result.append(params.at(paramIndex++));
99         pos = nextPos + 2U;
100     }
101     ASSERT_PRINT(paramIndex == params.size(), "Placeholder and param count mismatch in " + std::string(formatString));
102     result.append(formatString.substr(pos));
103     return result;
104 }
105 
operator <(const DiagnosticBase & rhs) const106 bool DiagnosticBase::operator<(const DiagnosticBase &rhs) const
107 {
108     if (File() != rhs.File()) {
109         return File() < rhs.File();
110     }
111     if (Line() != rhs.Line()) {
112         return Line() < rhs.Line();
113     }
114     if (Offset() != rhs.Offset()) {
115         return Offset() < rhs.Offset();
116     }
117     if (Type() != rhs.Type()) {
118         return Type() < rhs.Type();
119     }
120     return false;
121 }
122 
operator ==(const DiagnosticBase & rhs) const123 bool DiagnosticBase::operator==(const DiagnosticBase &rhs) const
124 {
125     if (File() != rhs.File()) {
126         return false;
127     }
128     if (Line() != rhs.Line()) {
129         return false;
130     }
131     if (Offset() != rhs.Offset()) {
132         return false;
133     }
134     if (Type() != rhs.Type()) {
135         return false;
136     }
137     return Message() == rhs.Message();
138 }
139 
Type() const140 DiagnosticType Diagnostic::Type() const
141 {
142     return diagnosticKind_->Type();
143 }
144 
Message() const145 std::string Diagnostic::Message() const
146 {
147     return Format(diagnosticKind_->Message(), diagnosticParams_);
148 }
149 
DiagnosticTypeToString(DiagnosticType type)150 const char *DiagnosticTypeToString(DiagnosticType type)
151 {
152     switch (type) {
153         case DiagnosticType::FATAL:
154             return "Fatal error";
155         case DiagnosticType::SYNTAX:
156             return "SyntaxError";
157         case DiagnosticType::SEMANTIC:
158             return "TypeError";
159         case DiagnosticType::WARNING:
160             return "Warning";
161         case DiagnosticType::PLUGIN_WARNING:
162             return "Plugin warning";
163         case DiagnosticType::PLUGIN_ERROR:
164             return "Plugin error";
165         case DiagnosticType::DECLGEN_ETS2TS_ERROR:
166             return "Declgen ets2ts error";
167         case DiagnosticType::DECLGEN_ETS2TS_WARNING:
168             return "Declgen ets2ts warning";
169         case DiagnosticType::ARKTS_CONFIG_ERROR:
170             return "ArkTS config error";
171         case DiagnosticType::SUGGESTION:
172             return "SUGGESTION";
173         case DiagnosticType::ISOLATED_DECLGEN:
174             return "Isolated declgen error";
175         default:
176             ES2PANDA_UNREACHABLE();
177     }
178 }
179 
DiagnosticBase(const lexer::SourcePosition & pos)180 DiagnosticBase::DiagnosticBase(const lexer::SourcePosition &pos)
181 {
182     if (pos.Program() != nullptr) {
183         lexer::SourceLocation loc = pos.ToLocation();
184         file_ = pos.Program()->SourceFilePath().Utf8();
185         line_ = loc.line;
186         offset_ = loc.col;
187     }
188 }
189 
DiagnosticBase(const lexer::SourceLocation & loc)190 DiagnosticBase::DiagnosticBase(const lexer::SourceLocation &loc)
191 {
192     if (loc.Program() != nullptr) {
193         file_ = loc.Program()->SourceFilePath().Utf8();
194         line_ = loc.line;
195         offset_ = loc.col;
196     }
197 }
198 
ThrowableDiagnostic(DiagnosticType type,const DiagnosticMessageParams & params,const lexer::SourceLocation & loc)199 ThrowableDiagnostic::ThrowableDiagnostic(DiagnosticType type, const DiagnosticMessageParams &params,
200                                          const lexer::SourceLocation &loc)
201     : DiagnosticBase(loc), type_(type), message_(Format(params))
202 {
203 }
204 
ThrowableDiagnostic(DiagnosticType type,const DiagnosticMessageParams & params,const lexer::SourcePosition & pos)205 ThrowableDiagnostic::ThrowableDiagnostic(DiagnosticType type, const DiagnosticMessageParams &params,
206                                          const lexer::SourcePosition &pos)
207     : DiagnosticBase(pos), type_(type), message_(Format(params))
208 {
209 }
210 
ThrowableDiagnostic(DiagnosticType type,const DiagnosticMessageParams & params,std::string_view file,size_t line,size_t offset)211 ThrowableDiagnostic::ThrowableDiagnostic(DiagnosticType type, const DiagnosticMessageParams &params,
212                                          std::string_view file, size_t line, size_t offset)
213     : DiagnosticBase(file, line, offset), type_(type), message_(Format(params))
214 {
215 }
216 
ThrowableDiagnostic(const DiagnosticType type,const diagnostic::DiagnosticKind & diagnosticKind,const util::DiagnosticMessageParams & diagnosticParams,const lexer::SourcePosition & pos)217 ThrowableDiagnostic::ThrowableDiagnostic(const DiagnosticType type, const diagnostic::DiagnosticKind &diagnosticKind,
218                                          const util::DiagnosticMessageParams &diagnosticParams,
219                                          const lexer::SourcePosition &pos)
220     : DiagnosticBase(pos), type_(type), message_(Format(diagnosticKind.Message(), FormatParams(diagnosticParams)))
221 {
222 }
223 
Suggestion(const diagnostic::DiagnosticKind * kind,std::vector<std::string> & params,const char * substitutionCode,const lexer::SourceRange * range)224 Suggestion::Suggestion(const diagnostic::DiagnosticKind *kind, std::vector<std::string> &params,
225                        const char *substitutionCode, const lexer::SourceRange *range)
226     : kind_(kind), substitutionCode_(substitutionCode), message_(Format(kind->Message(), params)), range_(range)
227 {
228 }
229 
Type() const230 DiagnosticType Suggestion::Type() const
231 {
232     return kind_->Type();
233 }
234 
Diagnostic(const diagnostic::DiagnosticKind & diagnosticKind,const util::DiagnosticMessageParams & diagnosticParams,const lexer::SourcePosition & pos,std::initializer_list<class Suggestion * > suggestions)235 Diagnostic::Diagnostic(const diagnostic::DiagnosticKind &diagnosticKind,
236                        const util::DiagnosticMessageParams &diagnosticParams, const lexer::SourcePosition &pos,
237                        std::initializer_list<class Suggestion *> suggestions)
238     : DiagnosticBase(pos), diagnosticKind_(&diagnosticKind), diagnosticParams_(FormatParams(diagnosticParams))
239 {
240     if (suggestions.size() != 0) {
241         suggestions_ = std::make_unique<std::vector<class Suggestion *>>();
242         for (auto suggestion : suggestions) {
243             suggestions_->emplace_back(suggestion);
244         }
245     }
246 }
247 
Diagnostic(const diagnostic::DiagnosticKind & diagnosticKind,const util::DiagnosticMessageParams & diagnosticParams)248 Diagnostic::Diagnostic(const diagnostic::DiagnosticKind &diagnosticKind,
249                        const util::DiagnosticMessageParams &diagnosticParams)
250     : Diagnostic(diagnosticKind, diagnosticParams, lexer::SourcePosition(), {})
251 {
252 }
253 
Diagnostic(const diagnostic::DiagnosticKind & diagnosticKind,const util::DiagnosticMessageParams & diagnosticParams,const lexer::SourcePosition & pos,class Suggestion * suggestion)254 Diagnostic::Diagnostic(const diagnostic::DiagnosticKind &diagnosticKind,
255                        const util::DiagnosticMessageParams &diagnosticParams, const lexer::SourcePosition &pos,
256                        class Suggestion *suggestion)
257     : Diagnostic(diagnosticKind, diagnosticParams, pos, {suggestion})
258 {
259 }
260 
Diagnostic(const diagnostic::DiagnosticKind & diagnosticKind,const util::DiagnosticMessageParams & diagnosticParams,const lexer::SourcePosition & pos)261 Diagnostic::Diagnostic(const diagnostic::DiagnosticKind &diagnosticKind,
262                        const util::DiagnosticMessageParams &diagnosticParams, const lexer::SourcePosition &pos)
263     : Diagnostic(diagnosticKind, diagnosticParams, pos, {})
264 {
265 }
266 
267 }  // namespace ark::es2panda::util
268