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