• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021 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_HELPERS_H
17 #define ES2PANDA_UTIL_HELPERS_H
18 
19 #include "varbinder/variableFlags.h"
20 #include "mem/pool_manager.h"
21 #include "util/ustring.h"
22 #include "ir/module/importSpecifier.h"
23 
24 #include <cmath>
25 #include <string>
26 
27 namespace panda::es2panda::varbinder {
28 class Variable;
29 }  // namespace panda::es2panda::varbinder
30 
31 namespace panda::es2panda::checker {
32 class ETSObjectType;
33 class Type;
34 }  // namespace panda::es2panda::checker
35 
36 namespace panda::es2panda::compiler {
37 class Literal;
38 }  // namespace panda::es2panda::compiler
39 
40 namespace panda::es2panda::ir {
41 class Expression;
42 class ScriptFunction;
43 class ClassDefinition;
44 class ClassProperty;
45 class Identifier;
46 class MethodDefinition;
47 class AstNode;
48 class ReturnStatement;
49 class CallExpression;
50 class ClassStaticBlock;
51 class TSInterfaceDeclaration;
52 class TSEnumDeclaration;
53 class ETSImportDeclaration;
54 enum class AstNodeType;
55 }  // namespace panda::es2panda::ir
56 
57 namespace panda::es2panda::util {
58 enum class LogLevel : std::uint8_t {
59     DEBUG,
60     INFO,
61     WARNING,
62     ERROR,
63     FATAL,
64 };
65 
66 class Helpers {
67 public:
68     Helpers() = delete;
69 
70     static bool IsGlobalIdentifier(const util::StringView &str);
71     static bool ContainSpreadElement(const ArenaVector<ir::Expression *> &args);
72     static util::StringView LiteralToPropName(const ir::Expression *lit);
73 
74     template <typename T>
75     static bool IsInteger(double number);
76     static bool IsIndex(double number);
77     static int64_t GetIndex(const util::StringView &str);
78 
79     static std::string ToString(double number);
80     static util::StringView ToStringView(ArenaAllocator *allocator, double number);
81     static util::StringView ToStringView(ArenaAllocator *allocator, int32_t number);
82     static util::StringView ToStringView(ArenaAllocator *allocator, uint32_t number);
83     static bool IsRelativePath(const std::string &path);
84     static bool IsRealPath(const std::string &path);
85     static std::string GetAbsPath(const std::string &path);
86 
87     static const ir::ScriptFunction *GetContainingConstructor(const ir::AstNode *node);
88     static const ir::ScriptFunction *GetContainingConstructor(const ir::ClassProperty *node);
89 
90     template <typename T,
91               typename U = std::enable_if_t<
92                   std::is_convertible_v<std::remove_const_t<std::remove_pointer_t<T>> *, ir::AstNode *>,
93                   std::conditional_t<std::is_const_v<std::remove_pointer_t<T>>, const ir::AstNode *, ir::AstNode *>>>
FindAncestorGivenByType(T node,ir::AstNodeType type)94     static U FindAncestorGivenByType(T node, ir::AstNodeType type)
95     {
96         U iter = node->Parent();
97 
98         while (iter->Type() != type) {
99             if (iter->Parent() != nullptr) {
100                 iter = iter->Parent();
101                 continue;
102             }
103 
104             return nullptr;
105         }
106 
107         return iter;
108     }
109 
110     static const checker::ETSObjectType *GetContainingObjectType(const ir::AstNode *node);
111     static const ir::TSEnumDeclaration *GetContainingEnumDeclaration(const ir::AstNode *node);
112     static const ir::ClassDefinition *GetContainingClassDefinition(const ir::AstNode *node);
113     static const ir::TSInterfaceDeclaration *GetContainingInterfaceDeclaration(const ir::AstNode *node);
114     static const ir::MethodDefinition *GetContainingClassMethodDefinition(const ir::AstNode *node);
115     static const ir::ClassStaticBlock *GetContainingClassStaticBlock(const ir::AstNode *node);
116     static const ir::ScriptFunction *GetContainingFunction(const ir::AstNode *node);
117     static const ir::ClassDefinition *GetClassDefiniton(const ir::ScriptFunction *node);
118     static bool IsSpecialPropertyKey(const ir::Expression *expr);
119     static bool IsConstantPropertyKey(const ir::Expression *expr, bool isComputed);
120     static compiler::Literal ToConstantLiteral(const ir::Expression *expr);
121     static bool IsBindingPattern(const ir::AstNode *node);
122     static bool IsPattern(const ir::AstNode *node);
123     static std::vector<ir::Identifier *> CollectBindingNames(ir::AstNode *node);
124     static util::StringView FunctionName(ArenaAllocator *allocator, const ir::ScriptFunction *func);
125     static void CheckImportedName(ArenaVector<ir::AstNode *> *specifiers, const ir::ImportSpecifier *specifier,
126                                   const std::string &fileName);
127     static std::tuple<util::StringView, bool> ParamName(ArenaAllocator *allocator, const ir::AstNode *param,
128                                                         uint32_t index);
129 
130     template <typename Source, typename Target>
IsTargetFitInSourceRange(Target target)131     static bool IsTargetFitInSourceRange(Target target)
132     {
133         if (!std::isfinite(target)) {
134             return true;
135         }
136 
137         // NOLINTNEXTLINE(misc-redundant-expression)
138         return target >= std::numeric_limits<Source>::lowest() &&
139                target <= static_cast<Target>(std::numeric_limits<Source>::max());
140     }
141 
142     static const uint32_t INVALID_INDEX = 4294967295L;
143 
144     static std::string CreateEscapedString(const std::string &str);
145     static std::string UTF16toUTF8(char16_t c);
146 
147     template <typename... Elements>
148     static void LogDebug(Elements &&...elems);
149     template <typename... Elements>
150     static void LogInfo(Elements &&...elems);
151     template <typename... Elements>
152     static void LogWarning(Elements &&...elems);
153     template <typename... Elements>
154     static void LogError(Elements &&...elems);
155     template <typename... Elements>
156     static void LogFatal(Elements &&...elems);
157 
158     template <typename... Elements>
159     static std::string AppendAll(Elements &&...elems);
160 
161     static std::pair<std::string_view, std::string_view> SplitSignature(std::string_view signature);
162 
163 private:
164     template <LogLevel LOG_L, typename... Elements>
165     static void Log(Elements &&...elems);
166 };
167 
168 template <typename T>
IsInteger(double number)169 bool Helpers::IsInteger(double number)
170 {
171     if (std::fabs(number) <= static_cast<double>(std::numeric_limits<T>::max())) {
172         T intNum = static_cast<T>(number);
173 
174         if (static_cast<double>(intNum) == number) {
175             return true;
176         }
177     }
178 
179     return false;
180 }
181 
182 template <LogLevel LOG_L, typename... Elements>
Log(Elements &&...elems)183 void Helpers::Log(Elements &&...elems)
184 {
185     constexpr auto ES2PANDA = panda::Logger::Component::ES2PANDA;
186     constexpr auto LOG_LEVEL = []() {
187         switch (LOG_L) {
188             case LogLevel::DEBUG: {
189                 return panda::Logger::Level::DEBUG;
190             }
191             case LogLevel::INFO: {
192                 return panda::Logger::Level::INFO;
193             }
194             case LogLevel::WARNING: {
195                 return panda::Logger::Level::WARNING;
196             }
197             case LogLevel::ERROR: {
198                 return panda::Logger::Level::ERROR;
199             }
200             case LogLevel::FATAL: {
201                 return panda::Logger::Level::FATAL;
202             }
203             default: {
204                 UNREACHABLE_CONSTEXPR();
205             }
206         }
207     }();
208 
209 #ifndef NDEBUG
210     const bool isMessageSuppressed = panda::Logger::IsMessageSuppressed(LOG_LEVEL, ES2PANDA);
211 #else
212     const bool isMessageSuppressed = false;
213 #endif
214     if (!panda::Logger::IsLoggingOnOrAbort(LOG_LEVEL, ES2PANDA) || isMessageSuppressed) {
215         return;
216     }
217 
218     (panda::Logger::Message(LOG_LEVEL, ES2PANDA, false).GetStream() << ... << std::forward<Elements>(elems));
219 }
220 
221 template <typename... Elements>
LogDebug(Elements &&...elems)222 void Helpers::LogDebug(Elements &&...elems)
223 {
224     Helpers::Log<LogLevel::DEBUG>(std::forward<Elements>(elems)...);
225 }
226 
227 template <typename... Elements>
LogInfo(Elements &&...elems)228 void Helpers::LogInfo(Elements &&...elems)
229 {
230     Helpers::Log<LogLevel::INFO>(std::forward<Elements>(elems)...);
231 }
232 
233 template <typename... Elements>
LogWarning(Elements &&...elems)234 void Helpers::LogWarning(Elements &&...elems)
235 {
236     Helpers::Log<LogLevel::WARNING>(std::forward<Elements>(elems)...);
237 }
238 
239 template <typename... Elements>
LogError(Elements &&...elems)240 void Helpers::LogError(Elements &&...elems)
241 {
242     Helpers::Log<LogLevel::ERROR>(std::forward<Elements>(elems)...);
243 }
244 
245 template <typename... Elements>
LogFatal(Elements &&...elems)246 void Helpers::LogFatal(Elements &&...elems)
247 {
248     Helpers::Log<LogLevel::FATAL>(std::forward<Elements>(elems)...);
249 }
250 
251 template <typename... Elements>
AppendAll(Elements &&...elems)252 std::string Helpers::AppendAll(Elements &&...elems)
253 {
254     std::string ret {};
255     ((ret += std::forward<Elements>(elems)), ...);
256     return ret;
257 }
258 
259 }  // namespace panda::es2panda::util
260 
261 #endif
262