From 188e2897f6fdbecd5598c3fc0f224f0a4644fa1e Mon Sep 17 00:00:00 2001 From: Georgy Bronnikov Date: Mon, 23 Jun 2025 07:51:32 +0300 Subject: [PATCH 1/3] Fix bug from instanceof and generics Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICGV43 Signed-off-by: Georgy Bronnikov --- ets2panda/checker/ETSAnalyzer.cpp | 1 + ets2panda/checker/ets/object.cpp | 9 +++++- ets2panda/test/runtime/ets/27016.ets | 41 ++++++++++++++++++++++++++ ets2panda/test/runtime/ets/27016_2.ets | 33 +++++++++++++++++++++ 4 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 ets2panda/test/runtime/ets/27016.ets create mode 100644 ets2panda/test/runtime/ets/27016_2.ets diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 2c0fd6a3fc..723613aa9c 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -3610,6 +3610,7 @@ checker::Type *ETSAnalyzer::Check(ir::TSQualifiedName *expr) const checker::Type *ETSAnalyzer::Check(ir::TSTypeAliasDeclaration *st) const { ETSChecker *checker = GetETSChecker(); + auto checkerContext = SavedCheckerContext(checker, CheckerStatus::NO_OPTS, checker->Context().ContainingClass()); checker->CheckAnnotations(st->Annotations()); diff --git a/ets2panda/checker/ets/object.cpp b/ets2panda/checker/ets/object.cpp index c5724a9d7e..7f957d9fa1 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -440,6 +440,13 @@ Type *ETSChecker::BuildBasicInterfaceProperties(ir::TSInterfaceDeclaration *inte interfaceType = var->TsType()->AsETSObjectType(); } + // Save before we mess with savedContext. + bool builtinsInitialized = HasStatus(CheckerStatus::BUILTINS_INITIALIZED); + + auto *enclosingClass = Context().ContainingClass(); + interfaceType->SetEnclosingType(enclosingClass); + CheckerStatus newStatus = CheckerStatus::IN_INTERFACE; + auto savedContext = checker::SavedCheckerContext(this, newStatus, interfaceType); ConstraintCheckScope ctScope(this); if (interfaceDecl->TypeParams() != nullptr) { interfaceType->AddTypeFlag(TypeFlag::GENERIC); @@ -453,7 +460,7 @@ Type *ETSChecker::BuildBasicInterfaceProperties(ir::TSInterfaceDeclaration *inte // Skip this check if the builtins are not initialized. // They will be initialized in different order, // and it is possible that the FunctionType interface is not yet created. - if (HasStatus(CheckerStatus::BUILTINS_INITIALIZED)) { + if (builtinsInitialized) { CheckInterfaceFunctions(interfaceType); } diff --git a/ets2panda/test/runtime/ets/27016.ets b/ets2panda/test/runtime/ets/27016.ets new file mode 100644 index 0000000000..fa618d9c23 --- /dev/null +++ b/ets2panda/test/runtime/ets/27016.ets @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025 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. + */ + +class NNBB { + static f(a: Object) { + return a instanceof B + } +} + +interface A { + get(): TA +} +interface B extends A { +} + +class D implements B { + constructor(d: TD) { + this.d = d + } + get(): TD { + return this.d + } + d: TD +} + +function main() { + let a: A = new D(5) + arktest.assertEQ(a.get(), 5) +} diff --git a/ets2panda/test/runtime/ets/27016_2.ets b/ets2panda/test/runtime/ets/27016_2.ets new file mode 100644 index 0000000000..9e95ee41cd --- /dev/null +++ b/ets2panda/test/runtime/ets/27016_2.ets @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 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. + */ + +class A { + f(b: object) { + b instanceof B + let c: B = {v: 1} + return c + } +} + +type B = C + +interface C { + v: T +} + +function main() { + let a = new A + arktest.assertEQ(a.f(a).v, 1) +} -- Gitee From 999045b368b2b5bce379e0a807226f0e50b82139 Mon Sep 17 00:00:00 2001 From: ekkoruse Date: Tue, 24 Jun 2025 00:10:39 +0800 Subject: [PATCH 2/3] Compile simultaneously for build_system support compile simultaneously Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICDR65?from=project-issue Change-Id: I4c3b7fc48469c2cc1cc6febb1113f4467a2a2eb6 Signed-off-by: zenghang --- ets2panda/driver/build_system/package.json | 11 +- .../build_system/src/build/base_mode.ts | 110 ++++++++++++++---- .../build_system/src/build/build_mode.ts | 2 +- ets2panda/driver/build_system/src/types.ts | 1 + 4 files changed, 92 insertions(+), 32 deletions(-) diff --git a/ets2panda/driver/build_system/package.json b/ets2panda/driver/build_system/package.json index 597e3abe96..5d9fe607cc 100644 --- a/ets2panda/driver/build_system/package.json +++ b/ets2panda/driver/build_system/package.json @@ -8,20 +8,15 @@ "clean": "rimraf dist", "build": "npm run clean && tsc", "build_debug": "npm run clean && tsc --sourceMap", - "mixed_hap:gen_decl": "npm run build && node ./dist/entry.js test/demo_mix_hap/build_config_decl.json", "mixed_hap:gen_abc": "node ./dist/entry.js test/demo_mix_hap/build_config.json", "mixed_hap:run": "npm run mixed_hap:gen_decl && npm run mixed_hap:gen_abc", - "demo_hap:gen_abc": "npm run build && node ./dist/entry.js test/demo_hap/build_config.json" }, "devDependencies": { - "typescript": "^5.0.0", - "@types/node": "22.10.7", "@tsconfig/recommended": "1.0.8", - "rimraf": "6.0.1" - }, - "dependencies": { - + "@types/node": "22.10.7", + "rimraf": "^6.0.1", + "typescript": "^5.0.0" } } diff --git a/ets2panda/driver/build_system/src/build/base_mode.ts b/ets2panda/driver/build_system/src/build/base_mode.ts index c5282cded0..b998ae78ce 100644 --- a/ets2panda/driver/build_system/src/build/base_mode.ts +++ b/ets2panda/driver/build_system/src/build/base_mode.ts @@ -261,6 +261,63 @@ export abstract class BaseMode { } } + public compileMultiFiles(filePaths: string[], moduleInfo: ModuleInfo): void { + let ets2pandaCmd: string[] = [ + '_', + '--extension', + 'ets', + '--arktsconfig', + moduleInfo.arktsConfigFile, + '--output', + path.resolve(this.outputDir, MERGED_ABC_FILE), + '--simultaneous' + ]; + ensurePathExists(path.resolve(this.outputDir, MERGED_ABC_FILE)); + if (this.isDebug) { + ets2pandaCmd.push('--debug-info'); + } + ets2pandaCmd.push(this.buildConfig.compileFiles[0]); + this.logger.printInfo('ets2pandaCmd: ' + ets2pandaCmd.join(' ')); + + let arktsGlobal = this.buildConfig.arktsGlobal; + let arkts = this.buildConfig.arkts; + let errorStatus = false; + try { + arktsGlobal.config = arkts.Config.create(ets2pandaCmd).peer; + //@ts-ignore + arktsGlobal.compilerContext = arkts.Context.createContextGenerateAbcForExternalSourceFiles(this.buildConfig.compileFiles);; + PluginDriver.getInstance().getPluginContext().setArkTSProgram(arktsGlobal.compilerContext.program); + + arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_PARSED, arktsGlobal.compilerContext.peer); + this.logger.printInfo('es2panda proceedToState parsed'); + let ast = arkts.EtsScript.fromContext(); + PluginDriver.getInstance().getPluginContext().setArkTSAst(ast); + PluginDriver.getInstance().runPluginHook(PluginHook.PARSED); + this.logger.printInfo('plugin parsed finished'); + + arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_CHECKED, arktsGlobal.compilerContext.peer); + this.logger.printInfo('es2panda proceedToState checked'); + + ast = arkts.EtsScript.fromContext(); + PluginDriver.getInstance().getPluginContext().setArkTSAst(ast); + PluginDriver.getInstance().runPluginHook(PluginHook.CHECKED); + this.logger.printInfo('plugin checked finished'); + + arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_BIN_GENERATED, arktsGlobal.compilerContext.peer); + this.logger.printInfo('es2panda bin generated'); + } catch (error) { + errorStatus = true; + throw error; + } finally { + if (!errorStatus) { + // when error occur,wrapper will destroy context. + arktsGlobal.es2panda._DestroyContext(arktsGlobal.compilerContext.peer); + } + PluginDriver.getInstance().runPluginHook(PluginHook.CLEAN); + arkts.destroyConfig(arktsGlobal.config); + } + } + public mergeAbcFiles(): void { let linkerInputFile: string = path.join(this.cacheDir, LINKER_INPUT_FILE); let linkerInputContent: string = ''; @@ -543,19 +600,15 @@ export abstract class BaseMode { } }); } - + private shouldSkipFile(file: string, moduleInfo: ModuleInfo, filePathFromModuleRoot: string, abcFilePath: string): boolean { const targetPath = this.enableDeclgenEts2Ts - ? changeFileExtension(path.join(moduleInfo.declgenBridgeCodePath as string, moduleInfo.packageName, filePathFromModuleRoot), TS_SUFFIX) - : abcFilePath; + ? changeFileExtension(path.join(moduleInfo.declgenBridgeCodePath as string, moduleInfo.packageName, filePathFromModuleRoot), TS_SUFFIX) + : abcFilePath; return !this.isFileChanged(file, targetPath); } protected collectCompileFiles(): void { - if (!this.isBuildConfigModified && this.isCacheFileExists && !this.enableDeclgenEts2Ts) { - this.collectDependentCompileFiles(); - return; - } this.entryFiles.forEach((file: string) => { for (const [packageName, moduleInfo] of this.moduleInfos) { if (!file.startsWith(moduleInfo.moduleRootPath)) { @@ -615,15 +668,26 @@ export abstract class BaseMode { this.generateModuleInfos(); const compilePromises: Promise[] = []; + let moduleToFile = new Map(); this.compileFiles.forEach((fileInfo: CompileFileInfo, file: string) => { - compilePromises.push(new Promise((resolve) => { - this.compile(fileInfo); - resolve(); - })); + if (!moduleToFile.has(fileInfo.packageName)) { + moduleToFile.set(fileInfo.packageName, []); + } + moduleToFile.get(fileInfo.packageName)?.push(fileInfo.filePath); }); - await Promise.all(compilePromises); - - this.mergeAbcFiles(); + try { + //@ts-ignore + this.compileMultiFiles([], this.moduleInfos.get(this.packageName)); + } catch (error) { + if (error instanceof Error) { + const logData: LogData = LogDataFactory.newInstance( + ErrorCode.BUILDSYSTEM_COMPILE_ABC_FAIL, + 'Compile abc files failed.', + error.message + ); + this.logger.printErrorAndExit(logData); + } + } } private terminateAllWorkers(): void { @@ -646,8 +710,8 @@ export abstract class BaseMode { this.dependencyAnalyzerCmd.push('@' + '"' + dependencyInputFile + '"'); for (const [packageName, module] of this.moduleInfos) { if (module.isMainModule) { - this.dependencyAnalyzerCmd.push('--arktsconfig=' + '"' + module.arktsConfigFile + '"'); - break; + this.dependencyAnalyzerCmd.push('--arktsconfig=' + '"' + module.arktsConfigFile + '"'); + break; } } this.dependencyAnalyzerCmd.push('--output=' + '"' + this.dependencyJsonFile + '"'); @@ -660,7 +724,7 @@ export abstract class BaseMode { ensurePathExists(this.dependencyJsonFile); try { - const output = child_process.execSync(dependencyAnalyzerCmdStr, { + const output = child_process.execSync(dependencyAnalyzerCmdStr, { stdio: 'pipe', encoding: 'utf-8' }); @@ -680,10 +744,10 @@ export abstract class BaseMode { const execError = error as child_process.ExecException; let fullErrorMessage = execError.message; if (execError.stderr) { - fullErrorMessage += `\nError output: ${execError.stderr}`; + fullErrorMessage += `\nError output: ${execError.stderr}`; } if (execError.stdout) { - fullErrorMessage += `\nOutput: ${execError.stdout}`; + fullErrorMessage += `\nOutput: ${execError.stdout}`; } const logData: LogData = LogDataFactory.newInstance( ErrorCode.BUILDSYSTEM_Dependency_Analyze_FAIL, @@ -736,7 +800,7 @@ export abstract class BaseMode { await this.dispatchTasks(); this.logger.printInfo('All declaration generation tasks complete.'); } catch (error) { - this.logger.printError(LogDataFactory.newInstance( + this.logger.printError(LogDataFactory.newInstance( ErrorCode.BUILDSYSTEM_DECLGEN_FAIL, 'Generate declaration files failed.' )); @@ -773,7 +837,7 @@ export abstract class BaseMode { const worker = cluster.fork(); this.setupWorkerMessageHandler(worker); - worker.send({ taskList: taskChunk, buildConfig: serializableConfig, moduleInfos: moduleInfosArray}); + worker.send({ taskList: taskChunk, buildConfig: serializableConfig, moduleInfos: moduleInfosArray }); const exitPromise = new Promise((resolve, reject) => { worker.on('exit', (status) => status === 0 ? resolve() : reject()); @@ -826,11 +890,11 @@ export abstract class BaseMode { execPath, execArgs = [], } = options; - + if (clearExitListeners) { cluster.removeAllListeners('exit'); } - + cluster.setupPrimary({ exec: execPath, execArgv: execArgs, diff --git a/ets2panda/driver/build_system/src/build/build_mode.ts b/ets2panda/driver/build_system/src/build/build_mode.ts index 59bdb759ab..b1643a8d9c 100644 --- a/ets2panda/driver/build_system/src/build/build_mode.ts +++ b/ets2panda/driver/build_system/src/build/build_mode.ts @@ -26,6 +26,6 @@ export class BuildMode extends BaseMode { } public async run(): Promise { - await super.runParallell(); + await super.run(); } } \ No newline at end of file diff --git a/ets2panda/driver/build_system/src/types.ts b/ets2panda/driver/build_system/src/types.ts index 0d0d0d38ac..e651e1e099 100644 --- a/ets2panda/driver/build_system/src/types.ts +++ b/ets2panda/driver/build_system/src/types.ts @@ -43,6 +43,7 @@ export interface ArkTSGlobal { export interface ArkTS { Config: { create: Function; + createContextGenerateAbcForExternalSourceFiles: Function; }; Context: { createFromString: Function; -- Gitee From ef7c2289a2fb688a07cd669ecc3992153c292841 Mon Sep 17 00:00:00 2001 From: ekkoruse Date: Tue, 24 Jun 2025 00:08:31 +0800 Subject: [PATCH 3/3] Compile simultaneously support compile simultaneously Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICDR65?from=project-issue Change-Id: I4c3b7fc48469c2cc1cc6febb1113f4467a2a2eb6 Signed-off-by: ekkoruse Signed-off-by: huyunhui1 --- ets2panda/checker/ETSchecker.cpp | 6 + ets2panda/checker/ets/helpers.cpp | 5 +- ets2panda/checker/ets/object.cpp | 6 +- ets2panda/checker/ets/typeCheckingHelpers.cpp | 11 + ets2panda/checker/ets/utilityTypeHandlers.cpp | 4 +- ets2panda/compiler/core/ETSemitter.cpp | 47 +++- ets2panda/compiler/core/compilerImpl.cpp | 13 +- ets2panda/compiler/core/emitter.cpp | 6 +- .../compiler/lowering/ets/lambdaLowering.cpp | 3 +- ets2panda/compiler/lowering/phase.cpp | 71 ++++--- ets2panda/compiler/scripts/signatures.yaml | 6 + ets2panda/es2panda.h | 1 + ets2panda/parser/ETSparser.cpp | 50 ++++- ets2panda/parser/ETSparser.h | 3 + ets2panda/parser/parserImpl.h | 15 ++ ets2panda/parser/program/program.cpp | 7 + ets2panda/parser/program/program.h | 10 +- ets2panda/public/es2panda_lib.cpp | 107 +++++++++- ets2panda/public/es2panda_lib.h | 2 + ets2panda/public/es2panda_lib.idl.erb | 1 + ets2panda/public/public.h | 35 ++- .../ets/import_export/eitest_export_A_1.ets | 16 ++ .../ets/import_export/eitest_export_A_2.ets | 18 ++ .../ets/import_export/eitest_export_B_1.ets | 16 ++ .../import_export/eitest_export_B_as_A_1.ets | 18 ++ .../eitest_export_default_A_1.ets | 16 ++ .../eitest_export_default_A_2.ets | 18 ++ .../eitest_export_default_B_1.ets | 16 ++ .../eitest_export_default_B_2.ets | 18 ++ ...test_export_default_import_default_A_1.ets | 18 ++ .../eitest_export_import_A_1.ets | 18 ++ .../eitest_export_import_A_2.ets | 18 ++ .../eitest_export_import_A_3.ets | 18 ++ .../eitest_export_import_default_A_1.ets | 18 ++ .../eitest_export_import_default_A_B_1.ets | 19 ++ .../import_export/eitest_export_type_A_1.ets | 19 ++ .../ets/import_export/eitest_import_A_1.ets | 20 ++ .../import_export/eitest_import_A_1_ne.ets | 24 +++ .../ets/import_export/eitest_import_A_2.ets | 20 ++ .../import_export/eitest_import_A_2_ne.ets | 24 +++ .../ets/import_export/eitest_import_A_3.ets | 20 ++ .../import_export/eitest_import_A_3_ne.ets | 24 +++ .../ets/import_export/eitest_import_A_4.ets | 20 ++ .../import_export/eitest_import_A_4_ne.ets | 24 +++ .../ets/import_export/eitest_import_A_5.ets | 20 ++ .../import_export/eitest_import_A_5_ne.ets | 24 +++ .../ets/import_export/eitest_import_A_6.ets | 20 ++ .../import_export/eitest_import_A_6_ne.ets | 24 +++ .../ets/import_export/eitest_import_A_7.ets | 20 ++ .../import_export/eitest_import_A_7_ne.ets | 24 +++ .../ets/import_export/eitest_import_A_B_1.ets | 21 ++ .../import_export/eitest_import_A_B_1_ne.ets | 24 +++ .../eitest_import_default_A_1.ets | 20 ++ .../eitest_import_default_A_1_ne.ets | 22 ++ .../eitest_import_default_A_2.ets | 20 ++ .../eitest_import_default_A_2_ne.ets | 24 +++ .../eitest_import_default_A_3.ets | 20 ++ .../eitest_import_default_A_3_ne.ets | 22 ++ .../import_export/eitest_import_type_A_1.ets | 20 ++ .../eitest_import_type_A_1_ne.ets | 22 ++ .../ets/import_export/external_export.ets | 16 ++ .../compiler/ets/import_export/test1_1.ets | 17 ++ .../compiler/ets/import_export/test2_1.ets | 18 ++ .../compiler/ets/import_export/test3_1.ets | 17 ++ .../isolated_interface-expected.txt | 2 +- .../srcdumper/srcdumper-ets-ignored.txt | 29 +++ ets2panda/util/diagnostic/fatal.yaml | 4 + ets2panda/util/importPathManager.cpp | 2 +- ets2panda/util/importPathManager.h | 7 +- ets2panda/util/options.cpp | 6 +- ets2panda/util/options.h | 1 + ets2panda/util/options.yaml | 5 + ets2panda/varbinder/ETSBinder.cpp | 201 +++++++++++++++--- ets2panda/varbinder/ETSBinder.h | 18 +- 74 files changed, 1454 insertions(+), 85 deletions(-) create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_export_A_1.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_export_A_2.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_export_B_1.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_export_B_as_A_1.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_export_default_A_1.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_export_default_A_2.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_export_default_B_1.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_export_default_B_2.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_export_default_import_default_A_1.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_export_import_A_1.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_export_import_A_2.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_export_import_A_3.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_export_import_default_A_1.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_export_import_default_A_B_1.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_export_type_A_1.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_1.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_1_ne.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_2.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_2_ne.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_3.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_3_ne.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_4.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_4_ne.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_5.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_5_ne.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_6.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_6_ne.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_7.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_7_ne.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_B_1.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_B_1_ne.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_import_default_A_1.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_import_default_A_1_ne.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_import_default_A_2.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_import_default_A_2_ne.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_import_default_A_3.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_import_default_A_3_ne.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_import_type_A_1.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/eitest_import_type_A_1_ne.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/external_export.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/test1_1.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/test2_1.ets create mode 100644 ets2panda/test/ast/compiler/ets/import_export/test3_1.ets diff --git a/ets2panda/checker/ETSchecker.cpp b/ets2panda/checker/ETSchecker.cpp index 452cf67b95..b09dd075df 100644 --- a/ets2panda/checker/ETSchecker.cpp +++ b/ets2panda/checker/ETSchecker.cpp @@ -365,10 +365,16 @@ void ETSChecker::CheckProgram(parser::Program *program, bool runAnalysis) if (extProg->IsASTChecked()) { continue; } + + auto *savedProgram2 = VarBinder()->AsETSBinder()->Program(); + VarBinder()->AsETSBinder()->SetProgram(extProg); + VarBinder()->AsETSBinder()->ResetTopScope(extProg->GlobalScope()); checker::SavedCheckerContext savedContext(this, Context().Status(), Context().ContainingClass()); AddStatus(checker::CheckerStatus::IN_EXTERNAL); CheckProgram(extProg, VarBinder()->IsGenStdLib()); extProg->SetFlag(parser::ProgramFlags::AST_CHECK_PROCESSED); + VarBinder()->AsETSBinder()->SetProgram(savedProgram2); + VarBinder()->AsETSBinder()->ResetTopScope(savedProgram2->GlobalScope()); } } diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index c799944902..71e89368fa 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -2854,6 +2854,8 @@ void ETSChecker::SetupGetterSetterFlags(ir::ClassProperty *originalProp, ETSObje ir::MethodDefinition *getter, ir::MethodDefinition *setter, const bool inExternal) { + auto getProgram = [](ir::AstNode *node) { return node->Range().start.Program(); }; + auto *const classDef = classType->GetDeclNode()->AsClassDefinition(); for (auto &method : {getter, setter}) { if (method == nullptr) { @@ -2869,7 +2871,7 @@ void ETSChecker::SetupGetterSetterFlags(ir::ClassProperty *originalProp, ETSObje method->Function()->AddModifier(ir::ModifierFlags::OVERRIDE); } - if (inExternal) { + if (inExternal && !getProgram(originalProp)->IsGenAbcForExternal()) { method->Function()->AddFlag(ir::ScriptFunctionFlags::EXTERNAL); } @@ -2993,6 +2995,7 @@ bool ETSChecker::TryTransformingToStaticInvoke(ir::Identifier *const ident, cons callExpr->SetCallee(transformedCallee); if (instantiateMethod != nullptr) { + auto lexScope {varbinder::LexicalScope::Enter(VarBinder(), compiler::NearestScope(callExpr))}; // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) auto *argExpr = GenerateImplicitInstantiateArg(std::string(className)); diff --git a/ets2panda/checker/ets/object.cpp b/ets2panda/checker/ets/object.cpp index 7f957d9fa1..2b6cfeac48 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -1880,7 +1880,11 @@ varbinder::Variable *ETSChecker::GetExtensionFuncVarInGlobalFunction(const ir::M { auto propertyName = memberExpr->Property()->AsIdentifier()->Name(); auto *globalFunctionVar = Scope()->FindInGlobal(propertyName, VO::STATIC_METHODS).variable; - if (globalFunctionVar == nullptr || !IsExtensionETSFunctionType(globalFunctionVar->TsType())) { + if (globalFunctionVar == nullptr) { + return nullptr; + } + + if (!IsExtensionETSFunctionType(GetTypeOfVariable(globalFunctionVar))) { return nullptr; } diff --git a/ets2panda/checker/ets/typeCheckingHelpers.cpp b/ets2panda/checker/ets/typeCheckingHelpers.cpp index 1fa0493279..3299c5ef72 100644 --- a/ets2panda/checker/ets/typeCheckingHelpers.cpp +++ b/ets2panda/checker/ets/typeCheckingHelpers.cpp @@ -773,8 +773,14 @@ Type *ETSChecker::GetTypeFromInterfaceReference(varbinder::Variable *var) return var->TsType(); } + CheckerStatus status = CheckerStatus::IN_STATIC_CONTEXT; + status &= this->Context().Status(); + this->Context().Status() &= ~CheckerStatus::IN_STATIC_CONTEXT; + auto *interfaceType = BuildBasicInterfaceProperties(var->Declaration()->Node()->AsTSInterfaceDeclaration()); var->SetTsType(interfaceType); + + this->Context().Status() |= status; return interfaceType; } @@ -786,8 +792,13 @@ Type *ETSChecker::GetTypeFromClassReference(varbinder::Variable *var) auto classDef = var->Declaration()->Node()->AsClassDefinition(); + CheckerStatus status = CheckerStatus::IN_STATIC_CONTEXT; + status &= this->Context().Status(); + this->Context().Status() &= ~CheckerStatus::IN_STATIC_CONTEXT; + auto *classType = BuildBasicClassProperties(classDef); var->SetTsType(classType); + this->Context().Status() |= status; return classType; } diff --git a/ets2panda/checker/ets/utilityTypeHandlers.cpp b/ets2panda/checker/ets/utilityTypeHandlers.cpp index d9e630189d..e0198ae7b4 100644 --- a/ets2panda/checker/ets/utilityTypeHandlers.cpp +++ b/ets2panda/checker/ets/utilityTypeHandlers.cpp @@ -141,7 +141,9 @@ Type *ETSChecker::CreatePartialTypeClass(ETSObjectType *typeToBePartial, ir::Ast // Check if we've already generated the partial class, then don't do it again const auto classNameToFind = - partialProgram == VarBinder()->Program() || VarBinder()->IsGenStdLib() ? partialName : partialQualifiedName; + partialProgram == VarBinder()->Program() || VarBinder()->IsGenStdLib() || partialProgram->IsGenAbcForExternal() + ? partialName + : partialQualifiedName; if (auto *var = SearchNamesInMultiplePrograms({partialProgram, VarBinder()->Program()}, {classNameToFind, partialName}); var != nullptr) { diff --git a/ets2panda/compiler/core/ETSemitter.cpp b/ets2panda/compiler/core/ETSemitter.cpp index 6eba5e1753..8ce70a9036 100644 --- a/ets2panda/compiler/core/ETSemitter.cpp +++ b/ets2panda/compiler/core/ETSemitter.cpp @@ -262,10 +262,35 @@ static std::vector> StoreExportNodes( return result; } +void FilterForSimultaneous(varbinder::ETSBinder *varbinder) +{ + ArenaSet &classDefinitions = varbinder->GetGlobalRecordTable()->ClassDefinitions(); + for (auto it = classDefinitions.begin(); it != classDefinitions.end(); ++it) { + if ((*it)->InternalName().Is(Signatures::ETS_GLOBAL)) { + classDefinitions.erase(it); + break; + } + } + std::vector filterFunctions = { + Signatures::UNUSED_ETSGLOBAL_CTOR, Signatures::UNUSED_ETSGLOBAL_INIT, Signatures::UNUSED_ETSGLOBAL_MAIN}; + auto &functions = varbinder->Functions(); + functions.erase(std::remove_if(functions.begin(), functions.end(), + [&filterFunctions](varbinder::FunctionScope *scope) -> bool { + return std::any_of( + filterFunctions.begin(), filterFunctions.end(), + [&scope](std::string_view &s) { return scope->InternalName().Is(s); }); + }), // CC-OFF(G.FMT.02) + functions.end()); +} + void ETSEmitter::GenAnnotation() { Program()->lang = EXTENSION; - const auto *varbinder = static_cast(Context()->parserProgram->VarBinder()); + auto *varbinder = static_cast(Context()->parserProgram->VarBinder()); + + if (Context()->config->options->GetCompilationMode() == CompilationMode::GEN_ABC_FOR_EXTERNAL_SOURCE) { + FilterForSimultaneous(varbinder); + } auto *globalRecordTable = varbinder->GetGlobalRecordTable(); auto baseName = varbinder->GetRecordTable()->RecordName().Mutf8(); @@ -324,29 +349,37 @@ static bool IsFromSelfHeadFile(const std::string &name, const parser::Program *c void ETSEmitter::GenExternalRecord(varbinder::RecordTable *recordTable, const parser::Program *extProg) { - bool isGenStdLib = recordTable->Program()->VarBinder()->IsGenStdLib(); + bool isExternalFromCompile = + !recordTable->Program()->VarBinder()->IsGenStdLib() && !recordTable->Program()->IsGenAbcForExternal(); const auto *varbinder = static_cast(Context()->parserProgram->VarBinder()); auto baseName = varbinder->GetRecordTable()->RecordName().Mutf8(); for (auto *annoDecl : recordTable->AnnotationDeclarations()) { auto newBaseName = GenerateMangledName(baseName, annoDecl->GetBaseName()->Name().Mutf8()); - GenCustomAnnotationRecord(annoDecl, newBaseName, !isGenStdLib); + GenCustomAnnotationRecord(annoDecl, newBaseName, isExternalFromCompile || annoDecl->IsDeclare()); } for (auto *classDecl : recordTable->ClassDefinitions()) { - GenClassRecord(classDecl, !isGenStdLib); + GenClassRecord(classDecl, isExternalFromCompile || classDecl->IsDeclare()); } for (auto *interfaceDecl : recordTable->InterfaceDeclarations()) { - GenInterfaceRecord(interfaceDecl, !isGenStdLib); + GenInterfaceRecord(interfaceDecl, isExternalFromCompile || interfaceDecl->IsDeclare()); } for (auto *signature : recordTable->Signatures()) { - auto func = GenScriptFunction(signature->Node()->AsScriptFunction(), this); + auto scriptFunc = signature->Node()->AsScriptFunction(); + auto func = GenScriptFunction(scriptFunc, this); - if (!isGenStdLib) { + if (isExternalFromCompile || scriptFunc->IsDeclare()) { func.metadata->SetAttribute(Signatures::EXTERNAL); } + if (extProg->IsGenAbcForExternal() && scriptFunc->IsAsyncFunc()) { + std::vector annotations; + annotations.push_back(GenAnnotationAsync(scriptFunc)); + func.metadata->AddAnnotations(annotations); + } + if (func.metadata->IsForeign() && IsFromSelfHeadFile(func.name, Context()->parserProgram, extProg)) { return; } diff --git a/ets2panda/compiler/core/compilerImpl.cpp b/ets2panda/compiler/core/compilerImpl.cpp index af038f7485..0f206c0f0d 100644 --- a/ets2panda/compiler/core/compilerImpl.cpp +++ b/ets2panda/compiler/core/compilerImpl.cpp @@ -397,7 +397,17 @@ static bool ExecuteParsingAndCompiling(const CompilationUnit &unit, public_lib:: AddExternalPrograms(context, unit, program); } - context->parser->ParseScript(unit.input, unit.options.GetCompilationMode() == CompilationMode::GEN_STD_LIB); + if (context->config->options->GetCompilationMode() == CompilationMode::GEN_ABC_FOR_EXTERNAL_SOURCE && + context->config->options->GetExtension() == ScriptExtension::ETS) { + std::unordered_set sourceFileNamesSet; + util::UString absolutePath(os::GetAbsolutePath(context->sourceFile->filePath), context->allocator); + sourceFileNamesSet.insert(absolutePath.View().Mutf8()); + context->sourceFileNames.emplace_back(absolutePath.View().Utf8()); + parser::ETSParser::AddGenExtenralSourceToParseList(context); + context->MarkGenAbcForExternal(sourceFileNamesSet, context->parserProgram->ExternalSources()); + } else { + context->parser->ParseScript(unit.input, unit.options.GetCompilationMode() == CompilationMode::GEN_STD_LIB); + } // We have to check the return status of 'RunVerifierAndPhase` and 'RunPhases` separately because there can be // some internal errors (say, in Post-Conditional check) or terminate options (say in 'CheckOptionsAfterPhase') @@ -434,6 +444,7 @@ static pandasm::Program *Compile(const CompilationUnit &unit, CompilerImpl *comp : nullptr); auto parser = Parser(&program, unit.options, unit.diagnosticEngine, static_cast(unit.rawParserStatus)); + parser.SetContext(context); context->parser = &parser; auto checker = Checker(unit.diagnosticEngine, context->allocator); context->checker = &checker; diff --git a/ets2panda/compiler/core/emitter.cpp b/ets2panda/compiler/core/emitter.cpp index 95b7d45aee..91ee21b4fb 100644 --- a/ets2panda/compiler/core/emitter.cpp +++ b/ets2panda/compiler/core/emitter.cpp @@ -438,6 +438,9 @@ static void UpdateLiteralBufferId([[maybe_unused]] ark::pandasm::Ins *ins, [[may void Emitter::AddProgramElement(ProgramElement *programElement) { + if (programElement->Function() == nullptr) { + return; + } prog_->strings.insert(programElement->Strings().begin(), programElement->Strings().end()); uint32_t newLiteralBufferIndex = literalBufferIndex_; @@ -535,7 +538,8 @@ pandasm::Program *Emitter::Finalize(bool dumpDebugInfo, std::string_view globalC dumper.Dump(); } - if (context_->parserProgram->VarBinder()->IsGenStdLib()) { + if (context_->parserProgram->VarBinder()->IsGenStdLib() || + context_->parserProgram->VarBinder()->Program()->IsGenAbcForExternal()) { auto it = prog_->recordTable.find(std::string(globalClass)); if (it != prog_->recordTable.end()) { prog_->recordTable.erase(it); diff --git a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp index 15f279ea37..c5446f76e1 100644 --- a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp +++ b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp @@ -1261,7 +1261,8 @@ bool LambdaConversionPhase::PerformForModule(public_lib::Context *ctx, parser::P // For reproducibility of results when several compilation sessions are executed during // the same process's lifetime. - if (program == ctx->parserProgram) { + if (program == ctx->parserProgram && + ctx->config->options->GetCompilationMode() != CompilationMode::GEN_ABC_FOR_EXTERNAL_SOURCE) { ResetCalleeCount(); } diff --git a/ets2panda/compiler/lowering/phase.cpp b/ets2panda/compiler/lowering/phase.cpp index 6cd559f27d..dc1403b400 100644 --- a/ets2panda/compiler/lowering/phase.cpp +++ b/ets2panda/compiler/lowering/phase.cpp @@ -14,6 +14,7 @@ */ #include "phase.h" + #include "checker/checker.h" #include "compiler/lowering/checkerPhase.h" #include "compiler/lowering/ets/asyncMethodLowering.h" @@ -307,62 +308,82 @@ bool PhaseForDeclarations::Postcondition(public_lib::Context *ctx, const parser: return PostconditionForModule(ctx, program); } +// CC-OFFNXT(huge_method, huge_depth) solid logic bool PhaseForBodies::Precondition(public_lib::Context *ctx, const parser::Program *program) { - auto checkExternalPrograms = [this, ctx](const ArenaVector &programs) { - for (auto *p : programs) { - if (!Precondition(ctx, p)) { - return false; + auto cMode = ctx->config->options->GetCompilationMode(); + + auto iterateExternal = [&cMode, this](public_lib::Context *context, const parser::Program *localProgram) { + for (auto &[_, extPrograms] : localProgram->ExternalSources()) { + (void)_; + for (auto *prog : extPrograms) { + if (!prog->IsGenAbcForExternal() && cMode == CompilationMode::GEN_ABC_FOR_EXTERNAL_SOURCE) { + continue; + } + + if (!Precondition(context, prog)) { + return false; + } } } return true; }; - - if (ctx->config->options->GetCompilationMode() == CompilationMode::GEN_STD_LIB) { - for (auto &[_, extPrograms] : program->ExternalSources()) { - (void)_; - if (!checkExternalPrograms(extPrograms)) { - return false; - }; + if (cMode == CompilationMode::GEN_STD_LIB || cMode == CompilationMode::GEN_ABC_FOR_EXTERNAL_SOURCE) { + if (!iterateExternal(ctx, program)) { + return false; } } return PreconditionForModule(ctx, program); } + +// CC-OFFNXT(huge_method, huge_depth) solid logic bool PhaseForBodies::Perform(public_lib::Context *ctx, parser::Program *program) { bool result = true; - if (ctx->config->options->GetCompilationMode() == CompilationMode::GEN_STD_LIB) { - for (auto &[_, extPrograms] : program->ExternalSources()) { + auto cMode = ctx->config->options->GetCompilationMode(); + auto iterateExternal = [&result, &cMode, this](public_lib::Context *context, parser::Program *localProgram) { + for (auto &[_, extPrograms] : localProgram->ExternalSources()) { (void)_; for (auto *extProg : extPrograms) { - result &= Perform(ctx, extProg); + if (!extProg->IsGenAbcForExternal() && cMode == CompilationMode::GEN_ABC_FOR_EXTERNAL_SOURCE) { + continue; + } + result &= Perform(context, extProg); } } + }; + if (cMode == CompilationMode::GEN_STD_LIB || cMode == CompilationMode::GEN_ABC_FOR_EXTERNAL_SOURCE) { + iterateExternal(ctx, program); } result &= PerformForModule(ctx, program); return result; } +// CC-OFFNXT(huge_method, huge_depth) solid logic bool PhaseForBodies::Postcondition(public_lib::Context *ctx, const parser::Program *program) { - auto checkExternalPrograms = [this, ctx](const ArenaVector &programs) { - for (auto *p : programs) { - if (!Postcondition(ctx, p)) { - return false; + auto cMode = ctx->config->options->GetCompilationMode(); + auto iterateExternal = [&cMode, this](public_lib::Context *context, const parser::Program *localProgram) { + for (auto &[_, extPrograms] : localProgram->ExternalSources()) { + (void)_; + for (auto *prog : extPrograms) { + if (!prog->IsGenAbcForExternal() && cMode == CompilationMode::GEN_ABC_FOR_EXTERNAL_SOURCE) { + continue; + } + + if (!Postcondition(context, prog)) { + return false; + } } } return true; }; - - if (ctx->config->options->GetCompilationMode() == CompilationMode::GEN_STD_LIB) { - for (auto &[_, extPrograms] : program->ExternalSources()) { - (void)_; - if (!checkExternalPrograms(extPrograms)) { - return false; - }; + if (cMode == CompilationMode::GEN_STD_LIB || cMode == CompilationMode::GEN_ABC_FOR_EXTERNAL_SOURCE) { + if (!iterateExternal(ctx, program)) { + return false; } } diff --git a/ets2panda/compiler/scripts/signatures.yaml b/ets2panda/compiler/scripts/signatures.yaml index 496aa8e961..c72828883c 100644 --- a/ets2panda/compiler/scripts/signatures.yaml +++ b/ets2panda/compiler/scripts/signatures.yaml @@ -218,6 +218,12 @@ defines: - name: 'InterfaceObjectLiteral' ref: INTERFACE_OBJ_LITERAL comment: ETS annotation type + - name: 'ETSGLOBAL.:void;' + ref: UNUSED_ETSGLOBAL_CTOR + - name: 'ETSGLOBAL._$init$_:void;' + ref: UNUSED_ETSGLOBAL_INIT + - name: 'ETSGLOBAL.main:void;' + ref: UNUSED_ETSGLOBAL_MAIN packages: - name: 'std.core' diff --git a/ets2panda/es2panda.h b/ets2panda/es2panda.h index 21c202e405..b7e93a6cbd 100644 --- a/ets2panda/es2panda.h +++ b/ets2panda/es2panda.h @@ -61,6 +61,7 @@ enum class CompilationMode { GEN_STD_LIB, PROJECT, SINGLE_FILE, + GEN_ABC_FOR_EXTERNAL_SOURCE, }; // CC-OFFNXT(G.FUD.06) switch-case, ODR inline Language ToLanguage(ScriptExtension ext) diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index 8161f7438f..4773c5f5a2 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -187,6 +187,22 @@ ir::ETSModule *ETSParser::ParseImportsOnly(lexer::SourcePosition startLoc, Arena return etsModule; } +bool ETSParser::CheckDupAndReplace(Program *&oldProg, Program *newProg) +{ + if (!importPathManager_->ArkTSConfig()->UseUrl() && oldProg->FileName() == newProg->FileName() && + oldProg->FileNameWithExtension() != newProg->FileNameWithExtension()) { + bool oldIsDeclare = oldProg->FileNameWithExtension().Length() > newProg->FileNameWithExtension().Length(); + if (oldIsDeclare) { + Context()->dupPrograms.emplace(oldProg->AbsoluteName(), newProg); + oldProg = newProg; + } else { + Context()->dupPrograms.emplace(newProg->AbsoluteName(), oldProg); + } + return true; + } + return false; +} + void ETSParser::AddExternalSource(const std::vector &programs) { auto &extSources = globalProgram_->ExternalSources(); @@ -197,11 +213,16 @@ void ETSParser::AddExternalSource(const std::vector &programs) extSources.try_emplace(name, Allocator()->Adapter()); } bool found = false; - for (auto *prog : extSources.at(name)) { + auto &extProgs = extSources.at(name); + for (auto prog : extProgs) { if (prog->SourceFilePath() == newProg->SourceFilePath()) { found = true; break; } + if (CheckDupAndReplace(prog, newProg)) { + found = true; + break; + } } if (!found) { extSources.at(name).emplace_back(newProg); @@ -241,7 +262,7 @@ void ETSParser::AddDirectImportsToDirectExternalSources( return; } - const util::StringView name = newProg->Ast()->Statements().empty() ? newProg->FileName() : newProg->ModuleName(); + auto name = newProg->ModuleName(); if (GetProgram()->DirectExternalSources().count(name) == 0) { GetProgram()->DirectExternalSources().try_emplace(name, Allocator()->Adapter()); } @@ -263,6 +284,25 @@ void ETSParser::ParseParseListElement(const util::ImportPathManager::ParseInfo & } } +void ETSParser::AddGenExtenralSourceToParseList(public_lib::Context *ctx) +{ + auto allocator = ctx->allocator; + auto ident = allocator->New(compiler::Signatures::ETS_GLOBAL, allocator); + ArenaVector stmts(allocator->Adapter()); + auto etsModule = allocator->New(allocator, std::move(stmts), ident, ir::ModuleFlag::ETSSCRIPT, + ctx->parserProgram); + ctx->parserProgram->SetAst(etsModule); + for (auto &sourceName : ctx->sourceFileNames) { + util::ImportPathManager::ImportMetadata importData {util::ImportFlags::NONE}; + importData.resolvedSource = sourceName; + importData.lang = Language::Id::ETS; + importData.declPath = util::ImportPathManager::DUMMY_PATH; + importData.ohmUrl = util::ImportPathManager::DUMMY_PATH; + ctx->parser->AsETSParser()->GetImportPathManager()->AddToParseList(importData); + } + ctx->parser->AsETSParser()->AddExternalSource(ctx->parser->AsETSParser()->ParseSources(true)); +} + static bool SearchImportedExternalSources(ETSParser *parser, const std::string_view &path) { auto *ctx = parser->GetGlobalProgram()->VarBinder()->GetContext(); @@ -368,7 +408,13 @@ parser::Program *ETSParser::ParseSource(const SourceFile &sourceFile) ir::ETSModule *script = nullptr; if (decl != nullptr) { statements.emplace_back(decl); + if (Context()->config->options->GetCompilationMode() == CompilationMode::GEN_ABC_FOR_EXTERNAL_SOURCE) { + importPathManager_->AddImplicitPackageImportToParseList(program->SourceFile().GetAbsoluteParentFolder(), + Lexer()->GetToken().Start()); + importPathManager_->MarkAsParsed(program->AbsoluteName()); + } SavedParserContext contextAfterParseDecl(this, GetContext().Status() |= ParserStatus::IN_PACKAGE); + script = ParseETSGlobalScript(startLoc, statements); } else { script = ParseETSGlobalScript(startLoc, statements); diff --git a/ets2panda/parser/ETSparser.h b/ets2panda/parser/ETSparser.h index 6c905bafe6..bdf7fcf9b6 100644 --- a/ets2panda/parser/ETSparser.h +++ b/ets2panda/parser/ETSparser.h @@ -70,6 +70,7 @@ public: void AddDirectImportsToDirectExternalSources(const ArenaVector &directImportsFromMainSource, parser::Program *newProg) const; + bool CheckDupAndReplace(Program *&oldProg, Program *newProg); ArenaVector ParseDefaultSources(std::string_view srcFile, std::string_view importSrc); lexer::LexerPosition HandleJsDocLikeComments(); @@ -142,8 +143,10 @@ public: void AddExternalSource(const std::vector &programs); std::vector ParseSources(bool firstSource = false); + static void AddGenExtenralSourceToParseList(public_lib::Context *ctx); private: + void ParseAndSetStdlib(); NodeFormatType GetFormatPlaceholderType(); ir::Statement *ParseStatementFormatPlaceholder() override; ir::Expression *ParseExpressionFormatPlaceholder(); diff --git a/ets2panda/parser/parserImpl.h b/ets2panda/parser/parserImpl.h index d64de90591..5dfca97b41 100644 --- a/ets2panda/parser/parserImpl.h +++ b/ets2panda/parser/parserImpl.h @@ -37,6 +37,10 @@ class Options; class SourcePositionHelper; } // namespace ark::es2panda::util +namespace ark::es2panda::public_lib { +struct Context; +} + namespace ark::es2panda::parser { using ENUMBITOPS_OPERATORS; @@ -101,6 +105,16 @@ public: lexer::SourcePosition GetPositionForDiagnostic() const; + void SetContext(public_lib::Context *ctx) + { + ctx_ = ctx; + } + + public_lib::Context *Context() + { + return ctx_; + } + protected: virtual void ParseProgram(ScriptKind kind); static ExpressionParseFlags CarryExpressionParserFlag(ExpressionParseFlags origin, ExpressionParseFlags carry); @@ -569,6 +583,7 @@ private: lexer::Lexer *lexer_ {}; const util::Options *options_; util::DiagnosticEngine &diagnosticEngine_; + public_lib::Context *ctx_ {nullptr}; }; } // namespace ark::es2panda::parser diff --git a/ets2panda/parser/program/program.cpp b/ets2panda/parser/program/program.cpp index 3d6ecb19e6..fa9263c325 100644 --- a/ets2panda/parser/program/program.cpp +++ b/ets2panda/parser/program/program.cpp @@ -39,6 +39,13 @@ Program::Program(ArenaAllocator *allocator, varbinder::VarBinder *varbinder) { } +bool Program::IsGenAbcForExternal() const +{ + return VarBinder()->GetContext()->config->options->GetCompilationMode() == + CompilationMode::GEN_ABC_FOR_EXTERNAL_SOURCE && + genAbcForExternalSource_; +} + std::string Program::Dump() const { ir::AstDumper dumper {ast_, SourceCode()}; diff --git a/ets2panda/parser/program/program.h b/ets2panda/parser/program/program.h index d3e0ac67a6..7bee07ed09 100644 --- a/ets2panda/parser/program/program.h +++ b/ets2panda/parser/program/program.h @@ -42,7 +42,7 @@ class CFG; } // namespace ark::es2panda::compiler namespace ark::es2panda::parser { -enum class ScriptKind { SCRIPT, MODULE, STDLIB }; +enum class ScriptKind { SCRIPT, MODULE, STDLIB, GENEXTERNAL }; enum EntityType { CLASS_PROPERTY = 0, METHOD_DEFINITION = 1, CLASS_DEFINITION = 2, TS_INTERFACE_DECLARATION = 3 }; #ifndef NDEBUG @@ -296,6 +296,13 @@ public: (FileName().Is("etsstdlib")); } + bool IsGenAbcForExternal() const; + + void SetGenAbcForExternalSources(bool genAbc = true) + { + genAbcForExternalSource_ = genAbc; + } + varbinder::ClassScope *GlobalClassScope(); const varbinder::ClassScope *GlobalClassScope() const; @@ -379,6 +386,7 @@ private: ExternalSource externalSources_; DirectExternalSource directExternalSources_; ScriptKind kind_ {}; + bool genAbcForExternalSource_ {false}; ScriptExtension extension_ {}; ETSNolintsCollectionMap etsnolintCollection_; util::ModuleInfo moduleInfo_; diff --git a/ets2panda/public/es2panda_lib.cpp b/ets2panda/public/es2panda_lib.cpp index 68c404993f..89bc8228d6 100644 --- a/ets2panda/public/es2panda_lib.cpp +++ b/ets2panda/public/es2panda_lib.cpp @@ -294,27 +294,63 @@ static void CompileJob(public_lib::Context *context, varbinder::FunctionScope *s funcEmitter.Generate(); } -__attribute__((unused)) static es2panda_Context *CreateContext(es2panda_Config *config, std::string &&source, - const char *fileName) +static void InitializeContext(Context *res) +{ + res->phaseManager = new compiler::PhaseManager(ScriptExtension::ETS, res->allocator); + res->queue = new compiler::CompileQueue(res->config->options->GetThread()); + + auto *varbinder = res->allocator->New(res->allocator); + res->parserProgram = res->allocator->New(res->allocator, varbinder); + res->parser = new parser::ETSParser(res->parserProgram, *res->config->options, *res->diagnosticEngine, + parser::ParserStatus::NO_OPTS); + res->parser->SetContext(res); + + res->checker = res->allocator->New(*res->diagnosticEngine, res->allocator); + res->analyzer = res->allocator->New(res->checker); + res->checker->SetAnalyzer(res->analyzer); + + varbinder->SetProgram(res->parserProgram); + varbinder->SetContext(res); + res->codeGenCb = CompileJob; + res->emitter = new compiler::ETSEmitter(res); + res->program = nullptr; + res->state = ES2PANDA_STATE_NEW; +} + +static Context *InitContext(es2panda_Config *config) { auto *cfg = reinterpret_cast(config); auto *res = new Context; - res->input = std::move(source); - res->sourceFileName = fileName; - res->config = cfg; if (cfg == nullptr) { res->errorMessage = "Config is nullptr."; res->state = ES2PANDA_STATE_ERROR; - return reinterpret_cast(res); + return res; } if (cfg->options->GetExtension() != ScriptExtension::ETS) { res->errorMessage = "Invalid extension. Plugin API supports only ETS."; res->state = ES2PANDA_STATE_ERROR; + res->diagnosticEngine = cfg->diagnosticEngine; + return res; + } + + res->config = cfg; + res->diagnosticEngine = cfg->diagnosticEngine; + return res; +} + +__attribute__((unused)) static es2panda_Context *CreateContext(es2panda_Config *config, std::string &&source, + const char *fileName) +{ + auto res = InitContext(config); + if (res->state == ES2PANDA_STATE_ERROR) { return reinterpret_cast(res); } + auto *cfg = reinterpret_cast(config); + res->input = std::move(source); + res->sourceFileName = fileName; res->sourceFile = new SourceFile(res->sourceFileName, res->input, cfg->options->IsModule()); res->allocator = new ArenaAllocator(SpaceType::SPACE_TYPE_COMPILER, nullptr, true); res->queue = new compiler::CompileQueue(cfg->options->GetThread()); @@ -362,6 +398,12 @@ extern "C" __attribute__((unused)) es2panda_Context *CreateContextFromFile(es2pa return CreateContext(config, ss.str(), sourceFileName); } +extern "C" __attribute__((unused)) es2panda_Context *CreateContextFromMultiFile(es2panda_Config *config, + char const *sourceFileNames) +{ + return CreateContext(config, "", sourceFileNames); +} + extern "C" __attribute__((unused)) es2panda_Context *CreateContextFromString(es2panda_Config *config, const char *source, char const *fileName) { @@ -369,6 +411,31 @@ extern "C" __attribute__((unused)) es2panda_Context *CreateContextFromString(es2 return CreateContext(config, std::string(source), fileName); } +extern __attribute__((unused)) es2panda_Context *CreateContextGenerateAbcForExternalSourceFiles( + es2panda_Config *config, int fileNamesCount, char const *const *fileNames) +{ + auto res = InitContext(config); + if (res->state == ES2PANDA_STATE_ERROR) { + return reinterpret_cast(res); + } + auto *cfg = reinterpret_cast(config); + + ES2PANDA_ASSERT(cfg->options->IsSimultaneous()); + for (size_t i = 0; i < static_cast(fileNamesCount); ++i) { + const char *cName = *(fileNames + i); + std::string fileName(cName); + res->sourceFileNames.emplace_back(std::move(fileName)); + } + + res->input = ""; + res->sourceFileName = ""; + res->sourceFile = new SourceFile(res->sourceFileName, res->input, cfg->options->IsModule()); + res->allocator = new ArenaAllocator(SpaceType::SPACE_TYPE_COMPILER, nullptr, true); + + InitializeContext(res); + return reinterpret_cast(res); +} + __attribute__((unused)) static Context *Parse(Context *ctx) { if (ctx->state != ES2PANDA_STATE_NEW) { @@ -377,13 +444,34 @@ __attribute__((unused)) static Context *Parse(Context *ctx) return ctx; } - ctx->phaseManager->Restart(); - ctx->parser->ParseScript(*ctx->sourceFile, - ctx->config->options->GetCompilationMode() == CompilationMode::GEN_STD_LIB); + if (ctx->config->options->IsSimultaneous()) { + parser::ETSParser::AddGenExtenralSourceToParseList(ctx); + std::unordered_set sourceFileNamesSet(ctx->sourceFileNames.begin(), ctx->sourceFileNames.end()); + ctx->MarkGenAbcForExternal(sourceFileNamesSet, ctx->parserProgram->ExternalSources()); + } else { + ctx->parser->ParseScript(*ctx->sourceFile, + ctx->config->options->GetCompilationMode() == CompilationMode::GEN_STD_LIB); + } ctx->state = ES2PANDA_STATE_PARSED; return ctx; } +__attribute__((unused)) static bool SetProgramGenAbc(Context *ctx, const char *path) +{ + util::StringView pathView(path); + public_lib::Context *context = reinterpret_cast(ctx); + for (auto &[_, extPrograms] : context->externalSources) { + (void)_; + for (auto *prog : extPrograms) { + if (prog->AbsoluteName() == pathView) { + prog->SetGenAbcForExternalSources(); + return true; + } + } + } + return false; +} + __attribute__((unused)) static Context *Bind(Context *ctx) { if (ctx->state < ES2PANDA_STATE_PARSED) { @@ -1050,6 +1138,7 @@ es2panda_Impl g_impl = { ConfigGetOptions, CreateContextFromFile, CreateContextFromString, + CreateContextGenerateAbcForExternalSourceFiles, ProceedToState, DestroyContext, ContextState, diff --git a/ets2panda/public/es2panda_lib.h b/ets2panda/public/es2panda_lib.h index b331f56829..2d0a01d930 100644 --- a/ets2panda/public/es2panda_lib.h +++ b/ets2panda/public/es2panda_lib.h @@ -181,6 +181,8 @@ struct CAPI_EXPORT es2panda_Impl { es2panda_Context *(*CreateContextFromFile)(es2panda_Config *config, char const *source_file_name); es2panda_Context *(*CreateContextFromString)(es2panda_Config *config, const char *source, char const *file_name); + es2panda_Context *(*CreateContextGenerateAbcForExternalSourceFiles)(es2panda_Config *config, int fileNamesCount, + char const *const *fileNames); es2panda_Context *(*ProceedToState)(es2panda_Context *context, es2panda_ContextState state); // context is consumed void (*DestroyContext)(es2panda_Context *context); diff --git a/ets2panda/public/es2panda_lib.idl.erb b/ets2panda/public/es2panda_lib.idl.erb index c884938c36..8d97227462 100644 --- a/ets2panda/public/es2panda_lib.idl.erb +++ b/ets2panda/public/es2panda_lib.idl.erb @@ -172,6 +172,7 @@ interface es2panda_Impl { es2panda_Context CreateContextFromFile(es2panda_Config config, String source_file_name); es2panda_Context CreateContextFromString(es2panda_Config config, String source, String file_name); + es2panda_Context CreateContextGenerateAbcForExternalSourceFiles(es2panda_Config config, i32 fileNamesCount, sequence fileNames); es2panda_Context ProceedToState(es2panda_Context context, es2panda_ContextState state); // context is consumed void DestroyContext(es2panda_Context context); diff --git a/ets2panda/public/public.h b/ets2panda/public/public.h index fdb18d9ca6..06b83daa5d 100644 --- a/ets2panda/public/public.h +++ b/ets2panda/public/public.h @@ -51,8 +51,9 @@ struct ConfigImpl { std::list diagnosticKindStorage; }; -using ExternalSources = std::unordered_map>; +using ExternalSources = std::unordered_map>; +using ExternalSource = ArenaUnorderedMap>; using ComputedAbstracts = ArenaUnorderedMap, ArenaUnorderedSet>>; @@ -160,6 +161,36 @@ struct Context { return util::NodeAllocator::ForceSetParent(Allocator(), std::forward(args)...); } + void MarkGenAbcForExternal(std::unordered_set &genAbcList, public_lib::ExternalSource &extSources) + { + size_t genCount = 0; + std::unordered_set genAbcListAbsolute; + + for (auto &path : genAbcList) { + genAbcListAbsolute.insert(os::GetAbsolutePath(path)); + } + for (auto &[_, extPrograms] : extSources) { + (void)_; + bool setFlag = false; + for (auto *prog : extPrograms) { + if (auto it = genAbcListAbsolute.find(prog->AbsoluteName().Mutf8()); it != genAbcListAbsolute.end()) { + ++genCount; + setFlag = true; + } + } + if (!setFlag) { + continue; + } + for (auto *prog : extPrograms) { + prog->SetGenAbcForExternalSources(); + } + } + + if (genCount != genAbcListAbsolute.size()) { + diagnosticEngine->LogFatalError(diagnostic::SIMULTANEOUSLY_MARK_FAILED.Message()); + } + } + ConfigImpl *config = nullptr; std::string sourceFileName; std::string input; @@ -188,6 +219,8 @@ struct Context { CompilingState compilingState {CompilingState::NONE_COMPILING}; ExternalSources externalSources; TransitionMemory *transitionMemory {nullptr}; + std::vector sourceFileNames; + std::map dupPrograms {}; // NOLINTEND(misc-non-private-member-variables-in-classes) }; } // namespace ark::es2panda::public_lib diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_export_A_1.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_A_1.ets new file mode 100644 index 0000000000..6780a05eb1 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_A_1.ets @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 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. + */ + +export class A{} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_export_A_2.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_A_2.ets new file mode 100644 index 0000000000..a12a108de3 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_A_2.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 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. + */ + +class A{} + +export A; \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_export_B_1.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_B_1.ets new file mode 100644 index 0000000000..e94062d246 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_B_1.ets @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 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. + */ + +export class B{} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_export_B_as_A_1.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_B_as_A_1.ets new file mode 100644 index 0000000000..2e2d5ca5aa --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_B_as_A_1.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 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. + */ + +class B{} + +export {B as A} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_export_default_A_1.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_default_A_1.ets new file mode 100644 index 0000000000..e7d776f8ed --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_default_A_1.ets @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 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. + */ + +export default class A{} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_export_default_A_2.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_default_A_2.ets new file mode 100644 index 0000000000..e3948e3dfb --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_default_A_2.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 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. + */ + +class A{} + +export default A; \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_export_default_B_1.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_default_B_1.ets new file mode 100644 index 0000000000..c3d22a7b65 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_default_B_1.ets @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 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. + */ + +export default class B{} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_export_default_B_2.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_default_B_2.ets new file mode 100644 index 0000000000..85a9380fbf --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_default_B_2.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 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. + */ + +class B{} + +export default B; \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_export_default_import_default_A_1.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_default_import_default_A_1.ets new file mode 100644 index 0000000000..8ed966ae30 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_default_import_default_A_1.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 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. + */ + +import A from "./eitest_export_default_A_1" + +export default A \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_export_import_A_1.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_import_A_1.ets new file mode 100644 index 0000000000..472711f075 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_import_A_1.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 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. + */ + +import {A} from "./eitest_export_A_1" + +export A \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_export_import_A_2.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_import_A_2.ets new file mode 100644 index 0000000000..b815742961 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_import_A_2.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 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. + */ + +import {B} from "./eitest_export_B_1" + +export {B as A} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_export_import_A_3.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_import_A_3.ets new file mode 100644 index 0000000000..9d1da0fa43 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_import_A_3.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 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. + */ + +import {A as B} from "./eitest_export_A_1" + +export {B as A} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_export_import_default_A_1.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_import_default_A_1.ets new file mode 100644 index 0000000000..b30c26cbbe --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_import_default_A_1.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 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. + */ + +import A from "./eitest_export_default_A_1" + +export A \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_export_import_default_A_B_1.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_import_default_A_B_1.ets new file mode 100644 index 0000000000..6fccdc60da --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_import_default_A_B_1.ets @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2025 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. + */ + +import A from "./eitest_export_default_A_1" +import B from "./eitest_export_default_B_1" + +export {A,B} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_export_type_A_1.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_type_A_1.ets new file mode 100644 index 0000000000..efebe3f5c0 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_export_type_A_1.ets @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2025 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. + */ + + +export class A {} + +export default type CLASS_A = A; \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_1.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_1.ets new file mode 100644 index 0000000000..16412b6e62 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_1.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 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. + */ + +import {A} from "./eitest_export_A_1" + +function main(){ + let a :A = new A() +} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_1_ne.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_1_ne.ets new file mode 100644 index 0000000000..3fed30fb92 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_1_ne.ets @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 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. + */ + +import A from "./eitest_export_A_1" + +function main(){ + let a :A = new A() +} + +/* @@? 16:15 Error TypeError: Cannot find default imported element in the target */ +/* @@? 19:12 Error TypeError: Cannot find type 'A'. */ +/* @@? 19:20 Error TypeError: Cannot find type 'A'. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_2.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_2.ets new file mode 100644 index 0000000000..4eb9ea3c1e --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_2.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 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. + */ + +import {A} from "./eitest_export_A_2" + +function main(){ + let a :A = new A() +} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_2_ne.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_2_ne.ets new file mode 100644 index 0000000000..a1da533413 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_2_ne.ets @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 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. + */ + +import A from "./eitest_export_A_2" + +function main(){ + let a :A = new A() +} + +/* @@? 16:15 Error TypeError: Cannot find default imported element in the target */ +/* @@? 19:12 Error TypeError: Cannot find type 'A'. */ +/* @@? 19:20 Error TypeError: Cannot find type 'A'. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_3.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_3.ets new file mode 100644 index 0000000000..d17ac7f13b --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_3.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 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. + */ + +import {A} from "./eitest_export_B_as_A_1" + +function main(){ + let a :A = new A() +} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_3_ne.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_3_ne.ets new file mode 100644 index 0000000000..5b0fa10162 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_3_ne.ets @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 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. + */ + +import A from "./eitest_export_B_as_A_1" + +function main(){ + let a :A = new A() +} + +/* @@? 16:15 Error TypeError: Cannot find default imported element in the target */ +/* @@? 19:12 Error TypeError: Cannot find type 'A'. */ +/* @@? 19:20 Error TypeError: Cannot find type 'A'. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_4.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_4.ets new file mode 100644 index 0000000000..48563cfcfb --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_4.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 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. + */ + +import {A} from "./eitest_export_import_A_1" + +function main(){ + let a :A = new A() +} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_4_ne.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_4_ne.ets new file mode 100644 index 0000000000..aa8c172b1f --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_4_ne.ets @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 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. + */ + +import A from "./eitest_export_import_A_1" + +function main(){ + let a :A = new A() +} + +/* @@? 16:15 Error TypeError: Cannot find default imported element in the target */ +/* @@? 19:12 Error TypeError: Cannot find type 'A'. */ +/* @@? 19:20 Error TypeError: Cannot find type 'A'. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_5.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_5.ets new file mode 100644 index 0000000000..036f643c19 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_5.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 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. + */ + +import {A} from "./eitest_export_import_A_2" + +function main(){ + let a :A = new A() +} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_5_ne.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_5_ne.ets new file mode 100644 index 0000000000..38e266873e --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_5_ne.ets @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 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. + */ + +import A from "./eitest_export_import_A_2" + +function main(){ + let a :A = new A() +} + +/* @@? 16:15 Error TypeError: Cannot find default imported element in the target */ +/* @@? 19:12 Error TypeError: Cannot find type 'A'. */ +/* @@? 19:20 Error TypeError: Cannot find type 'A'. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_6.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_6.ets new file mode 100644 index 0000000000..2ad8f1ce31 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_6.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 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. + */ + +import {A} from "./eitest_export_import_A_3" + +function main(){ + let a :A = new A() +} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_6_ne.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_6_ne.ets new file mode 100644 index 0000000000..06251d9939 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_6_ne.ets @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 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. + */ + +import A from "./eitest_export_import_A_3" + +function main(){ + let a :A = new A() +} + +/* @@? 16:15 Error TypeError: Cannot find default imported element in the target */ +/* @@? 19:12 Error TypeError: Cannot find type 'A'. */ +/* @@? 19:20 Error TypeError: Cannot find type 'A'. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_7.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_7.ets new file mode 100644 index 0000000000..43b3cbfb6e --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_7.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 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. + */ + +import {A} from "./eitest_export_import_default_A_1" + +function main(){ + let a :A = new A() +} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_7_ne.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_7_ne.ets new file mode 100644 index 0000000000..2aa03a66a4 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_7_ne.ets @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 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. + */ + +import A from "./eitest_export_import_default_A_1" + +function main(){ + let a :A = new A() +} + +/* @@? 16:15 Error TypeError: Cannot find default imported element in the target */ +/* @@? 19:12 Error TypeError: Cannot find type 'A'. */ +/* @@? 19:20 Error TypeError: Cannot find type 'A'. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_B_1.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_B_1.ets new file mode 100644 index 0000000000..ad032143e5 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_B_1.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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. + */ + +import {A,B} from "./eitest_export_import_default_A_B_1" + +function main(){ + let a :A = new A() + let b :B = new B() +} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_B_1_ne.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_B_1_ne.ets new file mode 100644 index 0000000000..259a491d0a --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_A_B_1_ne.ets @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 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. + */ + +import A from "./eitest_export_import_default_A_B_1" + +function main(){ + let a :A = new A() +} + +/* @@? 16:15 Error TypeError: Cannot find default imported element in the target */ +/* @@? 19:12 Error TypeError: Cannot find type 'A'. */ +/* @@? 19:20 Error TypeError: Cannot find type 'A'. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_import_default_A_1.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_default_A_1.ets new file mode 100644 index 0000000000..5fa1751e6b --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_default_A_1.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 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. + */ + +import A from "./eitest_export_default_A_1" + +function main(){ + let a :A = new A() +} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_import_default_A_1_ne.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_default_A_1_ne.ets new file mode 100644 index 0000000000..da65463362 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_default_A_1_ne.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 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. + */ + +import {A} from "./eitest_export_default_A_1" + +function main(){ + let a :A = new A() +} + +/* @@? 16:17 Error TypeError: Use the default import syntax to import a default exported element */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_import_default_A_2.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_default_A_2.ets new file mode 100644 index 0000000000..47bcf30f29 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_default_A_2.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 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. + */ + +import B from "./eitest_export_default_A_2" + +function main(){ + let a :B = new B() +} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_import_default_A_2_ne.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_default_A_2_ne.ets new file mode 100644 index 0000000000..6758e4fdde --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_default_A_2_ne.ets @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 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. + */ + +import {B} from "./eitest_export_default_A_2" + +function main(){ + let a :B = new B() +} + +/* @@? 16:17 Error TypeError: Cannot find imported element 'B' */ +/* @@? 19:12 Error TypeError: Cannot find type 'B'. */ +/* @@? 19:20 Error TypeError: Cannot find type 'B'. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_import_default_A_3.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_default_A_3.ets new file mode 100644 index 0000000000..988105af2c --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_default_A_3.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 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. + */ + +import A from "./eitest_export_default_import_default_A_1" + +function main(){ + let a :A = new A() +} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_import_default_A_3_ne.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_default_A_3_ne.ets new file mode 100644 index 0000000000..95df0589cc --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_default_A_3_ne.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 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. + */ + +import {A} from "./eitest_export_default_import_default_A_1" + +function main(){ + let a :A = new A() +} + +/* @@? 16:17 Error TypeError: Use the default import syntax to import a default exported element */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_import_type_A_1.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_type_A_1.ets new file mode 100644 index 0000000000..2de45482ea --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_type_A_1.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 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. + */ + +import CLASS_A from "./eitest_export_type_A_1" + +function main(){ + let a :CLASS_A = new CLASS_A() +} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/eitest_import_type_A_1_ne.ets b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_type_A_1_ne.ets new file mode 100644 index 0000000000..a5e1725a38 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/eitest_import_type_A_1_ne.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 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. + */ + +import {CLASS_A} from "./eitest_export_type_A_1" + +function main(){ + let a :CLASS_A = new CLASS_A() +} + +/* @@? 16:23 Error TypeError: Use the default import syntax to import a default exported element */ diff --git a/ets2panda/test/ast/compiler/ets/import_export/external_export.ets b/ets2panda/test/ast/compiler/ets/import_export/external_export.ets new file mode 100644 index 0000000000..01ac01d4e9 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/external_export.ets @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 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. + */ + +import {TT} from "./test1_1" diff --git a/ets2panda/test/ast/compiler/ets/import_export/test1_1.ets b/ets2panda/test/ast/compiler/ets/import_export/test1_1.ets new file mode 100644 index 0000000000..1fb57059d7 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/test1_1.ets @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 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. + */ + +import VAR_t from "./test2_1" +export class TT{} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/test2_1.ets b/ets2panda/test/ast/compiler/ets/import_export/test2_1.ets new file mode 100644 index 0000000000..bcfbd1fa61 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/test2_1.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 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. + */ + +import {VAR_i as VAR_o} from "./test3_1" +export default VAR_o +export type VAR_j = string; \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/import_export/test3_1.ets b/ets2panda/test/ast/compiler/ets/import_export/test3_1.ets new file mode 100644 index 0000000000..7ce9d1c5be --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/import_export/test3_1.ets @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 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. + */ + +export {VAR_j as VAR_xj} from "./test2_1" +export type VAR_i = int; \ No newline at end of file diff --git a/ets2panda/test/isolated_declgen/isolated_interface-expected.txt b/ets2panda/test/isolated_declgen/isolated_interface-expected.txt index 029658ebdd..430bc34f65 100644 --- a/ets2panda/test/isolated_declgen/isolated_interface-expected.txt +++ b/ets2panda/test/isolated_declgen/isolated_interface-expected.txt @@ -33,4 +33,4 @@ export declare interface Animal { get name(): String; makeSound(): void; -} \ No newline at end of file +} diff --git a/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt b/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt index cff206ab65..93f5508e79 100644 --- a/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt +++ b/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt @@ -192,3 +192,32 @@ runtime/ets/implicit_stringliteral_init.ets # #21051 should be log warnings, but there aren't ast/compiler/ets/not_initialized_variable/import_types.ets + +#Issue 22182 +ast/compiler/ets/implicit_package_import/package_test_5/package_module_1.sts + +#import tests, not test cases(path problem) +ast/compiler/ets/import_export/test1_1.ets +ast/compiler/ets/import_export/test1_1.ets +ast/compiler/ets/import_export/eitest_export_default_import_default_A_1.ets +ast/compiler/ets/import_export/eitest_export_import_A_1.ets +ast/compiler/ets/import_export/eitest_export_import_A_2.ets +ast/compiler/ets/import_export/eitest_export_import_A_3.ets +ast/compiler/ets/import_export/eitest_export_import_default_A_1.ets +ast/compiler/ets/import_export/eitest_export_import_default_A_B_1.ets +ast/compiler/ets/import_export/eitest_import_A_1.ets +ast/compiler/ets/import_export/eitest_import_A_2.ets +ast/compiler/ets/import_export/eitest_import_A_3.ets +ast/compiler/ets/import_export/eitest_import_A_4.ets +ast/compiler/ets/import_export/eitest_import_A_5.ets +ast/compiler/ets/import_export/eitest_import_A_6.ets +ast/compiler/ets/import_export/eitest_import_A_7.ets +ast/compiler/ets/import_export/eitest_import_A_B_1.ets +ast/compiler/ets/import_export/eitest_import_default_A_1.ets +ast/compiler/ets/import_export/eitest_import_default_A_2.ets +ast/compiler/ets/import_export/eitest_import_default_A_3.ets +ast/compiler/ets/import_export/eitest_import_type_A_1.ets +ast/compiler/ets/import_export/external_export.ets +ast/compiler/ets/import_export/test1_1.ets +ast/compiler/ets/import_export/test2_1.ets +ast/compiler/ets/import_export/test3_1.ets \ No newline at end of file diff --git a/ets2panda/util/diagnostic/fatal.yaml b/ets2panda/util/diagnostic/fatal.yaml index 0bc08c8af6..5cd4141733 100644 --- a/ets2panda/util/diagnostic/fatal.yaml +++ b/ets2panda/util/diagnostic/fatal.yaml @@ -111,3 +111,7 @@ fatal: - name: MISSING_OUTPUT_FILE id: 25 message: "Output file path must be specified." + +- name: SIMULTANEOUSLY_MARK_FAILED + id: 26 + message: "simultaneously compile is not work because of input file paths error." diff --git a/ets2panda/util/importPathManager.cpp b/ets2panda/util/importPathManager.cpp index 7cf0466927..e6d8a1e8b1 100644 --- a/ets2panda/util/importPathManager.cpp +++ b/ets2panda/util/importPathManager.cpp @@ -262,7 +262,7 @@ void ImportPathManager::AddToParseList(const ImportMetadata importMetadata) // surely re-parse it. // // If a file was already not implicitly package imported, then it's just a duplicate, return - if (!found->importData.IsImplicitPackageImported()) { + if (!found->importData.IsImplicitPackageImported() || importMetadata.IsImplicitPackageImported()) { return; } diff --git a/ets2panda/util/importPathManager.h b/ets2panda/util/importPathManager.h index 21095663b0..948b315850 100644 --- a/ets2panda/util/importPathManager.h +++ b/ets2panda/util/importPathManager.h @@ -140,6 +140,12 @@ public: void MarkAsParsed(StringView path); util::StringView FormRelativePath(const util::Path &path); + std::shared_ptr ArkTSConfig() const + { + return arktsConfig_; + } + + void AddToParseList(const ImportMetadata importMetadata); private: util::StringView FormModuleNameSolelyByAbsolutePath(const util::Path &path); @@ -161,7 +167,6 @@ private: std::string TryMatchDynamicPath(std::string_view fixedPath) const; StringView GetRealPath(StringView path) const; - void AddToParseList(const ImportMetadata importMetadata); #ifdef USE_UNIX_SYSCALL void UnixWalkThroughDirectoryAndAddToParseList(ImportMetadata importMetadata); #endif diff --git a/ets2panda/util/options.cpp b/ets2panda/util/options.cpp index 9f42bc27ab..699c636e5b 100644 --- a/ets2panda/util/options.cpp +++ b/ets2panda/util/options.cpp @@ -168,7 +168,7 @@ bool Options::ParseInputOutput() return false; } - if (compilationMode_ == CompilationMode::SINGLE_FILE) { + if (compilationMode_ == CompilationMode::SINGLE_FILE || GetExtension() != ScriptExtension::ETS) { std::ifstream inputStream(SourceFileName()); if (inputStream.fail()) { diagnosticEngine_.LogDiagnostic(diagnostic::OPEN_FAILED, @@ -222,10 +222,10 @@ bool Options::Parse(Span args) #endif DetermineCompilationMode(); - if (!ParseInputOutput()) { + if (!DetermineExtension()) { return false; } - if (!DetermineExtension()) { + if (!ParseInputOutput()) { return false; } if (extension_ != ScriptExtension::JS && IsModule()) { diff --git a/ets2panda/util/options.h b/ets2panda/util/options.h index 47e693e74c..f7bf991b9c 100644 --- a/ets2panda/util/options.h +++ b/ets2panda/util/options.h @@ -77,6 +77,7 @@ public: void DetermineCompilationMode() { compilationMode_ = IsGenStdlib() ? CompilationMode::GEN_STD_LIB + : IsSimultaneous() ? CompilationMode::GEN_ABC_FOR_EXTERNAL_SOURCE : inputFile_.WasSet() ? CompilationMode::SINGLE_FILE : CompilationMode::PROJECT; } diff --git a/ets2panda/util/options.yaml b/ets2panda/util/options.yaml index 3dab3459f6..94eda0b128 100644 --- a/ets2panda/util/options.yaml +++ b/ets2panda/util/options.yaml @@ -378,3 +378,8 @@ options: type: bool default: true description: Place AST trees in permanent arena + +- name: simultaneous + type: bool + default: false + description: compile all the files to abc in once. diff --git a/ets2panda/varbinder/ETSBinder.cpp b/ets2panda/varbinder/ETSBinder.cpp index 0f9ae6db10..38e6ab7b42 100644 --- a/ets2panda/varbinder/ETSBinder.cpp +++ b/ets2panda/varbinder/ETSBinder.cpp @@ -388,6 +388,11 @@ void ETSBinder::BuildInterfaceDeclaration(ir::TSInterfaceDeclaration *decl) void ETSBinder::BuildMethodDefinition(ir::MethodDefinition *methodDef) { + if (methodDef->BaseOverloadMethod() != nullptr && + methodDef->GetTopStatement()->AsETSModule()->Program() != Program() && + methodDef->BaseOverloadMethod()->GetTopStatement() != methodDef->GetTopStatement()) { + return; + } if (methodDef->Function()->TypeParams() != nullptr) { auto scopeCtx = LexicalScope::Enter(this, methodDef->Function()->TypeParams()->Scope()); ResolveReferences(methodDef->Function()->TypeParams()); @@ -785,11 +790,96 @@ static bool IsExportedVariable(varbinder::Variable *const var) (var->Declaration()->Node()->IsExported() || var->Declaration()->Node()->IsDefaultExported()); } -ir::ETSImportDeclaration *ETSBinder::FindImportDeclInReExports(const ir::ETSImportDeclaration *const import, - const util::StringView &imported, - const ir::StringLiteral *const importPath) +std::pair ETSBinder::FindImportDeclInExports( + const ir::ETSImportDeclaration *const import, const util::StringView &imported, + const ir::StringLiteral *const importPath) +{ + ir::ETSImportDeclaration *implDecl = nullptr; + ir::AstNode *specifier = nullptr; + std::tie(implDecl, specifier) = FindImportDeclInReExports(import, imported, importPath); + if (implDecl != nullptr) { + return std::make_pair(implDecl, specifier); + } + std::tie(implDecl, specifier) = FindImportDeclInNamedExports(import, imported, importPath); + return std::make_pair(implDecl, specifier); +} + +static std::pair FindImportDeclInProgram(parser::Program *program, + const util::StringView &imported) +{ + for (auto stmt : program->Ast()->AsETSModule()->Statements()) { + if (!stmt->IsETSImportDeclaration()) { + continue; + } + for (auto specifier : stmt->AsETSImportDeclaration()->Specifiers()) { + if (specifier->IsImportSpecifier() && specifier->AsImportSpecifier()->Local()->Name() == imported) { + return std::make_pair(stmt->AsETSImportDeclaration(), specifier); + } + if (specifier->IsImportDefaultSpecifier() && + specifier->AsImportDefaultSpecifier()->Local()->Name() == imported) { + return std::make_pair(stmt->AsETSImportDeclaration(), specifier); + } + } + } + return std::make_pair(nullptr, nullptr); +} + +std::pair ETSBinder::FindImportDeclInNamedExports( + const ir::ETSImportDeclaration *const import, [[maybe_unused]] const util::StringView &imported, + const ir::StringLiteral *const importPath) +{ + auto importMapIter = selectiveExportAliasMultimap_.find(import->ImportMetadata().resolvedSource); + if (importMapIter == selectiveExportAliasMultimap_.end()) { + return std::make_pair(nullptr, nullptr); + } + auto pairIter = importMapIter->second.find(imported); + if (pairIter == importMapIter->second.end()) { + return std::make_pair(nullptr, nullptr); + } + auto [localName, declNode] = pairIter->second; + const auto records = GetExternalProgram(import->ImportMetadata().resolvedSource, importPath); + if (records.empty()) { + return std::make_pair(nullptr, nullptr); + } + auto currProgram = records[0]; + if (currProgram == nullptr) { + return std::make_pair(nullptr, nullptr); + } + auto [newImportDecl, specfier] = FindImportDeclInProgram(currProgram, localName); + if (newImportDecl == nullptr) { + return std::make_pair(nullptr, nullptr); + } + return std::make_pair(newImportDecl->AsETSImportDeclaration(), specfier); +} + +static ir::AstNode *GetSpecifier(const util::StringView &importedLocal, ir::ETSImportDeclaration *decl) +{ + for (auto localSpecfier : decl->Specifiers()) { + util::StringView name; + if (localSpecfier->IsImportSpecifier()) { + name = localSpecfier->AsImportSpecifier()->Local()->Name(); + } else if (localSpecfier->IsImportNamespaceSpecifier()) { + name = localSpecfier->AsImportNamespaceSpecifier()->Local()->Name(); + } else { + name = localSpecfier->AsImportDefaultSpecifier()->Local()->Name(); + } + if (name == importedLocal) { + return localSpecfier; + } + } + if (decl->Specifiers().size() == 1 && decl->Specifiers()[0]->IsImportNamespaceSpecifier()) { + return decl->Specifiers()[0]; + } + ES2PANDA_UNREACHABLE(); +}; + +std::pair ETSBinder::FindImportDeclInReExports( + const ir::ETSImportDeclaration *const import, const util::StringView &imported, + const ir::StringLiteral *const importPath) { ir::ETSImportDeclaration *implDecl = nullptr; + ir::AstNode *specifier = nullptr; + for (auto item : ReExportImports()) { if (!ReexportPathMatchesImportPath(item, import)) { continue; @@ -803,6 +893,7 @@ ir::ETSImportDeclaration *ETSBinder::FindImportDeclInReExports(const ir::ETSImpo continue; } implDecl = item->GetETSImportDeclarations(); + specifier = GetSpecifier(imported, implDecl); } else { const auto records = GetExternalProgram(item->GetETSImportDeclarations()->ResolvedSource(), importPath); if (records.empty()) { @@ -812,17 +903,20 @@ ir::ETSImportDeclaration *ETSBinder::FindImportDeclInReExports(const ir::ETSImpo FindImportSpecifiersVariable(imported, records[0]->GlobalScope()->Bindings(), Span {records}); if (IsExportedVariable(var)) { implDecl = item->GetETSImportDeclarations(); + specifier = GetSpecifier(imported, implDecl); continue; } auto reExportImport = item->GetETSImportDeclarations(); auto reExportImportPath = reExportImport->Source(); - auto implDeclOrNullptr = FindImportDeclInReExports(reExportImport, imported, reExportImportPath); + auto [implDeclOrNullptr, localSpecifier] = + FindImportDeclInExports(reExportImport, imported, reExportImportPath); if (implDeclOrNullptr != nullptr) { implDecl = implDeclOrNullptr; + specifier = GetSpecifier(imported, implDecl); } } } - return implDecl; + return std::make_pair(implDecl, specifier); } void ETSBinder::ValidateImportVariable(const ir::AstNode *node, const util::StringView &imported, @@ -856,6 +950,46 @@ bool ETSBinder::DetectNameConflict(const util::StringView localName, Variable *c return true; } +Variable *ETSBinder::AddImportSpecifierFromReExport(ir::AstNode *importSpecifier, + const ir::ETSImportDeclaration *const import, + const util::StringView &imported, + const ir::StringLiteral *const importPath) +{ + auto [implDecl, localSpecifier] = FindImportDeclInExports(import, imported, importPath); + Variable *localVar = nullptr; + auto insertBinding = [this, importSpecifier, import](Variable *var) { + if (importSpecifier->IsImportSpecifier()) { + this->InsertOrAssignForeignBinding(importSpecifier, import, + importSpecifier->AsImportSpecifier()->Local()->Name(), var); + importSpecifier->AsImportSpecifier()->Local()->SetVariable(var); + importSpecifier->AsImportSpecifier()->Imported()->SetVariable(var); + } else if (importSpecifier->IsImportDefaultSpecifier()) { + this->InsertOrAssignForeignBinding(importSpecifier, import, + importSpecifier->AsImportDefaultSpecifier()->Local()->Name(), var); + importSpecifier->AsImportDefaultSpecifier()->Local()->SetVariable(var); + } + }; + if (implDecl != nullptr) { + if (localSpecifier->IsImportSpecifier() || localSpecifier->IsImportDefaultSpecifier()) { + AddSpecifiersToTopBindings(localSpecifier, implDecl); + if (localSpecifier->IsImportSpecifier()) { + localVar = localSpecifier->AsImportSpecifier()->Imported()->Variable(); + insertBinding(localVar); + } else if (localSpecifier->IsImportDefaultSpecifier()) { + localVar = localSpecifier->AsImportDefaultSpecifier()->Local()->Variable(); + insertBinding(localVar); + } + } else { + AddSpecifiersToTopBindings(importSpecifier, implDecl); + } + + return localVar; + } + + ThrowError(importPath->Start(), diagnostic::IMPORT_NOT_FOUND, {imported}); + return nullptr; +} + // CC-OFFNXT(huge_method, G.FUN.01-CPP) solid logic bool ETSBinder::AddImportSpecifiersToTopBindings(Span records, ir::ImportSpecifier *const importSpecifier, @@ -882,18 +1016,14 @@ bool ETSBinder::AddImportSpecifiersToTopBindings(Span re nameToSearchFor = imported; } - auto *const var = FindImportSpecifiersVariable(nameToSearchFor, globalBindings, records); + auto *var = FindImportSpecifiersVariable(nameToSearchFor, globalBindings, records); importSpecifier->Imported()->SetVariable(var); importSpecifier->Local()->SetVariable(var); if (var == nullptr) { - ir::ETSImportDeclaration *implDecl = FindImportDeclInReExports(import, imported, importPath); - if (implDecl != nullptr) { - AddSpecifiersToTopBindings(importSpecifier, implDecl); - return true; - } - - ThrowError(importPath->Start(), diagnostic::IMPORT_NOT_FOUND, {imported}); + var = AddImportSpecifierFromReExport(importSpecifier, import, imported, importPath); + } + if (var == nullptr) { return false; } @@ -938,9 +1068,15 @@ void ETSBinder::AddImportDefaultSpecifiersToTopBindings(Spansecond.begin(), selectMap2->second.end(), isDefaultExpored); if (item1 != selectMap2->second.end()) { - auto item2 = FindImportSpecifiersVariable(item1->first, globalBindings, records); - importDefaultSpecifier->Local()->SetVariable(item2); - InsertForeignBinding(importDefaultSpecifier, import, importDefaultSpecifier->Local()->Name(), item2); + auto var = FindImportSpecifiersVariable(item1->first, globalBindings, records); + if (var == nullptr) { + var = AddImportSpecifierFromReExport(importDefaultSpecifier, import, item1->first, import->Source()); + } + if (var == nullptr) { + return; + } + importDefaultSpecifier->Local()->SetVariable(var); + InsertOrAssignForeignBinding(importDefaultSpecifier, import, importDefaultSpecifier->Local()->Name(), var); return; } } @@ -1192,12 +1328,21 @@ void ETSBinder::InitImplicitThisParam() void ETSBinder::BuildProgram() { + // A tmp solution caused by #23877, needs to check stdlib first to avoid a bug in std/math/math.ets + // After the bug fixed, we can merge these 2 loop. + static const std::string STD_SUFFIX = "std."; + for (auto &[_, extPrograms] : Program()->ExternalSources()) { + if (_.Utf8().substr(0, STD_SUFFIX.length()) == STD_SUFFIX) { + for (auto *extProg : extPrograms) { + BuildExternalProgram(extProg); + } + } + } for (auto &[_, extPrograms] : Program()->ExternalSources()) { (void)_; - for (auto *extProg : extPrograms) { - if (!extProg->GetFlag(parser::ProgramFlags::AST_IDENTIFIER_ANALYZED)) { + if (_.Utf8().substr(0, STD_SUFFIX.length()) != STD_SUFFIX) { + for (auto *extProg : extPrograms) { BuildExternalProgram(extProg); - extProg->SetFlag(parser::ProgramFlags::AST_IDENTIFIER_ANALYZED); } } } @@ -1232,7 +1377,9 @@ void ETSBinder::BuildExternalProgram(parser::Program *extProgram) auto *savedRecordTable = recordTable_; auto *savedTopScope = TopScope(); - auto flags = Program()->VarBinder()->IsGenStdLib() ? RecordTableFlags::NONE : RecordTableFlags::EXTERNAL; + auto flags = Program()->VarBinder()->IsGenStdLib() || (extProgram->IsGenAbcForExternal()) + ? RecordTableFlags::NONE + : RecordTableFlags::EXTERNAL; auto *extRecordTable = Allocator()->New(Allocator(), extProgram, flags); externalRecordTable_.insert({extProgram, extRecordTable}); @@ -1301,7 +1448,7 @@ Variable *ETSBinder::ValidateImportSpecifier(const ir::ImportSpecifier *const sp } // Failed to find variable, go through reexports - const ir::ETSImportDeclaration *const implDecl = FindImportDeclInReExports(import, imported, import->Source()); + auto [implDecl, localSpecifier] = FindImportDeclInExports(import, imported, import->Source()); if (implDecl != nullptr) { return ValidateImportSpecifier(specifier, implDecl); } @@ -1427,24 +1574,28 @@ const DynamicImportData *ETSBinder::DynamicImportDataForVar(const Variable *var) return &it->second; } -ArenaVector ETSBinder::GetProgramList(const util::StringView &path) const noexcept +ArenaVector ETSBinder::GetProgramList(const util::StringView &oldPath) const noexcept { auto const *globalProgram = globalRecordTable_.Program(); + util::StringView newPath = oldPath; + if (auto it = GetContext()->dupPrograms.find(oldPath); it != GetContext()->dupPrograms.end()) { + newPath = it->second->AbsoluteName(); + } for (const auto &extRecords : globalProgram->ExternalSources()) { for (const auto &program : extRecords.second) { - if (program->AbsoluteName() == path) { + if (program->AbsoluteName() == newPath) { return extRecords.second; } // in case of importing a package folder, the path could not be resolved to a specific file - if (program->IsPackage() && program->SourceFileFolder() == path) { + if (program->IsPackage() && program->SourceFileFolder() == newPath) { return extRecords.second; } } } - if (globalProgram->IsPackage() && path.Compare(globalProgram->SourceFileFolder()) == 0) { + if (globalProgram->IsPackage() && newPath.Compare(globalProgram->SourceFileFolder()) == 0) { return ArenaVector({GetContext()->parserProgram}, Allocator()->Adapter()); } diff --git a/ets2panda/varbinder/ETSBinder.h b/ets2panda/varbinder/ETSBinder.h index 6d24b0f3c7..bc0096047f 100644 --- a/ets2panda/varbinder/ETSBinder.h +++ b/ets2panda/varbinder/ETSBinder.h @@ -154,9 +154,18 @@ public: [[nodiscard]] ArenaVector GetExternalProgram(util::StringView sourceName, const ir::StringLiteral *importPath); - ir::ETSImportDeclaration *FindImportDeclInReExports(const ir::ETSImportDeclaration *const import, - const util::StringView &imported, - const ir::StringLiteral *const importPath); + std::pair FindImportDeclInReExports( + const ir::ETSImportDeclaration *const import, const util::StringView &imported, + const ir::StringLiteral *const importPath); + std::pair FindImportDeclInNamedExports( + const ir::ETSImportDeclaration *const import, const util::StringView &imported, + const ir::StringLiteral *const importPath); + std::pair FindImportDeclInExports( + const ir::ETSImportDeclaration *const import, const util::StringView &imported, + const ir::StringLiteral *const importPath); + ir::ETSImportDeclaration *FindImportDeclIn(const ir::ETSImportDeclaration *const import, + const util::StringView &imported, + const ir::StringLiteral *const importPath); void AddImportNamespaceSpecifiersToTopBindings(Span records, ir::ImportNamespaceSpecifier *namespaceSpecifier, const ir::ETSImportDeclaration *import); @@ -171,6 +180,9 @@ public: const varbinder::Scope::VariableMap &globalBindings, Span record); Variable *FindStaticBinding(Span records, const ir::StringLiteral *importPath); + Variable *AddImportSpecifierFromReExport(ir::AstNode *importSpecifier, const ir::ETSImportDeclaration *const import, + const util::StringView &imported, + const ir::StringLiteral *const importPath); void AddSpecifiersToTopBindings(ir::AstNode *const specifier, const ir::ETSImportDeclaration *const import); void AddDynamicSpecifiersToTopBindings(ir::AstNode *const specifier, const ir::ETSImportDeclaration *const import); -- Gitee