From edf7cb97b923128fb2866b740ded3384a0926eef 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 ca365e2a61..bd5c95be85 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -3662,6 +3662,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 f3c52febcb..810d01985c 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -448,6 +448,13 @@ Type *ETSChecker::BuildBasicInterfaceProperties(ir::TSInterfaceDeclaration *inte type = Program()->IsDeclForDynamicStaticInterop() ? CreateGradualType(interfaceType) : interfaceType; } + // 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); @@ -461,7 +468,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 a958ff0073a98184ce17ebd757b9457d9796b6fb 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 --- .../build_system/src/build/base_mode.ts | 194 ++++++++++++------ ets2panda/driver/build_system/src/types.ts | 1 + 2 files changed, 130 insertions(+), 65 deletions(-) diff --git a/ets2panda/driver/build_system/src/build/base_mode.ts b/ets2panda/driver/build_system/src/build/base_mode.ts index 8b10894fe9..b54db08ac5 100644 --- a/ets2panda/driver/build_system/src/build/base_mode.ts +++ b/ets2panda/driver/build_system/src/build/base_mode.ts @@ -257,7 +257,7 @@ export abstract class BaseMode { arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_CHECKED, arktsGlobal.compilerContext.peer); this.logger.printInfo('es2panda proceedToState checked'); - + if (this.hasMainModule && (this.byteCodeHar || this.moduleType === OHOS_MODULE_TYPE.SHARED)) { let filePathFromModuleRoot: string = path.relative(this.moduleRootPath, fileInfo.filePath); let declEtsOutputPath: string = changeFileExtension( @@ -297,6 +297,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 = ''; @@ -622,19 +679,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.enableDeclgenEts2Ts) { - this.collectDependentCompileFiles(); - return; - } this.entryFiles.forEach((file: string) => { // Skip the declaration files when compiling abc if (file.endsWith(DECL_ETS_SUFFIX)) { @@ -718,15 +771,26 @@ export abstract class BaseMode { this.generateModuleInfos(); const compilePromises: Promise[] = []; - this.compileFiles.forEach((fileInfo: CompileFileInfo, _: string) => { - compilePromises.push(new Promise((resolve) => { - this.compile(fileInfo); - resolve(); - })); + let moduleToFile = new Map(); + this.compileFiles.forEach((fileInfo: CompileFileInfo, file: string) => { + 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); + } + } } // -- runParallell code begins -- @@ -750,8 +814,8 @@ export abstract class BaseMode { this.dependencyAnalyzerCmd.push('@' + '"' + dependencyInputFile + '"'); for (const [_, 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 + '"'); @@ -764,7 +828,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' }); @@ -784,10 +848,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, @@ -840,7 +904,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.' )); @@ -877,7 +941,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()); @@ -929,11 +993,11 @@ export abstract class BaseMode { execPath, execArgs = [], } = options; - + if (clearExitListeners) { cluster.removeAllListeners('exit'); } - + cluster.setupPrimary({ exec: execPath, execArgv: execArgs, @@ -950,63 +1014,63 @@ export abstract class BaseMode { const allNodes = new Set(); for (const node in graph.dependencies) { - allNodes.add(node); - graph.dependencies[node].forEach(dep => allNodes.add(dep)); + allNodes.add(node); + graph.dependencies[node].forEach(dep => allNodes.add(dep)); } for (const node in graph.dependants) { - allNodes.add(node); - graph.dependants[node].forEach(dep => allNodes.add(dep)); + allNodes.add(node); + graph.dependants[node].forEach(dep => allNodes.add(dep)); } Array.from(allNodes).forEach(node => { - adjacencyList[node] = graph.dependencies[node] || []; - reverseAdjacencyList[node] = graph.dependants[node] || []; + adjacencyList[node] = graph.dependencies[node] || []; + reverseAdjacencyList[node] = graph.dependants[node] || []; }); const visited = new Set(); const order: string[] = []; function dfs(node: string): void { - visited.add(node); - for (const neighbor of adjacencyList[node]) { - if (!visited.has(neighbor)) { - dfs(neighbor); - } + visited.add(node); + for (const neighbor of adjacencyList[node]) { + if (!visited.has(neighbor)) { + dfs(neighbor); } - order.push(node); + } + order.push(node); } Array.from(allNodes).forEach(node => { - if (!visited.has(node)) { - dfs(node); - } + if (!visited.has(node)) { + dfs(node); + } }); visited.clear(); const components = new Map>(); function reverseDfs(node: string, component: Set): void { - visited.add(node); - component.add(node); - for (const neighbor of reverseAdjacencyList[node]) { - if (!visited.has(neighbor)) { - reverseDfs(neighbor, component); - } + visited.add(node); + component.add(node); + for (const neighbor of reverseAdjacencyList[node]) { + if (!visited.has(neighbor)) { + reverseDfs(neighbor, component); } + } } for (let i = order.length - 1; i >= 0; i--) { - const node = order[i]; - if (!visited.has(node)) { - const component = new Set(); - reverseDfs(node, component); - if (component.size > 1) { - const sortedFiles = Array.from(component).sort(); - const hashKey = createHash(sortedFiles.join('|')); - components.set(hashKey, component); - } - + const node = order[i]; + if (!visited.has(node)) { + const component = new Set(); + reverseDfs(node, component); + if (component.size > 1) { + const sortedFiles = Array.from(component).sort(); + const hashKey = createHash(sortedFiles.join('|')); + components.set(hashKey, component); } + + } } return components; @@ -1031,14 +1095,14 @@ export abstract class BaseMode { private getAbcJobId(file: string): string { return '1' + file; } - + private getExternalProgramJobId(file: string): string { return '0' + file; } private getJobDependants(fileDeps: string[], cycleFiles: Map): Set { let depJobList: Set = new Set(); - fileDeps.forEach((file) => { + fileDeps.forEach((file) => { if (!file.endsWith(DECL_ETS_SUFFIX)) { depJobList.add(this.getAbcJobId(file)); } @@ -1256,7 +1320,7 @@ export abstract class BaseMode { '--output', fileInfo.abcFilePath, ]; - + if (this.isDebug) { ets2pandaCmd.push('--debug-info'); } @@ -1339,10 +1403,10 @@ export abstract class BaseMode { } private assignTaskToIdleWorker( - workerInfo: WorkerInfo, - queues: Queues, - processingJobs: Set, - serializableConfig: Object, + workerInfo: WorkerInfo, + queues: Queues, + processingJobs: Set, + serializableConfig: Object, globalContextPtr: KPointer): void { let job: Job | undefined; let jobInfo: JobInfo | undefined; @@ -1356,7 +1420,7 @@ export abstract class BaseMode { buildConfig: serializableConfig, globalContextPtr: globalContextPtr }; - } + } else if (queues.abcQueue.length > 0) { job = queues.abcQueue.shift()!; jobInfo = { @@ -1421,6 +1485,6 @@ function createHash(str: string): string { return hash.digest('hex'); } - // -- runConcurrent code ends -- +// -- runConcurrent code ends -- let finishedJob: string[] = []; \ 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 366be7e804..7da3a09ce0 100644 --- a/ets2panda/driver/build_system/src/types.ts +++ b/ets2panda/driver/build_system/src/types.ts @@ -66,6 +66,7 @@ export interface ArkTSGlobal { export interface ArkTS { Config: { create: Function; + createContextGenerateAbcForExternalSourceFiles: Function; }; Context: { createFromString: Function; -- Gitee From 5820c0973bf33d33c60e43c90652f44b6d9398ff 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 | 7 +- 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 | 49 ++++- ets2panda/compiler/core/compilerImpl.cpp | 12 +- ets2panda/compiler/core/emitter.cpp | 6 +- .../compiler/lowering/ets/lambdaLowering.cpp | 3 +- ets2panda/compiler/lowering/phase.cpp | 76 ++++--- ets2panda/compiler/scripts/signatures.yaml | 6 + ets2panda/es2panda.h | 1 + ets2panda/parser/ETSparser.cpp | 50 ++++- ets2panda/parser/ETSparser.h | 3 + ets2panda/parser/program/program.cpp | 7 + ets2panda/parser/program/program.h | 13 +- ets2panda/public/es2panda_lib.cpp | 94 ++++++-- ets2panda/public/es2panda_lib.h | 2 + ets2panda/public/es2panda_lib.idl.erb | 1 + ets2panda/public/public.cpp | 30 +++ ets2panda/public/public.h | 4 + .../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 ++ .../srcdumper/srcdumper-ets-ignored.txt | 29 +++ ets2panda/util/diagnostic/fatal.yaml | 4 + ets2panda/util/importPathManager.cpp | 2 +- ets2panda/util/importPathManager.h | 4 + ets2panda/util/options.cpp | 6 +- ets2panda/util/options.h | 1 + ets2panda/util/options.yaml | 5 + ets2panda/varbinder/ETSBinder.cpp | 200 +++++++++++++++--- ets2panda/varbinder/ETSBinder.h | 18 +- 73 files changed, 1420 insertions(+), 94 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 8d5541159a..daf66ddd4d 100644 --- a/ets2panda/checker/ETSchecker.cpp +++ b/ets2panda/checker/ETSchecker.cpp @@ -374,10 +374,15 @@ void ETSChecker::CheckProgram(parser::Program *program, bool runAnalysis) for (auto *extProg : extPrograms) { if (!extProg->IsASTLowered()) { extProg->PushChecker(this); + auto *savedProgram2 = VarBinder()->AsETSBinder()->Program(); varbinder::RecordTableContext recordTableCtx(VarBinder()->AsETSBinder(), extProg); + 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()); + CheckProgram(extProg, VarBinder()->IsGenStdLib() || extProg->IsGenAbcForExternal()); + VarBinder()->AsETSBinder()->SetProgram(savedProgram2); + VarBinder()->AsETSBinder()->ResetTopScope(savedProgram2->GlobalScope()); } } } diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index 26ed9ad28c..67f0f84894 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -2840,6 +2840,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) { @@ -2855,7 +2857,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); } @@ -2980,6 +2982,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 810d01985c..3c0ab334a3 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -1874,7 +1874,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 3728f497e3..77d3cf08eb 100644 --- a/ets2panda/checker/ets/typeCheckingHelpers.cpp +++ b/ets2panda/checker/ets/typeCheckingHelpers.cpp @@ -806,8 +806,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; } @@ -819,8 +825,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 33339c96f0..e893a1a951 100644 --- a/ets2panda/checker/ets/utilityTypeHandlers.cpp +++ b/ets2panda/checker/ets/utilityTypeHandlers.cpp @@ -156,7 +156,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 3e6f38dbad..16ccde3abe 100644 --- a/ets2panda/compiler/core/ETSemitter.cpp +++ b/ets2panda/compiler/core/ETSemitter.cpp @@ -222,10 +222,35 @@ static std::string GenerateMangledName(const std::string &baseName, const std::s return baseName + "$" + propName; } +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(); @@ -280,29 +305,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 const *signature : recordTable->Signatures()) { - auto func = GenScriptFunction(signature->Node()->AsScriptFunction(), this); + for (auto *signature : recordTable->Signatures()) { + 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)) { continue; } diff --git a/ets2panda/compiler/core/compilerImpl.cpp b/ets2panda/compiler/core/compilerImpl.cpp index 61b8a77601..8aea0d5139 100644 --- a/ets2panda/compiler/core/compilerImpl.cpp +++ b/ets2panda/compiler/core/compilerImpl.cpp @@ -359,7 +359,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') 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 5e4836e445..0c4e4caf52 100644 --- a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp +++ b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp @@ -1286,7 +1286,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 ea5a413a67..18eefa5f2d 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" @@ -299,23 +300,29 @@ 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; } } @@ -336,35 +343,56 @@ bool PhaseForBodies::ProcessExternalPrograms(public_lib::Context *ctx, parser::P return result; } +// CC-OFFNXT(huge_method, huge_depth) solid logic bool PhaseForBodies::Perform(public_lib::Context *ctx, parser::Program *program) { FetchCache(ctx, program); bool result = true; - if (ctx->config->options->GetCompilationMode() == CompilationMode::GEN_STD_LIB) { - result &= ProcessExternalPrograms(ctx, program); + 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) { + if (!extProg->IsGenAbcForExternal() && cMode == CompilationMode::GEN_ABC_FOR_EXTERNAL_SOURCE) { + continue; + } + + if (!extProg->IsASTLowered()) { + 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 490ec79695..5366d99f38 100644 --- a/ets2panda/compiler/scripts/signatures.yaml +++ b/ets2panda/compiler/scripts/signatures.yaml @@ -238,6 +238,12 @@ defines: comment: ETS annotation type - name: 'use static' ref: STATIC_PROGRAM_FLAG + - 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 39cdbf9e1b..1f5a0aafc4 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 9ad3b0d4f6..fff197fa75 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -204,6 +204,22 @@ ir::ETSModule *ETSParser::ParseImportsAndReExportOnly(lexer::SourcePosition star 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(); @@ -214,11 +230,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); @@ -267,7 +288,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()); } @@ -289,6 +310,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(); @@ -427,7 +467,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 94f513f1db..250f09b7ce 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/program/program.cpp b/ets2panda/parser/program/program.cpp index 572ce976dc..13cb454676 100644 --- a/ets2panda/parser/program/program.cpp +++ b/ets2panda/parser/program/program.cpp @@ -73,6 +73,13 @@ const checker::Checker *Program::Checker() const return checkers_.at(compiler::GetPhaseManager()->GetCurrentMajor()); } +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 8760276ccd..5056378116 100644 --- a/ets2panda/parser/program/program.h +++ b/ets2panda/parser/program/program.h @@ -47,7 +47,7 @@ class Checker; } // namespace ark::es2panda::checker namespace ark::es2panda::parser { -enum class ScriptKind { SCRIPT, MODULE, STDLIB }; +enum class ScriptKind { SCRIPT, MODULE, STDLIB, GENEXTERNAL }; #ifndef NDEBUG constexpr uint32_t POISON_VALUE {0x12346789}; @@ -302,6 +302,13 @@ public: (FileName().Is("etsstdlib")); } + bool IsGenAbcForExternal() const; + + void SetGenAbcForExternalSources(bool genAbc = true) + { + genAbcForExternalSource_ = genAbc; + } + varbinder::ClassScope *GlobalClassScope(); const varbinder::ClassScope *GlobalClassScope() const; @@ -375,10 +382,12 @@ private: ExternalSource externalSources_; DirectExternalSource directExternalSources_; ScriptKind kind_ {}; + bool isASTlowered_ {}; + bool genAbcForExternalSource_ {false}; ScriptExtension extension_ {}; ETSNolintsCollectionMap etsnolintCollection_; util::ModuleInfo moduleInfo_; - bool isASTlowered_ {}; + lexer::SourcePosition packageStartPosition_ {}; compiler::CFG *cfg_; ArenaVector functionScopes_; diff --git a/ets2panda/public/es2panda_lib.cpp b/ets2panda/public/es2panda_lib.cpp index 0cfb44268e..22757da105 100644 --- a/ets2panda/public/es2panda_lib.cpp +++ b/ets2panda/public/es2panda_lib.cpp @@ -371,10 +371,7 @@ static void InitializeContext(Context *res) res->state = ES2PANDA_STATE_NEW; } -__attribute__((unused)) static es2panda_Context *CreateContext(es2panda_Config *config, std::string &&source, - const char *fileName, - es2panda_GlobalContext *globalContext, bool isExternal, - bool genStdLib) +static Context *InitContext(es2panda_Config *config) { auto *cfg = reinterpret_cast(config); auto *res = new Context; @@ -382,20 +379,34 @@ __attribute__((unused)) static es2panda_Context *CreateContext(es2panda_Config * 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 reinterpret_cast(res); + 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, + es2panda_GlobalContext *globalContext, bool isExternal, + bool genStdLib) +{ + auto res = InitContext(config); + if (res->state == ES2PANDA_STATE_ERROR) { + return reinterpret_cast(res); + } + auto *cfg = reinterpret_cast(config); + res->isExternal = isExternal; res->globalContext = reinterpret_cast(globalContext); - res->diagnosticEngine = cfg->diagnosticEngine; res->input = std::move(source); res->sourceFileName = fileName; @@ -474,6 +485,12 @@ extern "C" __attribute__((unused)) es2panda_Context *CreateCacheContextFromStrin return CreateContext(config, std::string(source), fileName, globalContext, isExternal, false); } +extern "C" __attribute__((unused)) es2panda_Context *CreateContextFromMultiFile(es2panda_Config *config, + char const *sourceFileNames) +{ + return CreateContext(config, "", sourceFileNames, nullptr, false, false); +} + extern "C" __attribute__((unused)) es2panda_Context *CreateContextFromString(es2panda_Config *config, const char *source, char const *fileName) { @@ -481,6 +498,32 @@ extern "C" __attribute__((unused)) es2panda_Context *CreateContextFromString(es2 return CreateContext(config, std::string(source), fileName, nullptr, false, false); } +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()); + ir::DisableContextHistory(); + res->allocator = new ThreadSafeArenaAllocator(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) { @@ -490,20 +533,14 @@ __attribute__((unused)) static Context *Parse(Context *ctx) } ctx->phaseManager->Reset(); + if (ctx->isExternal && ctx->allocator != ctx->globalContext->stdLibAllocator) { - 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); - util::ImportPathManager::ImportMetadata importData {util::ImportFlags::NONE}; - importData.resolvedSource = ctx->sourceFileName; - 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)); + ctx->sourceFileNames.emplace_back(ctx->sourceFileName); + parser::ETSParser::AddGenExtenralSourceToParseList(ctx); + } else 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); @@ -513,6 +550,22 @@ __attribute__((unused)) static Context *Parse(Context *ctx) 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) { @@ -1250,6 +1303,7 @@ es2panda_Impl g_impl = { CreateCacheContextFromFile, CreateContextFromString, CreateCacheContextFromString, + CreateContextGenerateAbcForExternalSourceFiles, ProceedToState, DestroyContext, CreateGlobalContext, diff --git a/ets2panda/public/es2panda_lib.h b/ets2panda/public/es2panda_lib.h index 88b540eea6..cb861ee1db 100644 --- a/ets2panda/public/es2panda_lib.h +++ b/ets2panda/public/es2panda_lib.h @@ -190,6 +190,8 @@ struct CAPI_EXPORT es2panda_Impl { es2panda_Context *(*CreateCacheContextFromString)(es2panda_Config *config, const char *source, char const *file_name, es2panda_GlobalContext *globalContext, bool isExternal); + 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 34d06285fc..dcff86fb9e 100644 --- a/ets2panda/public/es2panda_lib.idl.erb +++ b/ets2panda/public/es2panda_lib.idl.erb @@ -175,6 +175,7 @@ interface es2panda_Impl { es2panda_Context CreateCacheContextFromFile(es2panda_Config config, String source_file_name, es2panda_GlobalContext globalContext, boolean isExternal); es2panda_Context CreateContextFromString(es2panda_Config config, String source, String file_name); es2panda_Context CreateCacheContextFromString(es2panda_Config config, String source, String file_name, es2panda_GlobalContext globalContext, boolean isExternal); + es2panda_Context CreateContextGenerateAbcForExternalSourceFiles(es2panda_Config config, i32 fileNamesCount, sequence fileNames); es2panda_Context ProceedToState(es2panda_Context context, es2panda_ContextState state); // context is consumed void DestroyContext(es2panda_Context context); es2panda_GlobalContext CreateGlobalContext(es2panda_Config config, sequence externalFileList, u32 fileNum, boolean LspUsage); diff --git a/ets2panda/public/public.cpp b/ets2panda/public/public.cpp index 3b3754328b..5bb8034274 100644 --- a/ets2panda/public/public.cpp +++ b/ets2panda/public/public.cpp @@ -28,4 +28,34 @@ checker::SemanticAnalyzer *Context::GetAnalyzer() const return analyzers_[compiler::GetPhaseManager()->GetCurrentMajor()]; } +void Context::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()); + } +}; + } // namespace ark::es2panda::public_lib diff --git a/ets2panda/public/public.h b/ets2panda/public/public.h index 447555838c..b3cd4ade2b 100644 --- a/ets2panda/public/public.h +++ b/ets2panda/public/public.h @@ -197,6 +197,8 @@ struct Context { } } + void MarkGenAbcForExternal(std::unordered_set &genAbcList, public_lib::ExternalSource &extSources); + ConfigImpl *config = nullptr; GlobalContext *globalContext = nullptr; std::string sourceFileName; @@ -224,6 +226,8 @@ struct Context { TransitionMemory *transitionMemory {nullptr}; bool isExternal = false; bool compiledByCapi = false; + std::vector sourceFileNames; + std::map dupPrograms {}; // NOLINTEND(misc-non-private-member-variables-in-classes) private: 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/test-lists/srcdumper/srcdumper-ets-ignored.txt b/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt index 2d7b73c673..67a4459f5d 100644 --- a/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt +++ b/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt @@ -70,3 +70,32 @@ runtime/ets/class_implements_interface_import.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 24d8d592b6..482af2e674 100644 --- a/ets2panda/util/importPathManager.cpp +++ b/ets2panda/util/importPathManager.cpp @@ -306,7 +306,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 2246eb83fb..04c4742836 100644 --- a/ets2panda/util/importPathManager.h +++ b/ets2panda/util/importPathManager.h @@ -160,6 +160,10 @@ public: void MarkAsParsed(StringView path); util::StringView FormRelativePath(const util::Path &path); + std::shared_ptr ArkTSConfig() const + { + return arktsConfig_; + } private: util::StringView FormModuleNameSolelyByAbsolutePath(const util::Path &path); diff --git a/ets2panda/util/options.cpp b/ets2panda/util/options.cpp index 680847e510..f3e1ea181f 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 fb662ff9f4..5768bfac32 100644 --- a/ets2panda/util/options.yaml +++ b/ets2panda/util/options.yaml @@ -379,3 +379,8 @@ options: type: bool default: false description: Dump es2panda performance metrics + +- 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 84b15b8e3c..0cfc10ccce 100644 --- a/ets2panda/varbinder/ETSBinder.cpp +++ b/ets2panda/varbinder/ETSBinder.cpp @@ -367,6 +367,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()); @@ -731,11 +736,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; @@ -749,6 +839,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()) { @@ -758,17 +849,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, @@ -802,6 +896,44 @@ 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](Variable *var) { + if (importSpecifier->IsImportSpecifier()) { + this->InsertOrAssignForeignBinding(importSpecifier->AsImportSpecifier()->Local()->Name(), var); + importSpecifier->AsImportSpecifier()->Local()->SetVariable(var); + importSpecifier->AsImportSpecifier()->Imported()->SetVariable(var); + } else if (importSpecifier->IsImportDefaultSpecifier()) { + this->InsertOrAssignForeignBinding(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, @@ -828,18 +960,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; } @@ -884,9 +1012,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->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->Local()->Name(), var); return; } } @@ -1135,10 +1269,22 @@ 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) { - BuildExternalProgram(extProg); + if (_.Utf8().substr(0, STD_SUFFIX.length()) != STD_SUFFIX) { + for (auto *extProg : extPrograms) { + BuildExternalProgram(extProg); + } } } @@ -1172,7 +1318,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); extRecordTable->SetClassDefinition(extProgram->GlobalClass()); @@ -1247,7 +1395,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); } @@ -1363,24 +1511,28 @@ void ETSBinder::ImportGlobalProperties(const ir::ClassDefinition *const classDef } } -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 2de8bce901..d5b6e9888d 100644 --- a/ets2panda/varbinder/ETSBinder.h +++ b/ets2panda/varbinder/ETSBinder.h @@ -152,9 +152,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); @@ -169,6 +178,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 ResolveInterfaceDeclaration(ir::TSInterfaceDeclaration *decl); -- Gitee