/** * Copyright (c) 2021-2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ES2PANDA_UTIL_HELPERS_H #define ES2PANDA_UTIL_HELPERS_H #include "varbinder/variableFlags.h" #include "mem/pool_manager.h" #include "util/ustring.h" #include "ir/module/importSpecifier.h" #include "parser/program/program.h" #include #include namespace ark::es2panda::varbinder { class Variable; } // namespace ark::es2panda::varbinder namespace ark::es2panda::checker { class ETSObjectType; class Type; } // namespace ark::es2panda::checker namespace ark::es2panda::compiler { class Literal; } // namespace ark::es2panda::compiler namespace ark::es2panda::ir { class Expression; class ScriptFunction; class ClassDefinition; class ClassProperty; class Identifier; class MethodDefinition; class AstNode; class ReturnStatement; class CallExpression; class ClassStaticBlock; class TSInterfaceDeclaration; class TSEnumDeclaration; class ETSImportDeclaration; enum class AstNodeType; } // namespace ark::es2panda::ir namespace ark::es2panda::util { enum class LogLevel : std::uint8_t { DEBUG, INFO, WARNING, ERROR, FATAL, INVALID, }; class NodeAllocator { public: template static T *NoSetParent(ArenaAllocator *alloc, Args &&...args) { return alloc->New(std::forward(args)...); } template static T *ForceSetParent(ArenaAllocator *alloc, Args &&...args) { auto *ret = NoSetParent(alloc, std::forward(args)...); if (ret == nullptr) { return nullptr; } ret->Iterate([ret](ir::AstNode *child) { child->SetParent(ret); }); return ret; } template static T *Alloc(ArenaAllocator *alloc, Args &&...args) { auto *ret = NoSetParent(alloc, std::forward(args)...); if (ret == nullptr) { return nullptr; } ret->Iterate([ret](ir::AstNode *child) { ASSERT(child->Parent() == nullptr); child->SetParent(ret); }); return ret; } }; class Helpers { public: Helpers() = delete; static bool IsGlobalIdentifier(const util::StringView &str); static bool ContainSpreadElement(const ArenaVector &args); static util::StringView LiteralToPropName(const ir::Expression *lit); template static bool IsInteger(double number); static bool IsIndex(double number); static int64_t GetIndex(const util::StringView &str); static std::string ToString(double number); static util::StringView ToStringView(ArenaAllocator *allocator, double number); static util::StringView ToStringView(ArenaAllocator *allocator, int32_t number); static util::StringView ToStringView(ArenaAllocator *allocator, uint32_t number); static bool EndsWith(const std::string &str, const std::string &suffix); static const ir::ScriptFunction *GetContainingConstructor(const ir::AstNode *node); static const ir::ScriptFunction *GetContainingConstructor(const ir::ClassProperty *node); template > *, ir::AstNode *>, std::conditional_t>, const ir::AstNode *, ir::AstNode *>>> static U FindAncestorGivenByType(T node, ir::AstNodeType type) { U iter = node->Parent(); while (iter->Type() != type) { if (iter->Parent() != nullptr) { iter = iter->Parent(); continue; } return nullptr; } return iter; } static const checker::ETSObjectType *GetContainingObjectType(const ir::AstNode *node); static const ir::TSEnumDeclaration *GetContainingEnumDeclaration(const ir::AstNode *node); static const ir::ClassDefinition *GetContainingClassDefinition(const ir::AstNode *node); static const ir::TSInterfaceDeclaration *GetContainingInterfaceDeclaration(const ir::AstNode *node); static const ir::MethodDefinition *GetContainingClassMethodDefinition(const ir::AstNode *node); static const ir::ClassStaticBlock *GetContainingClassStaticBlock(const ir::AstNode *node); static const ir::ScriptFunction *GetContainingFunction(const ir::AstNode *node); static const ir::ClassDefinition *GetClassDefiniton(const ir::ScriptFunction *node); static bool IsSpecialPropertyKey(const ir::Expression *expr); static bool IsConstantPropertyKey(const ir::Expression *expr, bool isComputed); static compiler::Literal ToConstantLiteral(const ir::Expression *expr); static bool IsBindingPattern(const ir::AstNode *node); static bool IsPattern(const ir::AstNode *node); static std::vector CollectBindingNames(ir::AstNode *node); static util::StringView FunctionName(ArenaAllocator *allocator, const ir::ScriptFunction *func); static void CheckImportedName(const ArenaVector &specifiers, const ir::ImportSpecifier *specifier, const std::string &fileName); static void CheckDefaultImportedName(const ArenaVector &specifiers, const ir::ImportDefaultSpecifier *specifier, const std::string &fileName); static void CheckDefaultImport(const ArenaVector &statements); static std::tuple ParamName(ArenaAllocator *allocator, const ir::AstNode *param, uint32_t index); template static ArenaVector ConvertVector(const ArenaVector &src) { ArenaVector dst(src.begin(), src.end(), src.get_allocator()); return dst; } template static bool IsTargetFitInSourceRange(Target target) { if (!std::isfinite(target)) { return true; } // NOLINTNEXTLINE(misc-redundant-expression) return target >= std::numeric_limits::lowest() && target <= static_cast(std::numeric_limits::max()); } static const uint32_t INVALID_INDEX = 4294967295L; static std::string CreateEscapedString(const std::string &str); static std::string UTF16toUTF8(const char16_t c); template static void LogDebug(Elements &&...elems); template static void LogInfo(Elements &&...elems); template static void LogWarning(Elements &&...elems); template static void LogError(Elements &&...elems); template static void LogFatal(Elements &&...elems); template static std::string AppendAll(Elements &&...elems); static std::pair SplitSignature(std::string_view signature); static std::vector &StdLib(); static bool IsStdLib(const parser::Program *program); private: template static void Log(Elements &&...elems); }; template bool Helpers::IsInteger(double number) { if (std::fabs(number) <= static_cast(std::numeric_limits::max())) { T intNum = static_cast(number); if (static_cast(intNum) == number) { return true; } } return false; } template void Helpers::Log(Elements &&...elems) { constexpr auto ES2PANDA = ark::Logger::Component::ES2PANDA; constexpr auto LOG_LEVEL = []() { switch (LOG_L) { case LogLevel::DEBUG: { return ark::Logger::Level::DEBUG; } case LogLevel::INFO: { return ark::Logger::Level::INFO; } case LogLevel::WARNING: { return ark::Logger::Level::WARNING; } case LogLevel::ERROR: { return ark::Logger::Level::ERROR; } case LogLevel::FATAL: { return ark::Logger::Level::FATAL; } default: { UNREACHABLE_CONSTEXPR(); } } }(); #ifndef NDEBUG const bool isMessageSuppressed = ark::Logger::IsMessageSuppressed(LOG_LEVEL, ES2PANDA); #else const bool isMessageSuppressed = false; #endif if (!ark::Logger::IsLoggingOnOrAbort(LOG_LEVEL, ES2PANDA) || isMessageSuppressed) { return; } (ark::Logger::Message(LOG_LEVEL, ES2PANDA, false).GetStream() << ... << std::forward(elems)); } template void Helpers::LogDebug(Elements &&...elems) { Helpers::Log(std::forward(elems)...); } template void Helpers::LogInfo(Elements &&...elems) { Helpers::Log(std::forward(elems)...); } template void Helpers::LogWarning(Elements &&...elems) { Helpers::Log(std::forward(elems)...); } template void Helpers::LogError(Elements &&...elems) { Helpers::Log(std::forward(elems)...); } template void Helpers::LogFatal(Elements &&...elems) { Helpers::Log(std::forward(elems)...); } template std::string Helpers::AppendAll(Elements &&...elems) { std::string ret {}; ((ret += std::forward(elems)), ...); return ret; } } // namespace ark::es2panda::util #endif