1 /**
2 * Copyright (c) 2021-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_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 ark::es2panda::parser {
28 class Program;
29 } // namespace ark::es2panda::parser
30
31 namespace ark::es2panda::varbinder {
32 class Variable;
33 } // namespace ark::es2panda::varbinder
34
35 namespace ark::es2panda::checker {
36 class ETSObjectType;
37 class Type;
38 } // namespace ark::es2panda::checker
39
40 namespace ark::es2panda::compiler {
41 class Literal;
42 } // namespace ark::es2panda::compiler
43
44 namespace ark::es2panda::ir {
45 class Expression;
46 class ScriptFunction;
47 class ClassDefinition;
48 class ClassProperty;
49 class Identifier;
50 class MethodDefinition;
51 class AstNode;
52 class ReturnStatement;
53 class CallExpression;
54 class ClassStaticBlock;
55 class TSInterfaceDeclaration;
56 class TSEnumDeclaration;
57 class ETSImportDeclaration;
58 enum class AstNodeType;
59 } // namespace ark::es2panda::ir
60
61 namespace ark::es2panda::util {
62
63 class NodeAllocator {
64 public:
65 template <typename T, typename... Args>
NoSetParent(ArenaAllocator * alloc,Args &&...args)66 static T *NoSetParent(ArenaAllocator *alloc, Args &&...args)
67 {
68 return alloc->New<T>(std::forward<Args>(args)...);
69 }
70
71 template <typename T, typename... Args>
ForceSetParent(ArenaAllocator * alloc,Args &&...args)72 static T *ForceSetParent(ArenaAllocator *alloc, Args &&...args)
73 {
74 auto *ret = NoSetParent<T>(alloc, std::forward<Args>(args)...);
75 if (ret == nullptr) {
76 return nullptr;
77 }
78 ret->Iterate([ret](ir::AstNode *child) { child->SetParent(ret); });
79 return ret;
80 }
81
82 template <typename T, typename... Args>
Alloc(ArenaAllocator * alloc,Args &&...args)83 static T *Alloc(ArenaAllocator *alloc, Args &&...args)
84 {
85 auto *ret = NoSetParent<T>(alloc, std::forward<Args>(args)...);
86 if (ret == nullptr) {
87 return nullptr;
88 }
89 ret->Iterate([ret](ir::AstNode *child) {
90 ES2PANDA_ASSERT(child->Parent() == nullptr);
91 child->SetParent(ret);
92 });
93 return ret;
94 }
95 };
96
97 class Helpers {
98 public:
99 Helpers() = delete;
100
101 static bool IsGlobalIdentifier(const util::StringView &str);
102 static bool ContainSpreadElement(const ArenaVector<ir::Expression *> &args);
103 static util::StringView LiteralToPropName(const ir::Expression *lit);
104
105 template <typename T>
106 static bool IsInteger(double number);
107 static bool IsIndex(double number);
108 static int64_t GetIndex(const util::StringView &str);
109
110 static std::string ToString(double number);
111 static util::StringView ToStringView(ArenaAllocator *allocator, double number);
112 static util::StringView ToStringView(ArenaAllocator *allocator, int32_t number);
113 static util::StringView ToStringView(ArenaAllocator *allocator, uint32_t number);
114 static bool EndsWith(const std::string &str, const std::string &suffix);
115
116 static const ir::ScriptFunction *GetContainingConstructor(const ir::AstNode *node);
117 static const ir::ScriptFunction *GetContainingConstructor(const ir::ClassProperty *node);
118
119 template <typename T,
120 typename U = std::enable_if_t<
121 std::is_convertible_v<std::remove_const_t<std::remove_pointer_t<T>> *, ir::AstNode *>,
122 std::conditional_t<std::is_const_v<std::remove_pointer_t<T>>, const ir::AstNode *, ir::AstNode *>>>
FindAncestorGivenByType(T node,ir::AstNodeType type)123 static U FindAncestorGivenByType(T node, ir::AstNodeType type)
124 {
125 U iter = node->Parent();
126
127 while (iter->Type() != type) {
128 if (iter->Parent() != nullptr) {
129 iter = iter->Parent();
130 continue;
131 }
132
133 return nullptr;
134 }
135
136 return iter;
137 }
138
139 static const checker::ETSObjectType *GetContainingObjectType(const ir::AstNode *node);
140 static const ir::TSEnumDeclaration *GetContainingEnumDeclaration(const ir::AstNode *node);
141 static const ir::ClassDefinition *GetContainingClassDefinition(const ir::AstNode *node);
142 static const ir::TSInterfaceDeclaration *GetContainingInterfaceDeclaration(const ir::AstNode *node);
143 static const ir::MethodDefinition *GetContainingClassMethodDefinition(const ir::AstNode *node);
144 static const ir::ClassStaticBlock *GetContainingClassStaticBlock(const ir::AstNode *node);
145 static const ir::ScriptFunction *GetContainingFunction(const ir::AstNode *node);
146 static const ir::ClassDefinition *GetClassDefiniton(const ir::ScriptFunction *node);
147 static bool IsSpecialPropertyKey(const ir::Expression *expr);
148 static bool IsConstantPropertyKey(const ir::Expression *expr, bool isComputed);
149 static compiler::Literal ToConstantLiteral(const ir::Expression *expr);
150 static bool IsBindingPattern(const ir::AstNode *node);
151 static bool IsPattern(const ir::AstNode *node);
152 static std::vector<ir::Identifier *> CollectBindingNames(varbinder::VarBinder *vb, ir::Expression *node);
153 static util::StringView FunctionName(ArenaAllocator *allocator, const ir::ScriptFunction *func);
154 static void CheckImportedName(const ArenaVector<ir::ImportSpecifier *> &specifiers,
155 const ir::ImportSpecifier *specifier, const std::string &fileName);
156 static void CheckDefaultImportedName(const ArenaVector<ir::ImportDefaultSpecifier *> &specifiers,
157 const ir::ImportDefaultSpecifier *specifier, const std::string &fileName);
158 static void CheckDefaultImport(const ArenaVector<ir::ETSImportDeclaration *> &statements);
159 static std::tuple<util::StringView, bool> ParamName(ArenaAllocator *allocator, const ir::Expression *param,
160 std::uint32_t index);
161 static bool IsAsyncMethod(ir::AstNode const *node);
162
163 static bool IsGlobalVar(const ark::es2panda::varbinder::Variable *var);
164
165 template <typename T, typename V>
ConvertVector(const ArenaVector<V * > & src)166 static ArenaVector<T *> ConvertVector(const ArenaVector<V *> &src)
167 {
168 ArenaVector<T *> dst(src.begin(), src.end(), src.get_allocator());
169 return dst;
170 }
171
172 template <typename Source, typename Target>
IsTargetFitInSourceRange(Target target)173 static bool IsTargetFitInSourceRange(Target target)
174 {
175 if (!std::isfinite(target)) {
176 return true;
177 }
178
179 // NOLINTNEXTLINE(misc-redundant-expression)
180 return target >= std::numeric_limits<Source>::lowest() &&
181 target <= static_cast<Target>(std::numeric_limits<Source>::max());
182 }
183
184 static const uint32_t INVALID_INDEX = 4294967295L;
185
186 static std::string CreateEscapedString(const std::string &str);
187 static std::string UTF16toUTF8(const char16_t c);
188
189 template <typename... Elements>
190 static std::string AppendAll(Elements &&...elems);
191
192 static std::pair<std::string_view, std::string_view> SplitSignature(std::string_view signature);
193
194 static std::vector<std::string> const &StdLib();
195 static bool IsStdLib(const parser::Program *program);
196 [[nodiscard]] static checker::Type *CheckReturnTypeOfCheck([[maybe_unused]] const ir::AstNode *const node,
197 checker::Type *const type);
198
199 [[nodiscard]] static util::UString EscapeHTMLString(ArenaAllocator *allocator, const std::string &str);
200 [[nodiscard]] static ir::AstNode *DerefETSTypeReference(ir::AstNode *node);
201 };
202
203 template <typename T>
IsInteger(double number)204 bool Helpers::IsInteger(double number)
205 {
206 if (std::fabs(number) <= static_cast<double>(std::numeric_limits<T>::max())) {
207 T intNum = static_cast<T>(number);
208
209 if (static_cast<double>(intNum) == number) {
210 return true;
211 }
212 }
213
214 return false;
215 }
216
217 template <typename... Elements>
AppendAll(Elements &&...elems)218 std::string Helpers::AppendAll(Elements &&...elems)
219 {
220 std::string ret {};
221 ((ret += std::forward<Elements>(elems)), ...);
222 return ret;
223 }
224
225 } // namespace ark::es2panda::util
226
227 #endif
228