13af6ab5fSopenharmony_ci/**
23af6ab5fSopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License.
53af6ab5fSopenharmony_ci * You may obtain a copy of the License at
63af6ab5fSopenharmony_ci *
73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
83af6ab5fSopenharmony_ci *
93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and
133af6ab5fSopenharmony_ci * limitations under the License.
143af6ab5fSopenharmony_ci */
153af6ab5fSopenharmony_ci
163af6ab5fSopenharmony_ci#include "declgenEts2Ts.h"
173af6ab5fSopenharmony_ci
183af6ab5fSopenharmony_ci#include "ir/base/classProperty.h"
193af6ab5fSopenharmony_ci#include "ir/base/methodDefinition.h"
203af6ab5fSopenharmony_ci#include "ir/base/scriptFunction.h"
213af6ab5fSopenharmony_ci#include "ir/ets/etsImportDeclaration.h"
223af6ab5fSopenharmony_ci#include "ir/expressions/identifier.h"
233af6ab5fSopenharmony_ci#include "ir/expressions/literals/numberLiteral.h"
243af6ab5fSopenharmony_ci#include "ir/module/importSpecifier.h"
253af6ab5fSopenharmony_ci#include "ir/statements/blockStatement.h"
263af6ab5fSopenharmony_ci#include "ir/statements/classDeclaration.h"
273af6ab5fSopenharmony_ci#include "ir/ts/tsEnumMember.h"
283af6ab5fSopenharmony_ci#include "ir/ts/tsInterfaceBody.h"
293af6ab5fSopenharmony_ci#include "ir/ts/tsTypeAliasDeclaration.h"
303af6ab5fSopenharmony_ci#include "ir/ts/tsTypeParameter.h"
313af6ab5fSopenharmony_ci
323af6ab5fSopenharmony_ci#define DEBUG_PRINT 0
333af6ab5fSopenharmony_ci
343af6ab5fSopenharmony_cinamespace ark::es2panda::declgen_ets2ts {
353af6ab5fSopenharmony_ci
363af6ab5fSopenharmony_cistatic void DebugPrint([[maybe_unused]] const std::string &msg)
373af6ab5fSopenharmony_ci{
383af6ab5fSopenharmony_ci#if DEBUG_PRINT
393af6ab5fSopenharmony_ci    std::cerr << msg << std::endl;
403af6ab5fSopenharmony_ci#endif
413af6ab5fSopenharmony_ci}
423af6ab5fSopenharmony_ci
433af6ab5fSopenharmony_cistatic void Warning(const std::string &msg)
443af6ab5fSopenharmony_ci{
453af6ab5fSopenharmony_ci    std::cerr << "Warning declgen ets2ts: " << msg << std::endl;
463af6ab5fSopenharmony_ci}
473af6ab5fSopenharmony_ci
483af6ab5fSopenharmony_civoid TSDeclGen::Generate()
493af6ab5fSopenharmony_ci{
503af6ab5fSopenharmony_ci    std::stringstream license;
513af6ab5fSopenharmony_ci    license << "/*\n";
523af6ab5fSopenharmony_ci    license << " * Copyright (c) 2023-2024 Huawei Device Co., Ltd.\n";
533af6ab5fSopenharmony_ci    license << " * Licensed under the Apache License, Version 2.0 (the \"License\");\n";
543af6ab5fSopenharmony_ci    license << " * you may not use this file except in compliance with the License.\n";
553af6ab5fSopenharmony_ci    license << " * You may obtain a copy of the License at\n";
563af6ab5fSopenharmony_ci    license << " *\n";
573af6ab5fSopenharmony_ci    license << " *     http://www.apache.org/licenses/LICENSE-2.0\n";
583af6ab5fSopenharmony_ci    license << " *\n";
593af6ab5fSopenharmony_ci    license << " * Unless required by applicable law or agreed to in writing, software\n";
603af6ab5fSopenharmony_ci    license << " * distributed under the License is distributed on an \"AS IS\" BASIS,\n";
613af6ab5fSopenharmony_ci    license << " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n";
623af6ab5fSopenharmony_ci    license << " * See the License for the specific language governing permissions and\n";
633af6ab5fSopenharmony_ci    license << " * limitations under the License.\n";
643af6ab5fSopenharmony_ci    license << " */\n\n";
653af6ab5fSopenharmony_ci    Out(license.str());
663af6ab5fSopenharmony_ci    Out("declare const exports: any;");
673af6ab5fSopenharmony_ci    OutEndl();
683af6ab5fSopenharmony_ci    Out("let ETSGLOBAL: any = (globalThis as any).Panda.getClass('LETSGLOBAL;');");
693af6ab5fSopenharmony_ci    OutEndl(2U);
703af6ab5fSopenharmony_ci
713af6ab5fSopenharmony_ci    for (auto *globalStatement : program_->Ast()->Statements()) {
723af6ab5fSopenharmony_ci        ResetState();
733af6ab5fSopenharmony_ci        if (globalStatement->IsETSImportDeclaration()) {
743af6ab5fSopenharmony_ci            GenImportDeclaration(globalStatement->AsETSImportDeclaration());
753af6ab5fSopenharmony_ci        } else if (globalStatement->IsTSEnumDeclaration()) {
763af6ab5fSopenharmony_ci            GenEnumDeclaration(globalStatement->AsTSEnumDeclaration());
773af6ab5fSopenharmony_ci        } else if (globalStatement->IsClassDeclaration()) {
783af6ab5fSopenharmony_ci            // The classes generated for enums starts with '#' but those are invalid names and
793af6ab5fSopenharmony_ci            // not requred for the ts code
803af6ab5fSopenharmony_ci            if (globalStatement->AsClassDeclaration()->Definition()->Ident()->Name().Mutf8().find('#') ==
813af6ab5fSopenharmony_ci                std::string::npos) {
823af6ab5fSopenharmony_ci                GenClassDeclaration(globalStatement->AsClassDeclaration());
833af6ab5fSopenharmony_ci            }
843af6ab5fSopenharmony_ci        } else if (globalStatement->IsTSInterfaceDeclaration()) {
853af6ab5fSopenharmony_ci            GenInterfaceDeclaration(globalStatement->AsTSInterfaceDeclaration());
863af6ab5fSopenharmony_ci        } else if (globalStatement->IsTSTypeAliasDeclaration()) {
873af6ab5fSopenharmony_ci            GenTypeAliasDeclaration(globalStatement->AsTSTypeAliasDeclaration());
883af6ab5fSopenharmony_ci        }
893af6ab5fSopenharmony_ci    }
903af6ab5fSopenharmony_ci}
913af6ab5fSopenharmony_ci
923af6ab5fSopenharmony_citemplate <class T, class CB>
933af6ab5fSopenharmony_civoid TSDeclGen::GenSeparated(const T &container, const CB &cb, const char *separator)
943af6ab5fSopenharmony_ci{
953af6ab5fSopenharmony_ci    if (container.empty()) {
963af6ab5fSopenharmony_ci        return;
973af6ab5fSopenharmony_ci    }
983af6ab5fSopenharmony_ci
993af6ab5fSopenharmony_ci    cb(container[0]);
1003af6ab5fSopenharmony_ci    for (std::size_t i = 1; i < container.size(); ++i) {
1013af6ab5fSopenharmony_ci        Out(separator);
1023af6ab5fSopenharmony_ci        cb(container[i]);
1033af6ab5fSopenharmony_ci    }
1043af6ab5fSopenharmony_ci}
1053af6ab5fSopenharmony_ci
1063af6ab5fSopenharmony_civoid TSDeclGen::ThrowError(const std::string_view message, const lexer::SourcePosition &pos = lexer::SourcePosition())
1073af6ab5fSopenharmony_ci{
1083af6ab5fSopenharmony_ci    lexer::LineIndex index(program_->SourceCode());
1093af6ab5fSopenharmony_ci    const lexer::SourceLocation loc = index.GetLocation(pos);
1103af6ab5fSopenharmony_ci
1113af6ab5fSopenharmony_ci    throw Error {ErrorType::GENERIC, program_->SourceFilePath().Utf8(), "declgen ets2ts: " + std::string(message),
1123af6ab5fSopenharmony_ci                 loc.line, loc.col};
1133af6ab5fSopenharmony_ci}
1143af6ab5fSopenharmony_ci
1153af6ab5fSopenharmony_ciconst ir::Identifier *TSDeclGen::GetKeyIdent(const ir::Expression *key)
1163af6ab5fSopenharmony_ci{
1173af6ab5fSopenharmony_ci    if (!key->IsIdentifier()) {
1183af6ab5fSopenharmony_ci        ThrowError("Not identifier keys are not supported", key->Start());
1193af6ab5fSopenharmony_ci    }
1203af6ab5fSopenharmony_ci
1213af6ab5fSopenharmony_ci    return key->AsIdentifier();
1223af6ab5fSopenharmony_ci}
1233af6ab5fSopenharmony_ci
1243af6ab5fSopenharmony_cistatic char const *GetDebugTypeName(const checker::Type *checkerType)
1253af6ab5fSopenharmony_ci{
1263af6ab5fSopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
1273af6ab5fSopenharmony_ci#define TYPE_CHECKS(type_flag, typeName) \
1283af6ab5fSopenharmony_ci    if (checkerType->Is##typeName()) {   \
1293af6ab5fSopenharmony_ci        return #typeName;                \
1303af6ab5fSopenharmony_ci    }
1313af6ab5fSopenharmony_ci    TYPE_MAPPING(TYPE_CHECKS)
1323af6ab5fSopenharmony_ci#undef TYPE_CHECKS
1333af6ab5fSopenharmony_ci    return "unknown type";
1343af6ab5fSopenharmony_ci}
1353af6ab5fSopenharmony_ci
1363af6ab5fSopenharmony_civoid TSDeclGen::GenType(const checker::Type *checkerType)
1373af6ab5fSopenharmony_ci{
1383af6ab5fSopenharmony_ci    DebugPrint("  GenType: ");
1393af6ab5fSopenharmony_ci#if DEBUG_PRINT
1403af6ab5fSopenharmony_ci    const auto var_name = checkerType->Variable() == nullptr ? "" : checkerType->Variable()->Name().Mutf8();
1413af6ab5fSopenharmony_ci    DebugPrint(std::string("  Converting type: ") + GetDebugTypeName(checkerType) + " (" + var_name + ")");
1423af6ab5fSopenharmony_ci#endif
1433af6ab5fSopenharmony_ci
1443af6ab5fSopenharmony_ci    if (checkerType->HasTypeFlag(checker::TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC)) {
1453af6ab5fSopenharmony_ci        Out("number");
1463af6ab5fSopenharmony_ci        return;
1473af6ab5fSopenharmony_ci    }
1483af6ab5fSopenharmony_ci    if (checkerType->HasTypeFlag(checker::TypeFlag::FUNCTION)) {
1493af6ab5fSopenharmony_ci        GenFunctionType(checkerType->AsETSFunctionType());
1503af6ab5fSopenharmony_ci        return;
1513af6ab5fSopenharmony_ci    }
1523af6ab5fSopenharmony_ci
1533af6ab5fSopenharmony_ci    switch (checker::ETSChecker::ETSType(checkerType)) {
1543af6ab5fSopenharmony_ci        case checker::TypeFlag::ETS_VOID:
1553af6ab5fSopenharmony_ci        case checker::TypeFlag::ETS_NULL:
1563af6ab5fSopenharmony_ci        case checker::TypeFlag::ETS_UNDEFINED:
1573af6ab5fSopenharmony_ci        case checker::TypeFlag::ETS_BOOLEAN:
1583af6ab5fSopenharmony_ci        case checker::TypeFlag::ETS_TYPE_PARAMETER:
1593af6ab5fSopenharmony_ci        case checker::TypeFlag::ETS_NONNULLISH:
1603af6ab5fSopenharmony_ci        case checker::TypeFlag::ETS_READONLY:
1613af6ab5fSopenharmony_ci        case checker::TypeFlag::ETS_INT_ENUM:
1623af6ab5fSopenharmony_ci            Out(checkerType->ToString());
1633af6ab5fSopenharmony_ci            return;
1643af6ab5fSopenharmony_ci        case checker::TypeFlag::ETS_OBJECT:
1653af6ab5fSopenharmony_ci        case checker::TypeFlag::ETS_DYNAMIC_TYPE:
1663af6ab5fSopenharmony_ci            GenObjectType(checkerType->AsETSObjectType());
1673af6ab5fSopenharmony_ci            return;
1683af6ab5fSopenharmony_ci        case checker::TypeFlag::ETS_ARRAY:
1693af6ab5fSopenharmony_ci            GenType(checkerType->AsETSArrayType()->ElementType());
1703af6ab5fSopenharmony_ci            Out("[]");
1713af6ab5fSopenharmony_ci            return;
1723af6ab5fSopenharmony_ci        case checker::TypeFlag::ETS_UNION:
1733af6ab5fSopenharmony_ci            GenUnionType(checkerType->AsETSUnionType());
1743af6ab5fSopenharmony_ci            return;
1753af6ab5fSopenharmony_ci        default:
1763af6ab5fSopenharmony_ci            ThrowError(std::string("Unsupported type: '") + GetDebugTypeName(checkerType));
1773af6ab5fSopenharmony_ci    }
1783af6ab5fSopenharmony_ci}
1793af6ab5fSopenharmony_ci
1803af6ab5fSopenharmony_civoid TSDeclGen::GenLiteral(const ir::Literal *literal)
1813af6ab5fSopenharmony_ci{
1823af6ab5fSopenharmony_ci    if (!literal->IsNumberLiteral()) {
1833af6ab5fSopenharmony_ci        ThrowError("Unsupported literal type", literal->Start());
1843af6ab5fSopenharmony_ci    }
1853af6ab5fSopenharmony_ci
1863af6ab5fSopenharmony_ci    const auto number = literal->AsNumberLiteral()->Number();
1873af6ab5fSopenharmony_ci    if (number.IsInt()) {
1883af6ab5fSopenharmony_ci        Out(std::to_string(number.GetInt()));
1893af6ab5fSopenharmony_ci        return;
1903af6ab5fSopenharmony_ci    }
1913af6ab5fSopenharmony_ci    if (number.IsLong()) {
1923af6ab5fSopenharmony_ci        Out(std::to_string(number.GetLong()));
1933af6ab5fSopenharmony_ci        return;
1943af6ab5fSopenharmony_ci    }
1953af6ab5fSopenharmony_ci    if (number.IsFloat()) {
1963af6ab5fSopenharmony_ci        Out(std::to_string(number.GetFloat()));
1973af6ab5fSopenharmony_ci        return;
1983af6ab5fSopenharmony_ci    }
1993af6ab5fSopenharmony_ci    if (number.IsDouble()) {
2003af6ab5fSopenharmony_ci        Out(std::to_string(number.GetDouble()));
2013af6ab5fSopenharmony_ci        return;
2023af6ab5fSopenharmony_ci    }
2033af6ab5fSopenharmony_ci
2043af6ab5fSopenharmony_ci    ThrowError("Unexpected number literal type", literal->Start());
2053af6ab5fSopenharmony_ci}
2063af6ab5fSopenharmony_ci
2073af6ab5fSopenharmony_civoid TSDeclGen::GenFunctionBody(const ir::MethodDefinition *methodDef, const checker::Signature *sig,
2083af6ab5fSopenharmony_ci                                const bool isConstructor, const bool isSetter)
2093af6ab5fSopenharmony_ci{
2103af6ab5fSopenharmony_ci    if (isConstructor) {
2113af6ab5fSopenharmony_ci        if (state_.super != nullptr) {
2123af6ab5fSopenharmony_ci            Out("{ super(...{} as (ConstructorParameters<typeof ");
2133af6ab5fSopenharmony_ci            GenType(state_.super->TsType());
2143af6ab5fSopenharmony_ci            Out(">)); }");
2153af6ab5fSopenharmony_ci        } else {
2163af6ab5fSopenharmony_ci            Out(" {}");
2173af6ab5fSopenharmony_ci        }
2183af6ab5fSopenharmony_ci    } else if (isSetter) {
2193af6ab5fSopenharmony_ci        Out(" {}");
2203af6ab5fSopenharmony_ci    } else {
2213af6ab5fSopenharmony_ci        Out(methodDef != nullptr ? ": " : " => ");
2223af6ab5fSopenharmony_ci        GenType(sig->ReturnType());
2233af6ab5fSopenharmony_ci        if (methodDef != nullptr && !state_.inInterface) {
2243af6ab5fSopenharmony_ci            Out(" { return {} as any; }");
2253af6ab5fSopenharmony_ci        }
2263af6ab5fSopenharmony_ci    }
2273af6ab5fSopenharmony_ci}
2283af6ab5fSopenharmony_ci
2293af6ab5fSopenharmony_civoid TSDeclGen::GenFunctionType(const checker::ETSFunctionType *etsFunctionType, const ir::MethodDefinition *methodDef)
2303af6ab5fSopenharmony_ci{
2313af6ab5fSopenharmony_ci    const bool isConstructor = methodDef != nullptr ? methodDef->IsConstructor() : false;
2323af6ab5fSopenharmony_ci    const bool isSetter = methodDef != nullptr ? methodDef->Kind() == ir::MethodDefinitionKind::SET : false;
2333af6ab5fSopenharmony_ci
2343af6ab5fSopenharmony_ci    const auto *sig = [this, methodDef, etsFunctionType]() -> const checker::Signature * {
2353af6ab5fSopenharmony_ci        if (methodDef != nullptr) {
2363af6ab5fSopenharmony_ci            return methodDef->Function()->Signature();
2373af6ab5fSopenharmony_ci        }
2383af6ab5fSopenharmony_ci        if (etsFunctionType->CallSignatures().size() != 1) {
2393af6ab5fSopenharmony_ci            const auto loc = methodDef != nullptr ? methodDef->Start() : lexer::SourcePosition();
2403af6ab5fSopenharmony_ci            ThrowError("Method overloads are not supported", loc);
2413af6ab5fSopenharmony_ci        }
2423af6ab5fSopenharmony_ci        return etsFunctionType->CallSignatures()[0];
2433af6ab5fSopenharmony_ci    }();
2443af6ab5fSopenharmony_ci
2453af6ab5fSopenharmony_ci    const auto *func = sig->Function();
2463af6ab5fSopenharmony_ci    GenTypeParameters(func->TypeParams());
2473af6ab5fSopenharmony_ci    Out("(");
2483af6ab5fSopenharmony_ci
2493af6ab5fSopenharmony_ci    GenSeparated(sig->Params(), [this](varbinder::LocalVariable *param) {
2503af6ab5fSopenharmony_ci        Out(param->Name());
2513af6ab5fSopenharmony_ci        const auto *paramType = param->TsType();
2523af6ab5fSopenharmony_ci
2533af6ab5fSopenharmony_ci        if (param->HasFlag(varbinder::VariableFlags::OPTIONAL)) {
2543af6ab5fSopenharmony_ci            Out("?");
2553af6ab5fSopenharmony_ci        }
2563af6ab5fSopenharmony_ci        Out(": ");
2573af6ab5fSopenharmony_ci        GenType(paramType);
2583af6ab5fSopenharmony_ci    });
2593af6ab5fSopenharmony_ci
2603af6ab5fSopenharmony_ci    const auto *sigInfo = sig->GetSignatureInfo();
2613af6ab5fSopenharmony_ci    if (sigInfo->restVar != nullptr) {
2623af6ab5fSopenharmony_ci        if (!sig->Params().empty()) {
2633af6ab5fSopenharmony_ci            Out(", ");
2643af6ab5fSopenharmony_ci        }
2653af6ab5fSopenharmony_ci        Out("...", sigInfo->restVar->Name().Mutf8(), ": ");
2663af6ab5fSopenharmony_ci        GenType(sigInfo->restVar->TsType());
2673af6ab5fSopenharmony_ci    }
2683af6ab5fSopenharmony_ci
2693af6ab5fSopenharmony_ci    Out(")");
2703af6ab5fSopenharmony_ci
2713af6ab5fSopenharmony_ci    GenFunctionBody(methodDef, sig, isConstructor, isSetter);
2723af6ab5fSopenharmony_ci}
2733af6ab5fSopenharmony_ci
2743af6ab5fSopenharmony_civoid TSDeclGen::GenEnumType(const checker::ETSIntEnumType *enumType)
2753af6ab5fSopenharmony_ci{
2763af6ab5fSopenharmony_ci    for (auto *member : enumType->GetMembers()) {
2773af6ab5fSopenharmony_ci        Out(INDENT);
2783af6ab5fSopenharmony_ci        if (!member->IsTSEnumMember()) {
2793af6ab5fSopenharmony_ci            ThrowError("Member of enum not of type TSEnumMember", member->Start());
2803af6ab5fSopenharmony_ci        }
2813af6ab5fSopenharmony_ci
2823af6ab5fSopenharmony_ci        const auto *enumMember = member->AsTSEnumMember();
2833af6ab5fSopenharmony_ci        Out(GetKeyIdent(enumMember->Key())->Name().Mutf8());
2843af6ab5fSopenharmony_ci        const auto *init = enumMember->Init();
2853af6ab5fSopenharmony_ci        if (init != nullptr) {
2863af6ab5fSopenharmony_ci            Out(" = ");
2873af6ab5fSopenharmony_ci
2883af6ab5fSopenharmony_ci            if (!init->IsLiteral()) {
2893af6ab5fSopenharmony_ci                ThrowError("Only literal enum initializers are supported", member->Start());
2903af6ab5fSopenharmony_ci            }
2913af6ab5fSopenharmony_ci
2923af6ab5fSopenharmony_ci            GenLiteral(init->AsLiteral());
2933af6ab5fSopenharmony_ci        }
2943af6ab5fSopenharmony_ci
2953af6ab5fSopenharmony_ci        Out(",");
2963af6ab5fSopenharmony_ci        OutEndl();
2973af6ab5fSopenharmony_ci    }
2983af6ab5fSopenharmony_ci}
2993af6ab5fSopenharmony_ci
3003af6ab5fSopenharmony_civoid TSDeclGen::GenUnionType(const checker::ETSUnionType *unionType)
3013af6ab5fSopenharmony_ci{
3023af6ab5fSopenharmony_ci    GenSeparated(
3033af6ab5fSopenharmony_ci        unionType->ConstituentTypes(), [this](checker::Type *arg) { GenType(arg); }, " | ");
3043af6ab5fSopenharmony_ci}
3053af6ab5fSopenharmony_ci
3063af6ab5fSopenharmony_civoid TSDeclGen::GenObjectType(const checker::ETSObjectType *objectType)
3073af6ab5fSopenharmony_ci{
3083af6ab5fSopenharmony_ci    if (objectType->IsETSStringType()) {
3093af6ab5fSopenharmony_ci        Out("string");
3103af6ab5fSopenharmony_ci        return;
3113af6ab5fSopenharmony_ci    }
3123af6ab5fSopenharmony_ci    if (objectType->HasObjectFlag(checker::ETSObjectFlags::UNBOXABLE_TYPE)) {
3133af6ab5fSopenharmony_ci        Out("number");  // NOTE(ivagin): create precise builtin type
3143af6ab5fSopenharmony_ci        return;
3153af6ab5fSopenharmony_ci    }
3163af6ab5fSopenharmony_ci    if (objectType->HasObjectFlag(checker::ETSObjectFlags::FUNCTIONAL)) {
3173af6ab5fSopenharmony_ci        const auto *invoke = objectType->GetOwnProperty<checker::PropertyType::INSTANCE_METHOD>(
3183af6ab5fSopenharmony_ci            checker::FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME);
3193af6ab5fSopenharmony_ci        ASSERT(invoke && invoke->TsType() && invoke->TsType()->IsETSFunctionType());
3203af6ab5fSopenharmony_ci        GenType(invoke->TsType());
3213af6ab5fSopenharmony_ci        return;
3223af6ab5fSopenharmony_ci    }
3233af6ab5fSopenharmony_ci    if (objectType->HasObjectFlag(checker::ETSObjectFlags::DYNAMIC)) {
3243af6ab5fSopenharmony_ci        Out("any");
3253af6ab5fSopenharmony_ci        return;
3263af6ab5fSopenharmony_ci    }
3273af6ab5fSopenharmony_ci
3283af6ab5fSopenharmony_ci    auto typeName = objectType->Name();
3293af6ab5fSopenharmony_ci    if (typeName.Empty()) {
3303af6ab5fSopenharmony_ci        Warning("Object type name is empty");
3313af6ab5fSopenharmony_ci        Out("any");
3323af6ab5fSopenharmony_ci    } else {
3333af6ab5fSopenharmony_ci        Out(typeName);
3343af6ab5fSopenharmony_ci    }
3353af6ab5fSopenharmony_ci
3363af6ab5fSopenharmony_ci    const auto &typeArgs = objectType->TypeArguments();
3373af6ab5fSopenharmony_ci    if (!typeArgs.empty()) {
3383af6ab5fSopenharmony_ci        Out("<");
3393af6ab5fSopenharmony_ci        GenSeparated(typeArgs, [this](checker::Type *arg) { GenType(arg); });
3403af6ab5fSopenharmony_ci        Out(">");
3413af6ab5fSopenharmony_ci    }
3423af6ab5fSopenharmony_ci}
3433af6ab5fSopenharmony_ci
3443af6ab5fSopenharmony_civoid TSDeclGen::GenTypeParameters(const ir::TSTypeParameterDeclaration *typeParams)
3453af6ab5fSopenharmony_ci{
3463af6ab5fSopenharmony_ci    if (typeParams != nullptr) {
3473af6ab5fSopenharmony_ci        Out("<");
3483af6ab5fSopenharmony_ci        GenSeparated(typeParams->Params(), [this](ir::TSTypeParameter *param) {
3493af6ab5fSopenharmony_ci            Out(param->Name()->Name());
3503af6ab5fSopenharmony_ci            auto *constraint = param->Constraint();
3513af6ab5fSopenharmony_ci            if (constraint != nullptr) {
3523af6ab5fSopenharmony_ci                Out(" extends ");
3533af6ab5fSopenharmony_ci                GenType(constraint->GetType(checker_));
3543af6ab5fSopenharmony_ci            }
3553af6ab5fSopenharmony_ci        });
3563af6ab5fSopenharmony_ci        Out(">");
3573af6ab5fSopenharmony_ci    }
3583af6ab5fSopenharmony_ci}
3593af6ab5fSopenharmony_ci
3603af6ab5fSopenharmony_civoid TSDeclGen::GenExport(const ir::Identifier *symbol)
3613af6ab5fSopenharmony_ci{
3623af6ab5fSopenharmony_ci    const auto symbolName = symbol->Name().Mutf8();
3633af6ab5fSopenharmony_ci    Out("export {", symbolName, "};");
3643af6ab5fSopenharmony_ci    OutEndl();
3653af6ab5fSopenharmony_ci    if (!symbol->Parent()->IsTSTypeAliasDeclaration() && !symbol->Parent()->IsTSInterfaceDeclaration()) {
3663af6ab5fSopenharmony_ci        Out("exports.", symbolName, " = ", symbolName, ";");
3673af6ab5fSopenharmony_ci    }
3683af6ab5fSopenharmony_ci    OutEndl();
3693af6ab5fSopenharmony_ci}
3703af6ab5fSopenharmony_ci
3713af6ab5fSopenharmony_civoid TSDeclGen::GenExport(const ir::Identifier *symbol, const std::string &alias)
3723af6ab5fSopenharmony_ci{
3733af6ab5fSopenharmony_ci    const auto symbolName = symbol->Name().Mutf8();
3743af6ab5fSopenharmony_ci    Out("export {", symbolName, " as ", alias, "};");
3753af6ab5fSopenharmony_ci    OutEndl();
3763af6ab5fSopenharmony_ci    if (!symbol->Parent()->IsTSTypeAliasDeclaration() && !symbol->Parent()->IsTSInterfaceDeclaration()) {
3773af6ab5fSopenharmony_ci        Out("exports.", alias, " = ", symbolName, ";");
3783af6ab5fSopenharmony_ci    }
3793af6ab5fSopenharmony_ci    OutEndl();
3803af6ab5fSopenharmony_ci}
3813af6ab5fSopenharmony_ci
3823af6ab5fSopenharmony_civoid TSDeclGen::GenDefaultExport(const ir::Identifier *symbol)
3833af6ab5fSopenharmony_ci{
3843af6ab5fSopenharmony_ci    const auto symbolName = symbol->Name().Mutf8();
3853af6ab5fSopenharmony_ci    Out("export default ", symbolName, ";");
3863af6ab5fSopenharmony_ci    OutEndl();
3873af6ab5fSopenharmony_ci    if (!symbol->Parent()->IsTSTypeAliasDeclaration() && !symbol->Parent()->IsTSInterfaceDeclaration()) {
3883af6ab5fSopenharmony_ci        Out("exports.default = ", symbolName, ";");
3893af6ab5fSopenharmony_ci    }
3903af6ab5fSopenharmony_ci    OutEndl();
3913af6ab5fSopenharmony_ci}
3923af6ab5fSopenharmony_ci
3933af6ab5fSopenharmony_civoid TSDeclGen::ExportIfNeeded(const ir::Identifier *symbol)
3943af6ab5fSopenharmony_ci{
3953af6ab5fSopenharmony_ci    if (symbol->Parent()->IsExported()) {
3963af6ab5fSopenharmony_ci        GenExport(symbol);
3973af6ab5fSopenharmony_ci    }
3983af6ab5fSopenharmony_ci    if (symbol->Parent()->IsExportedType()) {
3993af6ab5fSopenharmony_ci        GenExport(symbol);
4003af6ab5fSopenharmony_ci    }
4013af6ab5fSopenharmony_ci    if (symbol->Parent()->IsDefaultExported()) {
4023af6ab5fSopenharmony_ci        GenDefaultExport(symbol);
4033af6ab5fSopenharmony_ci    }
4043af6ab5fSopenharmony_ci}
4053af6ab5fSopenharmony_ci
4063af6ab5fSopenharmony_citemplate <class T>
4073af6ab5fSopenharmony_civoid TSDeclGen::GenModifier(const T *node)
4083af6ab5fSopenharmony_ci{
4093af6ab5fSopenharmony_ci    if (state_.inInterface) {
4103af6ab5fSopenharmony_ci        return;
4113af6ab5fSopenharmony_ci    }
4123af6ab5fSopenharmony_ci
4133af6ab5fSopenharmony_ci    if (node->IsPrivate()) {
4143af6ab5fSopenharmony_ci        Out("private ");
4153af6ab5fSopenharmony_ci    }
4163af6ab5fSopenharmony_ci    if (node->IsProtected()) {
4173af6ab5fSopenharmony_ci        Out("protected ");
4183af6ab5fSopenharmony_ci    }
4193af6ab5fSopenharmony_ci    if (node->IsPublic()) {
4203af6ab5fSopenharmony_ci        Out("public ");
4213af6ab5fSopenharmony_ci    }
4223af6ab5fSopenharmony_ci    if (node->IsReadonly()) {
4233af6ab5fSopenharmony_ci        Out("readonly ");
4243af6ab5fSopenharmony_ci    }
4253af6ab5fSopenharmony_ci    if (node->IsStatic()) {
4263af6ab5fSopenharmony_ci        Out("static ");
4273af6ab5fSopenharmony_ci    }
4283af6ab5fSopenharmony_ci}
4293af6ab5fSopenharmony_ci
4303af6ab5fSopenharmony_civoid TSDeclGen::GenImportDeclaration(const ir::ETSImportDeclaration *importDeclaration)
4313af6ab5fSopenharmony_ci{
4323af6ab5fSopenharmony_ci    DebugPrint("GenImportDeclaration");
4333af6ab5fSopenharmony_ci    if (importDeclaration->IsPureDynamic()) {
4343af6ab5fSopenharmony_ci        return;
4353af6ab5fSopenharmony_ci    }
4363af6ab5fSopenharmony_ci
4373af6ab5fSopenharmony_ci    const auto &specifiers = importDeclaration->Specifiers();
4383af6ab5fSopenharmony_ci    Out("import { ");
4393af6ab5fSopenharmony_ci    GenSeparated(specifiers, [this, &importDeclaration](ir::AstNode *specifier) {
4403af6ab5fSopenharmony_ci        if (!specifier->IsImportSpecifier()) {
4413af6ab5fSopenharmony_ci            ThrowError("Only import specifiers are supported", importDeclaration->Start());
4423af6ab5fSopenharmony_ci        }
4433af6ab5fSopenharmony_ci
4443af6ab5fSopenharmony_ci        const auto local = specifier->AsImportSpecifier()->Local()->Name();
4453af6ab5fSopenharmony_ci        const auto imported = specifier->AsImportSpecifier()->Imported()->Name();
4463af6ab5fSopenharmony_ci        Out(local);
4473af6ab5fSopenharmony_ci        if (local != imported) {
4483af6ab5fSopenharmony_ci            ThrowError("Imports with local bindings are not supported", importDeclaration->Start());
4493af6ab5fSopenharmony_ci        }
4503af6ab5fSopenharmony_ci    });
4513af6ab5fSopenharmony_ci
4523af6ab5fSopenharmony_ci    auto source = importDeclaration->Source()->Str().Mutf8();
4533af6ab5fSopenharmony_ci    Out(" } from \"", source, "\";");
4543af6ab5fSopenharmony_ci    OutEndl(2U);
4553af6ab5fSopenharmony_ci}
4563af6ab5fSopenharmony_ci
4573af6ab5fSopenharmony_civoid TSDeclGen::GenTypeAliasDeclaration(const ir::TSTypeAliasDeclaration *typeAlias)
4583af6ab5fSopenharmony_ci{
4593af6ab5fSopenharmony_ci    const auto name = typeAlias->Id()->Name().Mutf8();
4603af6ab5fSopenharmony_ci    DebugPrint("GenTypeAliasDeclaration: " + name);
4613af6ab5fSopenharmony_ci    const auto *aliasedType = typeAlias->TypeAnnotation()->GetType(checker_);
4623af6ab5fSopenharmony_ci    Out("type ", name, " = ");
4633af6ab5fSopenharmony_ci    GenType(aliasedType);
4643af6ab5fSopenharmony_ci    Out(";");
4653af6ab5fSopenharmony_ci    OutEndl();
4663af6ab5fSopenharmony_ci
4673af6ab5fSopenharmony_ci    ExportIfNeeded(typeAlias->Id());
4683af6ab5fSopenharmony_ci    OutEndl();
4693af6ab5fSopenharmony_ci}
4703af6ab5fSopenharmony_ci
4713af6ab5fSopenharmony_civoid TSDeclGen::GenEnumDeclaration(const ir::TSEnumDeclaration *enumDecl)
4723af6ab5fSopenharmony_ci{
4733af6ab5fSopenharmony_ci    const auto enumIdent = GetKeyIdent(enumDecl->Key());
4743af6ab5fSopenharmony_ci    const auto enumName = enumIdent->Name().Mutf8();
4753af6ab5fSopenharmony_ci    DebugPrint("GenEnumDeclaration: " + enumName);
4763af6ab5fSopenharmony_ci    Out("enum ", enumName, " {");
4773af6ab5fSopenharmony_ci    OutEndl();
4783af6ab5fSopenharmony_ci
4793af6ab5fSopenharmony_ci    ASSERT(enumDecl->TsType()->IsETSIntEnumType());
4803af6ab5fSopenharmony_ci    GenEnumType(enumDecl->TsType()->AsETSIntEnumType());
4813af6ab5fSopenharmony_ci
4823af6ab5fSopenharmony_ci    Out("}");
4833af6ab5fSopenharmony_ci    OutEndl();
4843af6ab5fSopenharmony_ci
4853af6ab5fSopenharmony_ci    ExportIfNeeded(enumIdent);
4863af6ab5fSopenharmony_ci    OutEndl();
4873af6ab5fSopenharmony_ci}
4883af6ab5fSopenharmony_ci
4893af6ab5fSopenharmony_civoid TSDeclGen::GenInterfaceDeclaration(const ir::TSInterfaceDeclaration *interfaceDecl)
4903af6ab5fSopenharmony_ci{
4913af6ab5fSopenharmony_ci    state_.inInterface = true;
4923af6ab5fSopenharmony_ci    const auto interfaceName = interfaceDecl->Id()->Name().Mutf8();
4933af6ab5fSopenharmony_ci    DebugPrint("GenInterfaceDeclaration: " + interfaceName);
4943af6ab5fSopenharmony_ci    Out("interface ", interfaceName);
4953af6ab5fSopenharmony_ci
4963af6ab5fSopenharmony_ci    GenTypeParameters(interfaceDecl->TypeParams());
4973af6ab5fSopenharmony_ci
4983af6ab5fSopenharmony_ci    Out(" {");
4993af6ab5fSopenharmony_ci    OutEndl();
5003af6ab5fSopenharmony_ci
5013af6ab5fSopenharmony_ci    for (auto *prop : interfaceDecl->Body()->Body()) {
5023af6ab5fSopenharmony_ci        if (prop->IsMethodDefinition()) {
5033af6ab5fSopenharmony_ci            GenMethodDeclaration(prop->AsMethodDefinition());
5043af6ab5fSopenharmony_ci            for (const auto *methodDef : prop->AsMethodDefinition()->Overloads()) {
5053af6ab5fSopenharmony_ci                GenMethodDeclaration(methodDef);
5063af6ab5fSopenharmony_ci            }
5073af6ab5fSopenharmony_ci        }
5083af6ab5fSopenharmony_ci        if (prop->IsClassProperty()) {
5093af6ab5fSopenharmony_ci            GenPropDeclaration(prop->AsClassProperty());
5103af6ab5fSopenharmony_ci        }
5113af6ab5fSopenharmony_ci    }
5123af6ab5fSopenharmony_ci
5133af6ab5fSopenharmony_ci    Out("}");
5143af6ab5fSopenharmony_ci    OutEndl();
5153af6ab5fSopenharmony_ci
5163af6ab5fSopenharmony_ci    ExportIfNeeded(interfaceDecl->Id());
5173af6ab5fSopenharmony_ci    OutEndl();
5183af6ab5fSopenharmony_ci}
5193af6ab5fSopenharmony_ci
5203af6ab5fSopenharmony_civoid TSDeclGen::GenClassDeclaration(const ir::ClassDeclaration *classDecl)
5213af6ab5fSopenharmony_ci{
5223af6ab5fSopenharmony_ci    const auto *classDef = classDecl->Definition();
5233af6ab5fSopenharmony_ci    std::string classDescriptor = "L" + classDef->InternalName().Mutf8() + ";";
5243af6ab5fSopenharmony_ci    std::replace(classDescriptor.begin(), classDescriptor.end(), '.', '/');
5253af6ab5fSopenharmony_ci    state_.currentClassDescriptor = classDescriptor;
5263af6ab5fSopenharmony_ci    const auto className = classDef->Ident()->Name().Mutf8();
5273af6ab5fSopenharmony_ci    state_.inGlobalClass = classDef->IsGlobal();
5283af6ab5fSopenharmony_ci
5293af6ab5fSopenharmony_ci    DebugPrint("GenClassDeclaration: " + className);
5303af6ab5fSopenharmony_ci
5313af6ab5fSopenharmony_ci    if (className == compiler::Signatures::DYNAMIC_MODULE_CLASS || className == compiler::Signatures::JSNEW_CLASS ||
5323af6ab5fSopenharmony_ci        className == compiler::Signatures::JSCALL_CLASS || (className.find("$partial") != std::string::npos)) {
5333af6ab5fSopenharmony_ci        return;
5343af6ab5fSopenharmony_ci    }
5353af6ab5fSopenharmony_ci
5363af6ab5fSopenharmony_ci    if (!state_.inGlobalClass) {
5373af6ab5fSopenharmony_ci        Out("class ", className);
5383af6ab5fSopenharmony_ci        GenTypeParameters(classDef->TypeParams());
5393af6ab5fSopenharmony_ci
5403af6ab5fSopenharmony_ci        const auto *super = classDef->Super();
5413af6ab5fSopenharmony_ci        state_.super = super;
5423af6ab5fSopenharmony_ci        if (super != nullptr) {
5433af6ab5fSopenharmony_ci            Out(" extends ");
5443af6ab5fSopenharmony_ci            GenType(super->TsType());
5453af6ab5fSopenharmony_ci        }
5463af6ab5fSopenharmony_ci
5473af6ab5fSopenharmony_ci        const auto &interfaces = classDef->TsType()->AsETSObjectType()->Interfaces();
5483af6ab5fSopenharmony_ci        if (!interfaces.empty()) {
5493af6ab5fSopenharmony_ci            Out(" implements ");
5503af6ab5fSopenharmony_ci            ASSERT(classDef->TsType()->IsETSObjectType());
5513af6ab5fSopenharmony_ci            GenSeparated(interfaces, [this](checker::ETSObjectType *interface) { GenType(interface); });
5523af6ab5fSopenharmony_ci        }
5533af6ab5fSopenharmony_ci
5543af6ab5fSopenharmony_ci        Out(" {");
5553af6ab5fSopenharmony_ci        OutEndl();
5563af6ab5fSopenharmony_ci    }
5573af6ab5fSopenharmony_ci
5583af6ab5fSopenharmony_ci    for (const auto *prop : classDef->Body()) {
5593af6ab5fSopenharmony_ci        if (prop->IsMethodDefinition()) {
5603af6ab5fSopenharmony_ci            GenMethodDeclaration(prop->AsMethodDefinition());
5613af6ab5fSopenharmony_ci            for (const auto *methodDef : prop->AsMethodDefinition()->Overloads()) {
5623af6ab5fSopenharmony_ci                GenMethodDeclaration(methodDef);
5633af6ab5fSopenharmony_ci            }
5643af6ab5fSopenharmony_ci        } else if (prop->IsClassProperty()) {
5653af6ab5fSopenharmony_ci            GenPropDeclaration(prop->AsClassProperty());
5663af6ab5fSopenharmony_ci        }
5673af6ab5fSopenharmony_ci    }
5683af6ab5fSopenharmony_ci
5693af6ab5fSopenharmony_ci    if (!state_.inGlobalClass) {
5703af6ab5fSopenharmony_ci        Out("};");
5713af6ab5fSopenharmony_ci        OutEndl();
5723af6ab5fSopenharmony_ci        Out("(", className, " as any) = (globalThis as any).Panda.getClass('", state_.currentClassDescriptor, "');");
5733af6ab5fSopenharmony_ci        OutEndl();
5743af6ab5fSopenharmony_ci        ExportIfNeeded(classDef->Ident());
5753af6ab5fSopenharmony_ci        OutEndl();
5763af6ab5fSopenharmony_ci    }
5773af6ab5fSopenharmony_ci}
5783af6ab5fSopenharmony_ci
5793af6ab5fSopenharmony_civoid TSDeclGen::GenMethodDeclaration(const ir::MethodDefinition *methodDef)
5803af6ab5fSopenharmony_ci{
5813af6ab5fSopenharmony_ci    const auto methodIdent = GetKeyIdent(methodDef->Key());
5823af6ab5fSopenharmony_ci    const auto methodName = methodIdent->Name().Mutf8();
5833af6ab5fSopenharmony_ci    if (methodName.find('#') != std::string::npos) {
5843af6ab5fSopenharmony_ci        return;
5853af6ab5fSopenharmony_ci    }
5863af6ab5fSopenharmony_ci
5873af6ab5fSopenharmony_ci    if (state_.inGlobalClass) {
5883af6ab5fSopenharmony_ci        Out("function ");
5893af6ab5fSopenharmony_ci    } else {
5903af6ab5fSopenharmony_ci        Out(INDENT);
5913af6ab5fSopenharmony_ci        GenModifier(methodDef);
5923af6ab5fSopenharmony_ci    }
5933af6ab5fSopenharmony_ci
5943af6ab5fSopenharmony_ci    if (methodDef->Kind() == ir::MethodDefinitionKind::GET) {
5953af6ab5fSopenharmony_ci        Out("get ");
5963af6ab5fSopenharmony_ci    }
5973af6ab5fSopenharmony_ci    if (methodDef->Kind() == ir::MethodDefinitionKind::SET) {
5983af6ab5fSopenharmony_ci        Out("set ");
5993af6ab5fSopenharmony_ci    }
6003af6ab5fSopenharmony_ci
6013af6ab5fSopenharmony_ci    DebugPrint("  GenMethodDeclaration: " + methodName);
6023af6ab5fSopenharmony_ci    Out(methodName);
6033af6ab5fSopenharmony_ci
6043af6ab5fSopenharmony_ci    if (methodDef->TsType() == nullptr) {
6053af6ab5fSopenharmony_ci        Warning("Untyped method encountered: " + methodName);
6063af6ab5fSopenharmony_ci        Out(": any");
6073af6ab5fSopenharmony_ci    } else {
6083af6ab5fSopenharmony_ci        GenFunctionType(methodDef->TsType()->AsETSFunctionType(), methodDef);
6093af6ab5fSopenharmony_ci    }
6103af6ab5fSopenharmony_ci
6113af6ab5fSopenharmony_ci    Out(";");
6123af6ab5fSopenharmony_ci    OutEndl();
6133af6ab5fSopenharmony_ci
6143af6ab5fSopenharmony_ci    if (state_.inGlobalClass) {
6153af6ab5fSopenharmony_ci        Out("(", methodName, " as any) = ETSGLOBAL.", methodName, ";");
6163af6ab5fSopenharmony_ci        OutEndl();
6173af6ab5fSopenharmony_ci        ExportIfNeeded(methodIdent);
6183af6ab5fSopenharmony_ci        if (methodName == compiler::Signatures::INIT_METHOD) {
6193af6ab5fSopenharmony_ci            Out(methodName, "();");
6203af6ab5fSopenharmony_ci        }
6213af6ab5fSopenharmony_ci        OutEndl(2U);
6223af6ab5fSopenharmony_ci    }
6233af6ab5fSopenharmony_ci}
6243af6ab5fSopenharmony_ci
6253af6ab5fSopenharmony_civoid TSDeclGen::GenPropDeclaration(const ir::ClassProperty *classProp)
6263af6ab5fSopenharmony_ci{
6273af6ab5fSopenharmony_ci    if (state_.inGlobalClass) {
6283af6ab5fSopenharmony_ci        GenGlobalVarDeclaration(classProp);
6293af6ab5fSopenharmony_ci        return;
6303af6ab5fSopenharmony_ci    }
6313af6ab5fSopenharmony_ci
6323af6ab5fSopenharmony_ci    const auto propName = GetKeyIdent(classProp->Key())->Name().Mutf8();
6333af6ab5fSopenharmony_ci    DebugPrint("  GenPropDeclaration: " + propName);
6343af6ab5fSopenharmony_ci
6353af6ab5fSopenharmony_ci    Out(INDENT);
6363af6ab5fSopenharmony_ci    GenModifier(classProp);
6373af6ab5fSopenharmony_ci    Out(propName);
6383af6ab5fSopenharmony_ci
6393af6ab5fSopenharmony_ci    Out(": ");
6403af6ab5fSopenharmony_ci    GenType(classProp->TsType());
6413af6ab5fSopenharmony_ci    if (!state_.inInterface) {
6423af6ab5fSopenharmony_ci        Out(" = {} as any");
6433af6ab5fSopenharmony_ci    }
6443af6ab5fSopenharmony_ci    Out(";");
6453af6ab5fSopenharmony_ci    OutEndl();
6463af6ab5fSopenharmony_ci}
6473af6ab5fSopenharmony_ci
6483af6ab5fSopenharmony_civoid TSDeclGen::GenGlobalVarDeclaration(const ir::ClassProperty *globalVar)
6493af6ab5fSopenharmony_ci{
6503af6ab5fSopenharmony_ci    if (!globalVar->IsExported() && !globalVar->IsDefaultExported()) {
6513af6ab5fSopenharmony_ci        return;
6523af6ab5fSopenharmony_ci    }
6533af6ab5fSopenharmony_ci
6543af6ab5fSopenharmony_ci    const auto symbol = GetKeyIdent(globalVar->Key());
6553af6ab5fSopenharmony_ci    const auto varName = symbol->Name().Mutf8();
6563af6ab5fSopenharmony_ci    DebugPrint("GenGlobalVarDeclaration: " + varName);
6573af6ab5fSopenharmony_ci    if (!globalVar->IsConst()) {
6583af6ab5fSopenharmony_ci        Warning("Not constant global variables are not supported, variable \"" + varName + "\" was skipped");
6593af6ab5fSopenharmony_ci        return;
6603af6ab5fSopenharmony_ci    }
6613af6ab5fSopenharmony_ci
6623af6ab5fSopenharmony_ci    Out("const ", varName, ": ");
6633af6ab5fSopenharmony_ci    GenType(globalVar->TsType());
6643af6ab5fSopenharmony_ci    Out(" = ETSGLOBAL.", varName, ';');
6653af6ab5fSopenharmony_ci    OutEndl();
6663af6ab5fSopenharmony_ci
6673af6ab5fSopenharmony_ci    GenExport(symbol);
6683af6ab5fSopenharmony_ci    OutEndl();
6693af6ab5fSopenharmony_ci}
6703af6ab5fSopenharmony_ci
6713af6ab5fSopenharmony_cibool GenerateTsDeclarations(checker::ETSChecker *checker, const ark::es2panda::parser::Program *program,
6723af6ab5fSopenharmony_ci                            const std::string &outPath)
6733af6ab5fSopenharmony_ci{
6743af6ab5fSopenharmony_ci    TSDeclGen declBuilder(checker, program);
6753af6ab5fSopenharmony_ci    declBuilder.Generate();
6763af6ab5fSopenharmony_ci
6773af6ab5fSopenharmony_ci    std::ofstream outStream(outPath);
6783af6ab5fSopenharmony_ci    if (outStream.fail()) {
6793af6ab5fSopenharmony_ci        std::cerr << "Failed to open file: " << outPath << std::endl;
6803af6ab5fSopenharmony_ci        return false;
6813af6ab5fSopenharmony_ci    }
6823af6ab5fSopenharmony_ci
6833af6ab5fSopenharmony_ci    outStream << declBuilder.Output().str();
6843af6ab5fSopenharmony_ci    outStream.close();
6853af6ab5fSopenharmony_ci
6863af6ab5fSopenharmony_ci    return true;
6873af6ab5fSopenharmony_ci}
6883af6ab5fSopenharmony_ci}  // namespace ark::es2panda::declgen_ets2ts
689