From be9c351f83462af736eb544c8c6e6efcb05e0633 Mon Sep 17 00:00:00 2001 From: dongchao Date: Wed, 11 Jun 2025 23:58:46 +0800 Subject: [PATCH] Support export decl in declgen_ets2ts Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICEHP1 Signed-off-by: dongchao Change-Id: Ia67436fc7ad50c19ddfdfb7a3e71882821a6907d --- ets2panda/bindings/native/src/bridges.cpp | 9 ++ .../bindings/src/Es2pandaNativeModule.ts | 3 + ets2panda/bindings/src/types.ts | 12 ++- ets2panda/compiler/lowering/phase.h | 9 ++ ets2panda/declgen_ets2ts/declgenEts2Ts.cpp | 91 ++++++++++++++++++- ets2panda/declgen_ets2ts/declgenEts2Ts.h | 13 ++- ets2panda/declgen_ets2ts/main.cpp | 6 +- .../build_system/src/build/base_mode.ts | 2 +- .../build_system/src/build/declgen_worker.ts | 2 +- ets2panda/driver/build_system/src/types.ts | 1 + ets2panda/public/es2panda_lib.cpp | 14 +++ ets2panda/public/es2panda_lib.h | 2 + ets2panda/public/es2panda_lib.idl.erb | 1 + 13 files changed, 150 insertions(+), 15 deletions(-) diff --git a/ets2panda/bindings/native/src/bridges.cpp b/ets2panda/bindings/native/src/bridges.cpp index 19790f849e..0c82ed867d 100644 --- a/ets2panda/bindings/native/src/bridges.cpp +++ b/ets2panda/bindings/native/src/bridges.cpp @@ -36,6 +36,15 @@ KNativePointer impl_CreateContextFromString(KNativePointer configPtr, KStringPtr } TS_INTEROP_3(CreateContextFromString, KNativePointer, KNativePointer, KStringPtr, KStringPtr) +KNativePointer impl_CreateContextFromStringWithHistory(KNativePointer configPtr, KStringPtr &sourcePtr, + KStringPtr &filenamePtr, KBoolean isEnableHistory) +{ + auto config = reinterpret_cast(configPtr); + return GetPublicImpl()->CreateContextFromStringWithHistory(config, sourcePtr.data(), filenamePtr.data(), + isEnableHistory); +} +TS_INTEROP_4(CreateContextFromStringWithHistory, KNativePointer, KNativePointer, KStringPtr, KStringPtr, KBoolean) + KInt impl_GenerateTsDeclarationsFromContext(KNativePointer contextPtr, KStringPtr &outputDeclEts, KStringPtr &outputEts, KBoolean exportAll, KBoolean isolated) { diff --git a/ets2panda/bindings/src/Es2pandaNativeModule.ts b/ets2panda/bindings/src/Es2pandaNativeModule.ts index fed3212068..5b2a44ffeb 100644 --- a/ets2panda/bindings/src/Es2pandaNativeModule.ts +++ b/ets2panda/bindings/src/Es2pandaNativeModule.ts @@ -70,6 +70,9 @@ export class Es2pandaNativeModule { _CreateContextFromString(config: KPtr, source: String, filename: String): KPtr { throw new Error('Not implemented'); } + _CreateContextFromStringWithHistory(config: KPtr, source: String, filename: String, isEnableHistory: KBoolean): KPtr { + throw new Error('Not implemented'); + } _GenerateTsDeclarationsFromContext( config: KPtr, outputDeclEts: String, diff --git a/ets2panda/bindings/src/types.ts b/ets2panda/bindings/src/types.ts index ef956f40bf..d96796bb23 100644 --- a/ets2panda/bindings/src/types.ts +++ b/ets2panda/bindings/src/types.ts @@ -13,7 +13,7 @@ * limitations under the License. */ -import { KNativePointer, KNativePointer as KPtr } from './InteropTypes'; +import { KBoolean, KNativePointer, KNativePointer as KPtr } from './InteropTypes'; import { global } from './global'; import { throwError } from './utils'; import { passString, passStringArray, unpackString } from './private'; @@ -104,6 +104,16 @@ export class Context extends ArktsObject { ); } + static createFromStringWithHistory(source: string, isEnableHistory: boolean): Context { + if (!global.configIsInitialized()) { + throwError(`Config not initialized`); + } + let isEnableHistory_: KBoolean = isEnableHistory ? 1 : 0; + return new Context( + global.es2panda._CreateContextFromStringWithHistory(global.config, passString(source), passString(global.filePath), isEnableHistory_) + ); + } + static lspCreateFromString(source: string, filePath: string, cfg: Config): KPtr { if (cfg === undefined) { throwError(`Config not initialized`); diff --git a/ets2panda/compiler/lowering/phase.h b/ets2panda/compiler/lowering/phase.h index 63c3e493f4..fcc41492ae 100644 --- a/ets2panda/compiler/lowering/phase.h +++ b/ets2panda/compiler/lowering/phase.h @@ -145,6 +145,15 @@ public: curr_.minor = phaseId; } + void SetCurrentPhaseIdWithoutReCheck(int32_t phaseId) + { + if (phaseId == curr_.minor) { + return; + } + prev_ = curr_; + curr_.minor = phaseId; + } + ArenaAllocator *Allocator() const { return allocator_; diff --git a/ets2panda/declgen_ets2ts/declgenEts2Ts.cpp b/ets2panda/declgen_ets2ts/declgenEts2Ts.cpp index b0d3441138..c2efe3e8ee 100644 --- a/ets2panda/declgen_ets2ts/declgenEts2Ts.cpp +++ b/ets2panda/declgen_ets2ts/declgenEts2Ts.cpp @@ -17,6 +17,7 @@ #include "isolatedDeclgenChecker.h" #include "checker/types/ets/etsTupleType.h" +#include "compiler/lowering/phase.h" #include "generated/diagnostic.h" #include "ir/base/classProperty.h" #include "ir/base/methodDefinition.h" @@ -27,10 +28,7 @@ #include "ir/ets/etsUnionType.h" #include "ir/expressions/identifier.h" #include "ir/expressions/literals/numberLiteral.h" -#include "ir/module/importSpecifier.h" -#include "ir/statements/blockStatement.h" #include "ir/statements/classDeclaration.h" -#include "ir/ts/tsEnumMember.h" #include "ir/ts/tsInterfaceBody.h" #include "ir/ts/tsTypeAliasDeclaration.h" #include "ir/ts/tsTypeParameter.h" @@ -279,6 +277,15 @@ type Record = { } } +void TSDeclGen::GenExportNamedDeclarations() +{ + for (auto *globalStatement : program_->Ast()->Statements()) { + if (globalStatement->IsExportNamedDeclaration()) { + GenExportNamedDeclaration(globalStatement->AsExportNamedDeclaration()); + } + } +} + void TSDeclGen::GenImportDeclarations() { for (auto *globalStatement : program_->Ast()->Statements()) { @@ -1017,6 +1024,18 @@ void TSDeclGen::GenAnnotationPropertyValue(ir::Expression *propValue) } } +void TSDeclGen::GenExportNamedDeclaration(const ir::ExportNamedDeclaration *exportDeclaration) +{ + DebugPrint("GenExportNamedDeclaration"); + const auto &specifiers = exportDeclaration->Specifiers(); + if (specifiers.empty()) { + return; + } + GenNamedExports(exportDeclaration, specifiers); + OutEndlDts(); + OutEndlTs(); +} + void TSDeclGen::GenImportDeclaration(const ir::ETSImportDeclaration *importDeclaration) { DebugPrint("GenImportDeclaration"); @@ -1126,6 +1145,34 @@ void TSDeclGen::GenDtsImportStatement(std::vector &specifiers, OutDts(" } from \"", source, "\";\n"); } + +void TSDeclGen::GenNamedExports(const ir::ExportNamedDeclaration *exportDeclaration, + const ArenaVector &specifiers) +{ + auto exportSpecifiers = FilterValidExportSpecifiers(specifiers); + if (exportSpecifiers.empty()) { + return; + } + if ((exportDeclaration->Modifiers() & (ir::ModifierFlags::DEFAULT_EXPORT)) != 0U) { + const auto local = specifiers[0]->AsExportSpecifier()->Local()->Name().Mutf8(); + importSet_.insert(local); + OutDts("export default ", local, ";"); + OutTs("export default ", local, ";"); + return; + } + + OutDts("export ", "{ "); + OutTs("export ", "{ "); + + GenSeparated( + exportSpecifiers, + [this](ir::AstNode *specifier) { GenSingleNamedExport(specifier); }, + ", ", true); + + OutDts(" };"); + OutTs(" };"); +} + void TSDeclGen::GenSingleNamedImport(ir::AstNode *specifier, const ir::ETSImportDeclaration *importDeclaration, bool isGlueCode) { @@ -1141,6 +1188,31 @@ void TSDeclGen::GenSingleNamedImport(ir::AstNode *specifier, const ir::ETSImport } } +void TSDeclGen::GenSingleNamedExport(ir::AstNode *specifier) +{ + const auto local = specifier->AsExportSpecifier()->Local()->Name().Mutf8(); + const auto imported = specifier->AsExportSpecifier()->Exported()->Name().Mutf8(); + if (local != imported) { + OutDts(imported, " as ", local); + OutTs(imported, " as ", local); + } else { + OutDts(local); + OutTs(local); + } +} + +std::vector TSDeclGen::FilterValidExportSpecifiers(const ArenaVector &specifiers) +{ + std::vector exportSpecifiers; + for (auto specifier : specifiers) { + const auto local = specifier->Local()->Name().Mutf8(); + if (importSet_.find(local) == importSet_.end()) { + exportSpecifiers.push_back(specifier); + } + } + return exportSpecifiers; +} + std::vector TSDeclGen::FilterValidImportSpecifiers(const ArenaVector &specifiers) { std::vector importSpecifiers; @@ -2204,13 +2276,22 @@ bool GenerateTsDeclarations(checker::ETSChecker *checker, const ark::es2panda::p declBuilder.ResetTsOutput(); declBuilder.ResetDtsOutput(); + compiler::GetPhaseManager()->SetCurrentPhaseIdWithoutReCheck(1); + declBuilder.GenExportNamedDeclarations(); + + std::string exportOutputEts = declBuilder.GetTsOutput(); + std::string exportOutputDEts = declBuilder.GetDtsOutput(); + + declBuilder.ResetTsOutput(); + declBuilder.ResetDtsOutput(); + declBuilder.GenImportDeclarations(); std::string importOutputEts = declBuilder.GetTsOutput(); std::string importOutputDEts = declBuilder.GetDtsOutput(); - std::string combineEts = importOutputEts + outputEts; - std::string combinedDEts = importOutputDEts + outputDEts; + std::string combineEts = importOutputEts + outputEts + exportOutputEts; + std::string combinedDEts = importOutputDEts + outputDEts + exportOutputDEts; if (!declBuilder.GetDeclgenOptions().outputDeclEts.empty()) { auto outDtsPath = declBuilder.GetDeclgenOptions().outputDeclEts; diff --git a/ets2panda/declgen_ets2ts/declgenEts2Ts.h b/ets2panda/declgen_ets2ts/declgenEts2Ts.h index 850722c6f0..cc71f678d2 100644 --- a/ets2panda/declgen_ets2ts/declgenEts2Ts.h +++ b/ets2panda/declgen_ets2ts/declgenEts2Ts.h @@ -16,10 +16,11 @@ #ifndef ES2PANDA_DECLGEN_ETS2TS_H #define ES2PANDA_DECLGEN_ETS2TS_H -#include "parser/program/program.h" #include "checker/ETSchecker.h" +#include "compiler/lowering/phase.h" #include "libpandabase/os/file.h" #include "libpandabase/utils/arena_containers.h" +#include "parser/program/program.h" #include "util/options.h" #include "util/diagnosticEngine.h" #include "isolatedDeclgenChecker.h" @@ -65,6 +66,7 @@ public: bool Generate(); void GenImportDeclarations(); + void GenExportNamedDeclarations(); std::string GetDtsOutput() const { @@ -121,6 +123,7 @@ private: std::vector FilterUnionTypes(const ArenaVector &originTypes); void GenImportDeclaration(const ir::ETSImportDeclaration *importDeclaration); + void GenExportNamedDeclaration(const ir::ExportNamedDeclaration *exportDeclaration); void GenNamespaceImport(const ir::AstNode *specifier, const std::string &source); void GenDefaultImport(const ir::AstNode *specifier, const std::string &source, bool isTypeKind = false); void GenNamedImports(const ir::ETSImportDeclaration *importDeclaration, @@ -129,8 +132,10 @@ private: 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 GenNamedExports(const ir::ExportNamedDeclaration *exportDeclaration, + const ArenaVector &specifiers); + void GenSingleNamedImport(ir::AstNode *specifier, const ir::ETSImportDeclaration *importDeclaration, bool isGlueCode = false); + void GenSingleNamedExport(ir::AstNode *specifier); void GenReExportDeclaration(const ir::ETSReExportDeclaration *reExportDeclaration); bool GenNamespaceReExportDeclaration(const ir::AstNode *specifier, const ir::ETSImportDeclaration *importDeclaration); @@ -188,6 +193,7 @@ private: void ProcessFuncParameters(const checker::Signature *sig); void ProcessClassPropertyType(const ir::ClassProperty *classProp); std::vector FilterValidImportSpecifiers(const ArenaVector &specifiers); + std::vector FilterValidExportSpecifiers(const ArenaVector &specifiers); std::string ReplaceETSGLOBAL(const std::string &typeName); std::string GetIndent() const; std::string RemoveModuleExtensionName(const std::string &filepath); @@ -228,7 +234,6 @@ private: void ProcessInterfaceBody(const ir::TSInterfaceBody *body); void ProcessMethodDefinition(const ir::MethodDefinition *methodDef, std::unordered_set &processedMethods); - void ProcessMethodsFromInterfaces(std::unordered_set &processedMethods, const ArenaVector &interfaces); diff --git a/ets2panda/declgen_ets2ts/main.cpp b/ets2panda/declgen_ets2ts/main.cpp index a13937b367..041a477476 100644 --- a/ets2panda/declgen_ets2ts/main.cpp +++ b/ets2panda/declgen_ets2ts/main.cpp @@ -16,6 +16,7 @@ #include "public/es2panda_lib.h" #include "public/public.h" #include "declgenEts2Ts.h" +#include "ir/astNodeHistory.h" #include "isolatedDeclgenChecker.h" namespace ark::es2panda::declgen_ets2ts { @@ -90,9 +91,8 @@ static int Run(int argc, const char **argv) } auto *cfgImpl = reinterpret_cast(cfg); auto parserInputCStr = cfgImpl->options->CStrParserInputContents().first; - es2panda_Context *ctx = - impl->CreateContextFromString(cfg, parserInputCStr, cfgImpl->options->SourceFileName().c_str()); - + es2panda_Context *ctx = impl->CreateContextFromStringWithHistory(cfg, parserInputCStr, + cfgImpl->options->SourceFileName().c_str(), true); auto *ctxImpl = reinterpret_cast(ctx); auto *checker = reinterpret_cast(ctxImpl->GetChecker()); diff --git a/ets2panda/driver/build_system/src/build/base_mode.ts b/ets2panda/driver/build_system/src/build/base_mode.ts index 55b4555ac3..79833a389d 100644 --- a/ets2panda/driver/build_system/src/build/base_mode.ts +++ b/ets2panda/driver/build_system/src/build/base_mode.ts @@ -173,7 +173,7 @@ export abstract class BaseMode { fileInfo.arktsConfigFile, fileInfo.filePath ]).peer; - arktsGlobal.compilerContext = arkts.Context.createFromString(source); + arktsGlobal.compilerContext = arkts.Context.createFromStringWithHistory(source, true); PluginDriver.getInstance().getPluginContext().setArkTSProgram(arktsGlobal.compilerContext.program); arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_PARSED, arktsGlobal.compilerContext.peer, true); diff --git a/ets2panda/driver/build_system/src/build/declgen_worker.ts b/ets2panda/driver/build_system/src/build/declgen_worker.ts index 42d9f819b8..6eedfc5b01 100644 --- a/ets2panda/driver/build_system/src/build/declgen_worker.ts +++ b/ets2panda/driver/build_system/src/build/declgen_worker.ts @@ -77,7 +77,7 @@ process.on('message', (message: { fileInfo.arktsConfigFile, fileInfo.filePath ]).peer; - arktsGlobal.compilerContext = arkts.Context.createFromString(source); + arktsGlobal.compilerContext = arkts.Context.createFromStringWithHistory(source, true); pluginDriver.getPluginContext().setArkTSProgram(arktsGlobal.compilerContext.program); arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_PARSED, arktsGlobal.compilerContext.peer, true); diff --git a/ets2panda/driver/build_system/src/types.ts b/ets2panda/driver/build_system/src/types.ts index d3012e4096..7e2f916f54 100644 --- a/ets2panda/driver/build_system/src/types.ts +++ b/ets2panda/driver/build_system/src/types.ts @@ -74,6 +74,7 @@ export interface ArkTS { }; Context: { createFromString: Function; + createFromStringWithHistory: Function; }; EtsScript: { fromContext: Function; diff --git a/ets2panda/public/es2panda_lib.cpp b/ets2panda/public/es2panda_lib.cpp index 22757da105..b46e5ea3f1 100644 --- a/ets2panda/public/es2panda_lib.cpp +++ b/ets2panda/public/es2panda_lib.cpp @@ -524,6 +524,19 @@ extern __attribute__((unused)) es2panda_Context *CreateContextGenerateAbcForExte return reinterpret_cast(res); } +extern "C" __attribute__((unused)) es2panda_Context *CreateContextFromStringWithHistory(es2panda_Config *config, + const char *source, + char const *fileName, + bool isEnableContextHistory) +{ + // NOTE: gogabr. avoid copying source. + es2panda_Context *context = CreateContextFromString(config, source, fileName); + if (isEnableContextHistory) { + ir::EnableContextHistory(); + } + return context; +} + __attribute__((unused)) static Context *Parse(Context *ctx) { if (ctx->state != ES2PANDA_STATE_NEW) { @@ -1302,6 +1315,7 @@ es2panda_Impl g_impl = { CreateContextFromFile, CreateCacheContextFromFile, CreateContextFromString, + CreateContextFromStringWithHistory, CreateCacheContextFromString, CreateContextGenerateAbcForExternalSourceFiles, ProceedToState, diff --git a/ets2panda/public/es2panda_lib.h b/ets2panda/public/es2panda_lib.h index cb861ee1db..67f9a3f9bc 100644 --- a/ets2panda/public/es2panda_lib.h +++ b/ets2panda/public/es2panda_lib.h @@ -187,6 +187,8 @@ struct CAPI_EXPORT es2panda_Impl { es2panda_Context *(*CreateCacheContextFromFile)(es2panda_Config *config, char const *source_file_name, es2panda_GlobalContext *globalContext, bool isExternal); es2panda_Context *(*CreateContextFromString)(es2panda_Config *config, const char *source, char const *file_name); + es2panda_Context *(*CreateContextFromStringWithHistory)(es2panda_Config *config, const char *source, + char const *file_name, bool isEnableContextHistory); es2panda_Context *(*CreateCacheContextFromString)(es2panda_Config *config, const char *source, char const *file_name, es2panda_GlobalContext *globalContext, bool isExternal); diff --git a/ets2panda/public/es2panda_lib.idl.erb b/ets2panda/public/es2panda_lib.idl.erb index dcff86fb9e..0aef8bfcca 100644 --- a/ets2panda/public/es2panda_lib.idl.erb +++ b/ets2panda/public/es2panda_lib.idl.erb @@ -174,6 +174,7 @@ interface es2panda_Impl { es2panda_Context CreateContextFromFile(es2panda_Config config, String source_file_name); es2panda_Context CreateCacheContextFromFile(es2panda_Config config, String source_file_name, es2panda_GlobalContext globalContext, boolean isExternal); es2panda_Context CreateContextFromString(es2panda_Config config, String source, String file_name); + es2panda_Context CreateContextFromStringWithHistory(es2panda_Config config, String source, String file_name, boolean isEnableContextHistory); es2panda_Context CreateCacheContextFromString(es2panda_Config config, String source, String file_name, es2panda_GlobalContext globalContext, boolean isExternal); es2panda_Context CreateContextGenerateAbcForExternalSourceFiles(es2panda_Config config, i32 fileNamesCount, sequence fileNames); es2panda_Context ProceedToState(es2panda_Context context, es2panda_ContextState state); // context is consumed -- Gitee