• 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 "diagnosticEngine.h"
17 #include <memory>
18 #include "util/diagnostic.h"
19 #include "util/options.h"
20 
21 #include <csignal>
22 
23 namespace ark::es2panda::util {
24 
Print(const DiagnosticBase & diagnostic,std::ostream & out) const25 void CLIDiagnosticPrinter::Print(const DiagnosticBase &diagnostic, std::ostream &out) const
26 {
27     out << DiagnosticTypeToString(diagnostic.Type()) << ": " << diagnostic.Message();
28     if (!diagnostic.File().empty()) {
29         out << " [" << util::BaseName(diagnostic.File()) << ":" << diagnostic.Line() << ":" << diagnostic.Offset()
30             << "]";
31     }
32     out << std::endl;
33 }
34 
Print(const DiagnosticBase & diagnostic) const35 void CLIDiagnosticPrinter::Print(const DiagnosticBase &diagnostic) const
36 {
37     Print(diagnostic, std::cout);
38 }
39 
GetDiagnosticStorage(DiagnosticType type)40 const DiagnosticStorage &DiagnosticEngine::GetDiagnosticStorage(DiagnosticType type)
41 {
42     return diagnostics_[type];
43 }
44 
Throw(ThrowableDiagnostic diag) const45 [[noreturn]] void DiagnosticEngine::Throw(ThrowableDiagnostic diag) const
46 {
47     throw diag;
48 }
49 
GetAllDiagnostic()50 DiagnosticStorage DiagnosticEngine::GetAllDiagnostic()
51 {
52     size_t totalSize = 0;
53     for (const auto &vec : diagnostics_) {
54         totalSize += vec.size();
55     }
56 
57     DiagnosticStorage merged;
58     merged.reserve(totalSize);
59     for (auto &vec : diagnostics_) {
60         for (auto &&diag : vec) {
61             merged.emplace_back(std::move(diag));
62         }
63     }
64     return merged;
65 }
66 
GetErrorDiagnostic()67 DiagnosticStorage DiagnosticEngine::GetErrorDiagnostic()
68 {
69     size_t errorCount = 0;
70     for (const auto &vec : diagnostics_) {
71         if (!vec.empty() && IsError(vec.front()->Type())) {
72             errorCount += vec.size();
73         }
74     }
75 
76     DiagnosticStorage merged;
77     merged.reserve(errorCount);
78     for (const auto &vec : diagnostics_) {
79         if (!vec.empty() && IsError(vec.front()->Type())) {
80             merged.insert(merged.end(), vec.begin(), vec.end());
81         }
82     }
83     return merged;
84 }
85 
PrintAndFlushErrorDiagnostic()86 std::string DiagnosticEngine::PrintAndFlushErrorDiagnostic()
87 {
88     auto log = GetErrorDiagnostic();
89     std::sort(log.begin(), log.end(), [](const auto &lhs, const auto &rhs) { return *lhs < *rhs; });
90     auto last = std::unique(log.begin(), log.end(), [](const auto &lhs, const auto &rhs) { return *lhs == *rhs; });
91     std::ostringstream oss;
92     for (auto it = log.begin(); it != last; ++it) {
93         printer_->Print(**it, oss);
94     }
95     return oss.str();
96 }
97 
FlushDiagnostic()98 void DiagnosticEngine::FlushDiagnostic()
99 {
100     auto log = GetAllDiagnostic();
101     std::sort(log.begin(), log.end(), [](const auto &lhs, const auto &rhs) { return *lhs < *rhs; });
102     auto last =
103         std::unique(log.begin(), log.end(), [&](const auto &rhs, const auto &lhs) -> bool { return *rhs == *lhs; });
104     for (auto it = log.begin(); it != last; it++) {
105         printer_->Print(**it);
106     }
107     for (auto &vec : diagnostics_) {
108         vec.clear();
109     }
110 }
111 #ifndef FUZZING_EXIT_ON_FAILED_ASSERT
SigSegvHandler(int sig)112 static void SigSegvHandler([[maybe_unused]] int sig)
113 {
114     CompilerBugAction(lexer::SourcePosition {});
115     ark::PrintStack(ark::GetStacktrace(), std::cerr);
116     std::abort();  // CC-OFF(G.STD.16-CPP) fatal error
117 }
118 #endif
119 
InitializeSignalHandlers()120 void DiagnosticEngine::InitializeSignalHandlers()
121 {
122 #ifndef FUZZING_EXIT_ON_FAILED_ASSERT
123     std::signal(SIGSEGV, SigSegvHandler);
124 #endif
125 }
126 
IsAnyError() const127 bool DiagnosticEngine::IsAnyError() const noexcept
128 {
129     for (size_t i = DiagnosticType::BEGIN; i < DiagnosticType::COUNT; ++i) {
130         if (IsError(static_cast<DiagnosticType>(i)) && !diagnostics_[i].empty()) {
131             return true;
132         }
133     }
134     return false;
135 }
136 
GetAnyError() const137 const DiagnosticBase &DiagnosticEngine::GetAnyError() const
138 {
139     ES2PANDA_ASSERT(IsAnyError());
140     for (size_t i = DiagnosticType::BEGIN; i < DiagnosticType::COUNT; ++i) {
141         if (IsError(static_cast<DiagnosticType>(i)) && !diagnostics_[i].empty()) {
142             return *diagnostics_[i].front();
143         }
144     }
145     ES2PANDA_UNREACHABLE();
146 }
147 
IsError(DiagnosticType type) const148 bool DiagnosticEngine::IsError(DiagnosticType type) const
149 {
150     switch (type) {
151         case DiagnosticType::FATAL:
152         case DiagnosticType::SYNTAX:
153         case DiagnosticType::SEMANTIC:
154         case DiagnosticType::PLUGIN_ERROR:
155         case DiagnosticType::DECLGEN_ETS2TS_ERROR:
156         case DiagnosticType::ARKTS_CONFIG_ERROR:
157         case DiagnosticType::ISOLATED_DECLGEN:
158             return true;
159         case DiagnosticType::WARNING:
160         case DiagnosticType::DECLGEN_ETS2TS_WARNING:
161         case DiagnosticType::PLUGIN_WARNING:
162             return wError_;
163         case DiagnosticType::SUGGESTION:
164             return false;
165         default:
166             ES2PANDA_UNREACHABLE();
167     }
168 }
169 
170 }  // namespace ark::es2panda::util
171