From 34de0d2292fe6ef89b9a6b93f314d2e5ddb04362 Mon Sep 17 00:00:00 2001 From: dongchao Date: Wed, 25 Jun 2025 09:43:36 +0800 Subject: [PATCH] Fix restparam scene in declgen_ets2ts Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICHL3R Signed-off-by: dongchao Change-Id: I58c707e3a95e8438a763fbeceeeccaf4a17573df --- ets2panda/declgen_ets2ts/declgenEts2Ts.cpp | 232 ++++++++++++++------- ets2panda/declgen_ets2ts/declgenEts2Ts.h | 20 +- ets2panda/parser/ETSparserClasses.cpp | 1 + 3 files changed, 180 insertions(+), 73 deletions(-) diff --git a/ets2panda/declgen_ets2ts/declgenEts2Ts.cpp b/ets2panda/declgen_ets2ts/declgenEts2Ts.cpp index bc6861126e0..b0d34411389 100644 --- a/ets2panda/declgen_ets2ts/declgenEts2Ts.cpp +++ b/ets2panda/declgen_ets2ts/declgenEts2Ts.cpp @@ -1030,13 +1030,13 @@ void TSDeclGen::GenImportDeclaration(const ir::ETSImportDeclaration *importDecla auto source = importDeclaration->Source()->Str().Mutf8(); source = RemoveModuleExtensionName(source); const auto specifierFirst = specifiers[0]; - const auto typeStr = importDeclaration->IsTypeKind() ? "type " : ""; + bool isTypeKind = importDeclaration->IsTypeKind(); if (specifierFirst->IsImportNamespaceSpecifier()) { GenNamespaceImport(specifierFirst, source); } else if (specifierFirst->IsImportDefaultSpecifier()) { - GenDefaultImport(specifierFirst, source, typeStr); + GenDefaultImport(specifierFirst, source, isTypeKind); } else if (specifierFirst->IsImportSpecifier()) { - GenNamedImports(importDeclaration, specifiers, source, typeStr); + GenNamedImports(importDeclaration, specifiers, isTypeKind); } } @@ -1052,45 +1052,78 @@ void TSDeclGen::GenNamespaceImport(const ir::AstNode *specifier, const std::stri OutEndlDts(); } -void TSDeclGen::GenDefaultImport(const ir::AstNode *specifier, const std::string &source, const std::string &typeStr) +void TSDeclGen::GenDefaultImport(const ir::AstNode *specifier, const std::string &source, bool isTypeKind) { const auto local = specifier->AsImportDefaultSpecifier()->Local()->Name(); - OutTs("import ", typeStr, local, " from \"", source, "\";"); + if (specifier->AsImportDefaultSpecifier()->Local()->Variable() && + specifier->AsImportDefaultSpecifier()->Local()->Variable()->Declaration() && + specifier->AsImportDefaultSpecifier()->Local()->Variable()->Declaration()->Node() && + specifier->AsImportDefaultSpecifier()->Local()->Variable()->Declaration()->Node()->IsTSInterfaceDeclaration()) { + OutTs("import type ", local, " from \"", source, "\";"); + } else { + OutTs(isTypeKind ? "import type " : "import ", local, " from \"", source, "\";"); + } OutEndlTs(); if (importSet_.find(local.Mutf8()) == importSet_.end()) { return; } - OutDts("import ", typeStr, local, " from \"", source, "\";"); + OutDts(isTypeKind ? "import type " : "import ", local, " from \"", source, "\";"); OutEndlDts(); } void TSDeclGen::GenNamedImports(const ir::ETSImportDeclaration *importDeclaration, - const ArenaVector &specifiers, const std::string &source, - const std::string &typeStr) + const ArenaVector &specifiers, bool isTypeKind) +{ + if (specifiers.empty()) { + return; + } + std::vector interfaceSpecifiers; + std::vector normalSpecifiers; + SeparateInterfaceSpecifiers(specifiers, interfaceSpecifiers, normalSpecifiers); + + GenTsImportStatement(interfaceSpecifiers, importDeclaration, true); + GenTsImportStatement(normalSpecifiers, importDeclaration); + + auto importSpecifiers = FilterValidImportSpecifiers(specifiers); + GenDtsImportStatement(importSpecifiers, importDeclaration, isTypeKind); +} + +void TSDeclGen::GenTsImportStatement(std::vector &specifiers, + const ir::ETSImportDeclaration *importDeclaration, bool isInterface) { if (specifiers.empty()) { return; } - OutTs("import ", typeStr, "{ "); + + auto source = importDeclaration->Source()->Str().Mutf8(); + source = RemoveModuleExtensionName(source); + OutTs(isInterface ? "import type" : "import", " { "); + GenSeparated( specifiers, - [this, &importDeclaration](ir::AstNode *specifier) { - GenSingleNamedImport(specifier, importDeclaration, true); - }, + [this, importDeclaration](ir::AstNode *specifier) { GenSingleNamedImport(specifier, importDeclaration, true); }, ", ", true, false); - OutTs(" } from \"", source, "\";"); - OutEndlTs(); - auto importSpecifiers = FilterValidImportSpecifiers(specifiers); - if (importSpecifiers.empty()) { + + OutTs(" } from \"", source, "\";\n"); +} + +void TSDeclGen::GenDtsImportStatement(std::vector &specifiers, + const ir::ETSImportDeclaration *importDeclaration, bool isTypeKind) +{ + if (specifiers.empty()) { return; } - OutDts("import ", typeStr, "{ "); + + auto source = importDeclaration->Source()->Str().Mutf8(); + source = RemoveModuleExtensionName(source); + OutDts(isTypeKind ? "import type" : "import", " { "); + GenSeparated( - importSpecifiers, - [this, &importDeclaration](ir::AstNode *specifier) { GenSingleNamedImport(specifier, importDeclaration); }, + specifiers, + [this, importDeclaration](ir::AstNode *specifier) { GenSingleNamedImport(specifier, importDeclaration); }, ", "); - OutDts(" } from \"", source, "\";"); - OutEndlDts(); + + OutDts(" } from \"", source, "\";\n"); } void TSDeclGen::GenSingleNamedImport(ir::AstNode *specifier, const ir::ETSImportDeclaration *importDeclaration, @@ -1131,48 +1164,115 @@ void TSDeclGen::GenReExportDeclaration(const ir::ETSReExportDeclaration *reExpor return; } const auto &specifiers = importDeclaration->Specifiers(); - if (specifiers.size() == 1 && specifiers[0]->IsImportNamespaceSpecifier()) { - const auto local = specifiers[0]->AsImportNamespaceSpecifier()->Local()->Name(); + + if (specifiers.size() == 1 && GenNamespaceReExportDeclaration(specifiers[0], importDeclaration)) { + return; + } + + bool isTypeKind = reExportDeclaration->IsExportedType(); + std::vector interfaceSpecifiers; + std::vector normalSpecifiers; + SeparateInterfaceSpecifiers(specifiers, interfaceSpecifiers, normalSpecifiers); + + GenDtsReExportStatement(specifiers, importDeclaration, isTypeKind); + + GenTsReExportStatement(interfaceSpecifiers, importDeclaration, true); + GenTsReExportStatement(normalSpecifiers, importDeclaration); +} + +bool TSDeclGen::GenNamespaceReExportDeclaration(const ir::AstNode *specifier, + const ir::ETSImportDeclaration *importDeclaration) +{ + if (specifier->IsImportNamespaceSpecifier()) { + const auto local = specifier->AsImportNamespaceSpecifier()->Local()->Name(); if (local.Empty()) { - OutDts("export * from \"", importDeclaration->Source()->Str().Mutf8(), "\";"); - OutEndlDts(); - OutTs("export * from \"", importDeclaration->Source()->Str().Mutf8(), "\";"); - OutEndlTs(); - return; + auto source = importDeclaration->Source()->Str().Mutf8(); + source = RemoveModuleExtensionName(source); + OutDts("export * from \"", source, "\";\n"); + OutTs("export * from \"", source, "\";\n"); + return true; + } + } + return false; +} + +void TSDeclGen::SeparateInterfaceSpecifiers(const ArenaVector &specifiers, + std::vector &interfaceSpecifiers, + std::vector &normalSpecifiers) +{ + for (auto *specifier : specifiers) { + if (!specifier->IsImportSpecifier()) { + continue; + } + if (specifier->AsImportSpecifier()->Imported()->Variable() && + specifier->AsImportSpecifier()->Imported()->Variable()->Declaration() && + specifier->AsImportSpecifier()->Imported()->Variable()->Declaration()->Node() && + specifier->AsImportSpecifier()->Imported()->Variable()->Declaration()->Node()->IsTSInterfaceDeclaration()) { + interfaceSpecifiers.push_back(specifier); + } else { + normalSpecifiers.push_back(specifier); + } + } +} + +void TSDeclGen::GenSingleNamedReExport(ir::AstNode *specifier, const ir::ETSImportDeclaration *importDeclaration, + bool isGlueCode) +{ + if (specifier->IsImportSpecifier()) { + const auto local = specifier->AsImportSpecifier()->Local()->Name().Mutf8(); + const auto imported = specifier->AsImportSpecifier()->Imported()->Name().Mutf8(); + importSet_.insert(local); + if (local != imported) { + isGlueCode ? OutTs(imported, " as ", local) : OutDts(imported, " as ", local); + } else { + isGlueCode ? OutTs(local) : OutDts(local); } + } else if (specifier->IsImportNamespaceSpecifier()) { + const auto local = specifier->AsImportNamespaceSpecifier()->Local()->Name().Mutf8(); + importSet_.insert(local); + isGlueCode ? OutTs(local) : OutDts(local); + } else { + LogError(diagnostic::IMPORT_SPECIFIERS_SUPPORT, {}, importDeclaration->Start()); + } +} + +void TSDeclGen::GenDtsReExportStatement(const ArenaVector &specifiers, + const ir::ETSImportDeclaration *importDeclaration, bool isTypeKind) +{ + if (specifiers.empty()) { + return; } - OutDts("export { "); - OutTs("export { "); + + auto source = importDeclaration->Source()->Str().Mutf8(); + source = RemoveModuleExtensionName(source); + OutDts(isTypeKind ? "export type" : "export", " { "); + GenSeparated( specifiers, - [this, &importDeclaration](ir::AstNode *specifier) { - if (specifier->IsImportSpecifier()) { - const auto local = specifier->AsImportSpecifier()->Local()->Name().Mutf8(); - const auto imported = specifier->AsImportSpecifier()->Imported()->Name().Mutf8(); - importSet_.insert(local); - if (local != imported) { - OutDts(imported, " as ", local); - OutTs(imported, " as ", local); - } else { - OutDts(local); - OutTs(local); - } - } else if (specifier->IsImportNamespaceSpecifier()) { - const auto local = specifier->AsImportNamespaceSpecifier()->Local()->Name(); - importSet_.insert(local.Mutf8()); - OutDts(local); - OutTs(local); - } else { - LogError(diagnostic::IMPORT_SPECIFIERS_SUPPORT, {}, importDeclaration->Start()); - } - }, - ", ", true); + [this, importDeclaration](ir::AstNode *specifier) { GenSingleNamedReExport(specifier, importDeclaration); }, + ", "); + OutDts(" } from \"", source, "\";\n"); +} + +void TSDeclGen::GenTsReExportStatement(const std::vector &specifiers, + const ir::ETSImportDeclaration *importDeclaration, bool isInterface) +{ + if (specifiers.empty()) { + return; + } auto source = importDeclaration->Source()->Str().Mutf8(); - OutDts(" } from \"", source, "\";"); - OutEndlDts(); - OutTs(" } from \"", source, "\";"); - OutEndlTs(); + source = RemoveModuleExtensionName(source); + OutTs(isInterface ? "export type" : "export", " { "); + + GenSeparated( + specifiers, + [this, importDeclaration](ir::AstNode *specifier) { + GenSingleNamedReExport(specifier, importDeclaration, true); + }, + ", ", true, false); + + OutTs(" } from \"", source, "\";\n"); } std::string TSDeclGen::ReplaceETSGLOBAL(const std::string &typeName) @@ -1362,10 +1462,12 @@ void TSDeclGen::ProcessETSFunctionType(const ir::ETSFunctionType *etsFunction) bool inUnionBody = !state_.inUnionBodyStack.empty() && state_.inUnionBodyStack.top(); OutDts(inUnionBody ? "((" : "("); GenSeparated(etsFunction->Params(), [this](ir::Expression *param) { - const auto paramName = param->AsETSParameterExpression()->Name(); - OutDts(paramName.Is("=t") ? "this" : paramName, ": "); - ProcessTypeAnnotationType(param->AsETSParameterExpression()->TypeAnnotation(), - param->AsETSParameterExpression()->TypeAnnotation()->TsType()); + const auto paramExpr = param->AsETSParameterExpression(); + const auto paramName = paramExpr->Name(); + const bool isRestParam = paramExpr->IsRestParameter(); + const bool isOptional = paramExpr->IsOptional(); + OutDts(isRestParam ? "..." : "", paramName.Is("=t") ? "this" : paramName, isOptional ? "?: " : ": "); + ProcessTypeAnnotationType(paramExpr->TypeAnnotation(), paramExpr->TypeAnnotation()->TsType()); }); OutDts(") => "); ProcessTypeAnnotationType(etsFunction->ReturnType(), etsFunction->ReturnType()->TsType()); @@ -1401,16 +1503,6 @@ void TSDeclGen::GenTypeAliasDeclaration(const ir::TSTypeAliasDeclaration *typeAl OutDts("export default ", name, ";"); OutEndlDts(); } - - auto typeName = typeAliasMap_[name]; - const auto classDesc = ReplaceETSGLOBAL(typeName); - OutTs("const ", name, " = (globalThis as any).Panda.getClass('", classDesc, "');"); - OutEndlTs(); - if (state_.inNamespace) { - return; - } - OutTs("export { ", name, " };"); - OutEndlTs(); } void TSDeclGen::GenEnumDeclaration(const ir::ClassProperty *enumMember) diff --git a/ets2panda/declgen_ets2ts/declgenEts2Ts.h b/ets2panda/declgen_ets2ts/declgenEts2Ts.h index efda8673055..850722c6f03 100644 --- a/ets2panda/declgen_ets2ts/declgenEts2Ts.h +++ b/ets2panda/declgen_ets2ts/declgenEts2Ts.h @@ -122,13 +122,27 @@ private: void GenImportDeclaration(const ir::ETSImportDeclaration *importDeclaration); void GenNamespaceImport(const ir::AstNode *specifier, const std::string &source); - void GenDefaultImport(const ir::AstNode *specifier, const std::string &source, const std::string &typeStr); + void GenDefaultImport(const ir::AstNode *specifier, const std::string &source, bool isTypeKind = false); void GenNamedImports(const ir::ETSImportDeclaration *importDeclaration, - const ArenaVector &specifiers, const std::string &source, - const std::string &typeStr); + const ArenaVector &specifiers, bool isTypeKind = false); + void GenDtsImportStatement(std::vector &specifiers, + const ir::ETSImportDeclaration *importDeclaration, bool isTypeKind = false); + void GenTsImportStatement(std::vector &specifiers, const ir::ETSImportDeclaration *importDeclaration, + bool isInterface = false); void GenSingleNamedImport(ir::AstNode *specifier, const ir::ETSImportDeclaration *importDeclaration, bool isGlueCode = false); void GenReExportDeclaration(const ir::ETSReExportDeclaration *reExportDeclaration); + bool GenNamespaceReExportDeclaration(const ir::AstNode *specifier, + const ir::ETSImportDeclaration *importDeclaration); + void SeparateInterfaceSpecifiers(const ArenaVector &specifiers, + std::vector &interfaceSpecifiers, + std::vector &normalSpecifiers); + void GenDtsReExportStatement(const ArenaVector &specifiers, + const ir::ETSImportDeclaration *importDeclaration, bool isTypeKind = false); + void GenTsReExportStatement(const std::vector &specifiers, + const ir::ETSImportDeclaration *importDeclaration, bool isInterface = false); + void GenSingleNamedReExport(ir::AstNode *specifier, const ir::ETSImportDeclaration *importDeclaration, + bool isGlueCode = false); void GenTypeAliasDeclaration(const ir::TSTypeAliasDeclaration *typeAlias); void GenEnumDeclaration(const ir::ClassProperty *enumMember); void GenInterfaceDeclaration(const ir::TSInterfaceDeclaration *interfaceDecl); diff --git a/ets2panda/parser/ETSparserClasses.cpp b/ets2panda/parser/ETSparserClasses.cpp index 1ca0f3e10c6..1241c1b7681 100644 --- a/ets2panda/parser/ETSparserClasses.cpp +++ b/ets2panda/parser/ETSparserClasses.cpp @@ -1307,6 +1307,7 @@ std::pair ETSParser::ParseMemberModifi Lexer()->Rewind(savedPos); } memberModifiers |= ir::ModifierFlags::EXPORT; + memberModifiers |= ir::ModifierFlags::EXPORT_TYPE; } else if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { LogError(diagnostic::ERROR_ARKTS_NO_EXPORT_ASSIGNMENT); } else { -- Gitee