diff --git a/ets2panda/BUILD.gn b/ets2panda/BUILD.gn index 5a788f0982c1c3b03192087c2c64767440d065a7..a6883d4d3e1a7673cb433b01065e7721071a71d0 100644 --- a/ets2panda/BUILD.gn +++ b/ets2panda/BUILD.gn @@ -214,6 +214,7 @@ libes2panda_sources = [ "compiler/lowering/ets/constantExpressionLowering.cpp", "compiler/lowering/ets/convertPrimitiveCastMethodCall.cpp", "compiler/lowering/ets/declareOverloadLowering.cpp", + "compiler/lowering/ets/declGenPhase.cpp", "compiler/lowering/ets/defaultParametersInConstructorLowering.cpp", "compiler/lowering/ets/defaultParametersLowering.cpp", "compiler/lowering/ets/enumLowering.cpp", @@ -1124,6 +1125,7 @@ libes2panda_configs = [ ":libes2panda_config", "$ark_root/libpandabase:arkbase_public_config", "$ark_root/libpandafile:arkfile_public_config", + "$ark_root/abc2program:arkts_abc2program_public_config", ] libes2panda_public_configs = [ @@ -1173,6 +1175,7 @@ ohos_source_set("libes2panda_frontend_static") { "runtime_core:libarktsbase_package", "runtime_core:libarktscompiler_package", "runtime_core:libarktsfile_package", + "runtime_core:libarktsabc2program_package", sdk_libc_secshared_dep, ] part_name = "ets_frontend" @@ -1213,7 +1216,14 @@ ohos_source_set("libes2panda_public_frontend_static") { deps = [ ":libes2panda_frontend_static" ] if (ark_standalone_build || ark_static_standalone_build) { - deps += [ "$ark_root/bytecode_optimizer:libarktsbytecodeopt_package" ] + deps += [ + "$ark_root/bytecode_optimizer:libarktsbytecodeopt_package", + "$ark_root/abc2program:libarktsabc2program_package", + "$ark_root/assembler:libarktsassembler", + "$ark_root/compiler:libarktscompiler", + "$ark_root/libpandabase:libarktsbase", + "$ark_root/libpandafile:libarktsfile", + ] } if (target_os != "win" && target_os != "mingw" && target_os != "winuwp") { @@ -1223,6 +1233,7 @@ ohos_source_set("libes2panda_public_frontend_static") { external_deps = [ "runtime_core:libarktsbytecodeopt_package", + "runtime_core:libarktsabc2program_package", sdk_libc_secshared_dep, ] part_name = "ets_frontend" diff --git a/ets2panda/CMakeLists.txt b/ets2panda/CMakeLists.txt index 214331408045028a732113408788dc4ef3eb74c6..a6b0cb1894639839cb64fe2142e442d7e8a39583 100644 --- a/ets2panda/CMakeLists.txt +++ b/ets2panda/CMakeLists.txt @@ -73,10 +73,10 @@ if(PANDA_WITH_ETS) " \"@arkts.collections\": [\"${STATIC_CORE}${DELIM}plugins${DELIM}ets${DELIM}sdk${DELIM}arkts${DELIM}@arkts.collections.ets\"],\n" " \"import_tests\": [\"${CMAKE_CURRENT_SOURCE_DIR}/test/parser/ets/import_tests\"]\n" " },\n" - " \"dynamicPaths\": {\n" + " \"dependencies\": {\n" " \"dynamic_import_tests\": {\"language\": \"js\", \"ohmUrl\": \"dynamic_import_tests\"},\n" - " \"dynamic_import_tests/modules/instanceof\": {\"language\": \"js\", \"declPath\": \"${CMAKE_CURRENT_SOURCE_DIR}/test/parser/ets/dynamic_import_tests/modules/instanceof.ets\", \"ohmUrl\": \"${CMAKE_CURRENT_SOURCE_DIR}/test/parser/ets/dynamic_import_tests/modules/instanceof.ets\"},\n" - " \"dynamic_import_tests/modules/module\": {\"language\": \"js\", \"declPath\": \"${CMAKE_CURRENT_SOURCE_DIR}/test/parser/ets/dynamic_import_tests/modules/module.ets\", \"ohmUrl\": \"${CMAKE_CURRENT_SOURCE_DIR}/test/parser/ets/dynamic_import_tests/modules/module.ets\"}\n" + " \"dynamic_import_tests/modules/instanceof\": {\"language\": \"js\", \"path\": \"${CMAKE_CURRENT_SOURCE_DIR}/test/parser/ets/dynamic_import_tests/modules/instanceof.ets\", \"ohmUrl\": \"${CMAKE_CURRENT_SOURCE_DIR}/test/parser/ets/dynamic_import_tests/modules/instanceof.ets\"},\n" + " \"dynamic_import_tests/modules/module\": {\"language\": \"js\", \"path\": \"${CMAKE_CURRENT_SOURCE_DIR}/test/parser/ets/dynamic_import_tests/modules/module.ets\", \"ohmUrl\": \"${CMAKE_CURRENT_SOURCE_DIR}/test/parser/ets/dynamic_import_tests/modules/module.ets\"}\n" " }\n" " }\n" "}\n" @@ -283,6 +283,7 @@ set(ES2PANDA_LIB_SRC compiler/lowering/ets/constantExpressionLowering.cpp compiler/lowering/ets/convertPrimitiveCastMethodCall.cpp compiler/lowering/ets/declareOverloadLowering.cpp + compiler/lowering/ets/declGenPhase.cpp compiler/lowering/ets/defaultParametersInConstructorLowering.cpp compiler/lowering/ets/defaultParametersLowering.cpp compiler/lowering/ets/exportAnonymousConst.cpp @@ -692,7 +693,7 @@ endif() panda_target_link_libraries(es2panda-lib PUBLIC arkbase hmicuuc.z - PRIVATE arkassembler arkdisassembler arkfile + PRIVATE arkassembler arkdisassembler arkfile abc2program ) if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.1) OR diff --git a/ets2panda/aot/BUILD.gn b/ets2panda/aot/BUILD.gn index 2a76c53b3d2214e54eb8041d586d43d357d518bf..7efccf65854505a222c43bd299160c92bb3e5e2f 100644 --- a/ets2panda/aot/BUILD.gn +++ b/ets2panda/aot/BUILD.gn @@ -36,6 +36,7 @@ ohos_executable("ets2panda") { "$ark_root/bytecode_optimizer:bytecodeopt_public_config", "$ark_root/compiler:arkcompiler_public_config", "$ark_root/runtime:arkruntime_public_config", + "$ark_root/abc2program:arkts_abc2program_public_config", ] deps = [ @@ -57,6 +58,7 @@ ohos_executable("ets2panda") { "runtime_core:libarktsbytecodeopt_package", "runtime_core:libarktscompiler_package", "runtime_core:libarktsfile_package", + "runtime_core:libarktsabc2program_package", sdk_libc_secshared_dep, ] diff --git a/ets2panda/bindings/src/build/generateArkTSConfig.ts b/ets2panda/bindings/src/build/generateArkTSConfig.ts index fe1dc108fc57d5604614ef0e4498e76d8f1b21c5..2197374fdff417064431a5cd0718f51761d929e2 100644 --- a/ets2panda/bindings/src/build/generateArkTSConfig.ts +++ b/ets2panda/bindings/src/build/generateArkTSConfig.ts @@ -20,10 +20,10 @@ import { changeFileExtension, ensurePathExists } from '../utils'; import { BuildConfig, ModuleInfo } from '../types'; import { LANGUAGE_VERSION, SYSTEM_SDK_PATH_FROM_SDK } from '../preDefine'; -interface DynamicPathItem { +interface DependencyItem { language: string; - declPath: string; - runtimeName: string; + path: string; + ohmUrl: string; } interface ArkTSConfigObject { @@ -31,9 +31,8 @@ interface ArkTSConfigObject { package: string; baseUrl: string; paths: Record; - dependencies: string[] | undefined; entry: string; - dynamicPaths: Record; + dependencies: Record; }; } @@ -128,20 +127,13 @@ export class ArkTSConfigGenerator { return this.pathSection; } - private getDependenciesSection(moduleInfo: ModuleInfo, dependenciesSection: string[]): void { - let depModules: Map = moduleInfo.staticDepModuleInfos; - depModules.forEach((depModuleInfo: ModuleInfo) => { - dependenciesSection.push(depModuleInfo.arktsConfigFile); - }); - } - private getOhmurl(file: string, moduleInfo: ModuleInfo): string { let unixFilePath: string = file.replace(/\\/g, '/'); let ohmurl: string = moduleInfo.packageName + '/' + unixFilePath; return changeFileExtension(ohmurl, ''); } - private getDynamicPathSection(moduleInfo: ModuleInfo, dynamicPathSection: Record): void { + private getDependenciesSection(moduleInfo: ModuleInfo, dependencySection: Record): void { let depModules: Map = moduleInfo.dynamicDepModuleInfos; depModules.forEach((depModuleInfo: ModuleInfo) => { @@ -153,16 +145,16 @@ export class ArkTSConfigGenerator { let declFilesObject = JSON.parse(fs.readFileSync(depModuleInfo.declFilesPath, 'utf-8')); Object.keys(declFilesObject.files).forEach((file: string) => { let ohmurl: string = this.getOhmurl(file, depModuleInfo); - dynamicPathSection[ohmurl] = { + dependencySection[ohmurl] = { language: 'js', - declPath: declFilesObject.files[file].declPath, - runtimeName: declFilesObject.files[file].ohmUrl + path: declFilesObject.files[file].declPath, + ohmUrl: declFilesObject.files[file].ohmUrl }; let absFilePath: string = path.resolve(depModuleInfo.moduleRootPath, file); let entryFileWithoutExtension: string = changeFileExtension(depModuleInfo.entryFile, ''); if (absFilePath === entryFileWithoutExtension) { - dynamicPathSection[depModuleInfo.packageName] = dynamicPathSection[ohmurl]; + dependencySection[depModuleInfo.packageName] = dependencySection[ohmurl]; } }); }); @@ -173,9 +165,8 @@ export class ArkTSConfigGenerator { console.error('SourceRoots not set from hvigor.'); } let pathSection = this.getPathSection(); - let dependenciesSection: string[] = []; - let dynamicPathSection: Record = {}; - this.getDynamicPathSection(moduleInfo, dynamicPathSection); + let dependencySection: Record = {}; + this.getDependenciesSection(moduleInfo, dependencySection); let baseUrl: string = path.resolve(moduleInfo.moduleRootPath, moduleInfo.sourceRoots[0]); let arktsConfig: ArkTSConfigObject = { @@ -183,9 +174,8 @@ export class ArkTSConfigGenerator { package: moduleInfo.packageName, baseUrl: baseUrl, paths: pathSection, - dependencies: dependenciesSection.length === 0 ? undefined : dependenciesSection, entry: moduleInfo.entryFile, - dynamicPaths: dynamicPathSection + dependencies: dependencySection } }; diff --git a/ets2panda/compiler/core/ETSemitter.cpp b/ets2panda/compiler/core/ETSemitter.cpp index 81ff05cfe2b47612f29a5eb7a8a7bb1523c9432a..b0bdd7d66f24c5ae898ee1e46c3756cb4fa8decb 100644 --- a/ets2panda/compiler/core/ETSemitter.cpp +++ b/ets2panda/compiler/core/ETSemitter.cpp @@ -218,51 +218,6 @@ static std::string GenerateMangledName(const std::string &baseName, const std::s return baseName + "$" + propName; } -static void StoreEntity(std::vector &literals, uint8_t type) -{ - uint32_t emptyValue = 0; - literals.emplace_back(pandasm::LiteralArray::Literal {panda_file::LiteralTag::TAGVALUE, - static_cast(panda_file::LiteralTag::INTEGER)}); - literals.emplace_back(pandasm::LiteralArray::Literal {panda_file::LiteralTag::INTEGER, emptyValue}); - - literals.emplace_back(pandasm::LiteralArray::Literal {panda_file::LiteralTag::TAGVALUE, - static_cast(panda_file::LiteralTag::ACCESSOR)}); - literals.emplace_back(pandasm::LiteralArray::Literal {panda_file::LiteralTag::ACCESSOR, type}); - - literals.emplace_back(pandasm::LiteralArray::Literal {panda_file::LiteralTag::TAGVALUE, - static_cast(panda_file::LiteralTag::INTEGER)}); - literals.emplace_back(pandasm::LiteralArray::Literal {panda_file::LiteralTag::INTEGER, emptyValue}); -} - -static std::vector> StoreExportNodes( - std::vector> &declGen, pandasm::Program *program) -{ - std::vector literals; - std::vector> result; - - for (auto &pair : declGen) { - auto declString = std::string {pair.first}; - auto *node = pair.second; - if (node->IsClassProperty() && node->IsConst()) { - StoreEntity(literals, parser::EntityType::CLASS_PROPERTY); - result.emplace_back(declString, node->AsClassProperty()->Id()->Name().Mutf8()); - } else if (node->IsMethodDefinition()) { - StoreEntity(literals, parser::EntityType::METHOD_DEFINITION); - result.emplace_back(declString, node->AsMethodDefinition()->Function()->Scope()->InternalName()); - } else if (node->IsClassDefinition()) { - StoreEntity(literals, parser::EntityType::CLASS_DEFINITION); - result.emplace_back(declString, node->AsClassDefinition()->InternalName().Mutf8()); - } else if (node->IsTSInterfaceDeclaration()) { - StoreEntity(literals, parser::EntityType::TS_INTERFACE_DECLARATION); - result.emplace_back(declString, node->AsTSInterfaceDeclaration()->InternalName().Mutf8()); - } else { - ES2PANDA_UNREACHABLE(); - } - } - program->literalarrayTable.emplace("export_entities", literals); - return result; -} - void ETSEmitter::GenAnnotation() { Program()->lang = EXTENSION; @@ -309,10 +264,6 @@ void ETSEmitter::GenAnnotation() for (auto [arrType, signature] : checker->GlobalArrayTypes()) { GenGlobalArrayRecord(arrType, signature); } - if (Context()->config->options->WasSetWithExportTable()) { - auto result = StoreExportNodes(Context()->parserProgram->DeclGenExportNodes(), Program()); - Program()->exportStrMap = std::move(result); - } } static bool IsFromSelfHeadFile(const std::string &name, const parser::Program *curProg, const parser::Program *extProg) diff --git a/ets2panda/compiler/core/compilerImpl.cpp b/ets2panda/compiler/core/compilerImpl.cpp index 86b978ffe4b4bd12de41312ed8be0a7acf31e157..61b8a776018bd9a2429d720692982cb338090440 100644 --- a/ets2panda/compiler/core/compilerImpl.cpp +++ b/ets2panda/compiler/core/compilerImpl.cpp @@ -175,16 +175,6 @@ static bool RunVerifierAndPhases(public_lib::Context &context, parser::Program & if (afterCheckerPhase && context.diagnosticEngine->IsAnyError()) { return false; } - - if (options.IsGenerateDeclEnabled() && name == compiler::CheckerPhase::NAME) { - std::string path; - if (!options.WasSetGenerateDeclPath()) { - path = ark::os::RemoveExtension(util::BaseName(options.SourceFileName())).append(".d.ets"); - } else { - path = options.GetGenerateDeclPath(); - } - HandleGenerateDecl(program, *context.diagnosticEngine, path); - } } return true; diff --git a/ets2panda/compiler/lowering/ets/declGenPhase.cpp b/ets2panda/compiler/lowering/ets/declGenPhase.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1609abacd0cf11612aeba8f2cf3ab90af016fe51 --- /dev/null +++ b/ets2panda/compiler/lowering/ets/declGenPhase.cpp @@ -0,0 +1,67 @@ +/** + * 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. + */ + +#include "declGenPhase.h" + +#include "checker/ETSchecker.h" +#include "compiler/lowering/util.h" + +namespace ark::es2panda::compiler { + +bool DeclGenPhase::PerformForModule(public_lib::Context *ctx, parser::Program *program) +{ + if (!ctx->config->options->IsEmitDeclaration()) { + return true; + } + + checker_ = ctx->GetChecker()->AsETSChecker(); + phaseManager_ = ctx->phaseManager; + + DumpDeclaration(program); + CreateModuleDeclarationAnnotation(program); + + return true; +} + +void DeclGenPhase::DumpDeclaration(parser::Program *program) +{ + declaration_ = program->Ast()->DumpDecl(); + declaration_.erase(0, declaration_.find_first_not_of('\n')); + declaration_.erase(declaration_.find_last_not_of('\n'), declaration_.size() - 1); +} + +void DeclGenPhase::CreateModuleDeclarationAnnotation(parser::Program *program) +{ + auto *const annoUsageIdent = checker_->AllocNode(MODULE_DECLARATION_NAME, checker_->Allocator()); + annoUsageIdent->SetAnnotationUsage(); + + auto flags = ir::ModifierFlags::ANNOTATION_USAGE; + ArenaVector properties(checker_->Allocator()->Adapter()); + auto *singleParamName = + checker_->AllocNode(compiler::Signatures::ANNOTATION_KEY_VALUE, checker_->Allocator()); + auto *declarationLiteral = checker_->AllocNode(declaration_.c_str()); + auto *declarationProp = checker_->AllocNode(singleParamName, declarationLiteral, nullptr, flags, + checker_->Allocator(), false); + properties.push_back(declarationProp); + + auto *annotationUsage = checker_->AllocNode(annoUsageIdent, std::move(properties)); + annotationUsage->AddModifier(flags); + annotationUsage->SetParent(program->GlobalClass()); + + program->GlobalClass()->AddAnnotations(annotationUsage); + Recheck(phaseManager_, checker_->VarBinder()->AsETSBinder(), checker_, annotationUsage); +} + +} // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/declGenPhase.h b/ets2panda/compiler/lowering/ets/declGenPhase.h new file mode 100644 index 0000000000000000000000000000000000000000..09534fc7c8091f0d1679dd3c42ac69b33bfb9aae --- /dev/null +++ b/ets2panda/compiler/lowering/ets/declGenPhase.h @@ -0,0 +1,48 @@ +/** + * 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. + */ + +#ifndef ES2PANDA_COMPILER_LOWERING_DECL_GEN_PHASE_H +#define ES2PANDA_COMPILER_LOWERING_DECL_GEN_PHASE_H + +#include "compiler/lowering/phase.h" + +namespace ark::es2panda::compiler { + +// 1. Generate declaration for checked AST +// 2. Store declaration to annotation to ETSGLOBAL class +class DeclGenPhase : public PhaseForBodies { +public: + std::string_view Name() const override + { + return "DeclGenPhase"; + } + + bool PerformForModule(public_lib::Context *ctx, parser::Program *program) override; + + static constexpr std::string_view const MODULE_DECLARATION_NAME {"ModuleDeclaration"}; + static constexpr std::string_view const MODULE_DECLARATION_ANNOTATION {"std.annotations.ModuleDeclaration"}; + +private: + void DumpDeclaration(parser::Program *program); + void CreateModuleDeclarationAnnotation(parser::Program *program); + + checker::ETSChecker *checker_ {nullptr}; + compiler::PhaseManager *phaseManager_ {nullptr}; + std::string declaration_; +}; + +} // namespace ark::es2panda::compiler + +#endif // ES2PANDA_COMPILER_LOWERING_DECL_GEN_PHASE_H diff --git a/ets2panda/compiler/lowering/phase.cpp b/ets2panda/compiler/lowering/phase.cpp index c321ed36b8b664e093983492e3613f3e40d3ed51..91d85209538ecc406a7c175f1dece946fd30b9d2 100644 --- a/ets2panda/compiler/lowering/phase.cpp +++ b/ets2panda/compiler/lowering/phase.cpp @@ -28,6 +28,7 @@ #include "compiler/lowering/ets/convertPrimitiveCastMethodCall.h" #include "compiler/lowering/ets/declareOverloadLowering.h" #include "compiler/lowering/ets/cfgBuilderPhase.h" +#include "compiler/lowering/ets/declGenPhase.h" #include "compiler/lowering/ets/defaultParametersInConstructorLowering.h" #include "compiler/lowering/ets/defaultParametersLowering.h" #include "compiler/lowering/ets/enumLowering.h" @@ -121,7 +122,9 @@ std::vector GetETSPhaseList() new AnnotationCopyLowering, // please DO NOT change order of these two phases: checkerPhase and pluginsAfterCheck new CheckerPhase, - // pluginsAfterCheck has to go right after checkerPhase, nothing should be between them + // Dump declaration right after checker + new DeclGenPhase, + // pluginsAfterCheck has to go right after checkerPhase new PluginPhase {g_pluginsAfterCheck, ES2PANDA_STATE_CHECKED, &util::Plugin::AfterCheck}, // new ConvertPrimitiveCastMethodCall, new AnnotationCopyPostLowering, diff --git a/ets2panda/docs/cheatsheet.md b/ets2panda/docs/cheatsheet.md index 48e7146f52faea3e052ed0c20cd8e873e1f21ffb..6810c0711a03882073d5615106e4020dfc49d0b6 100644 --- a/ets2panda/docs/cheatsheet.md +++ b/ets2panda/docs/cheatsheet.md @@ -139,7 +139,7 @@ in each module that we compile. The default config file looks like this: "import_tests": ["/path/to/static_core/tools/es2panda/test/parser/ets/import_tests"], "dynamic_import_tests": ["/path/to/static_core/tools/es2panda/test/parser/ets/dynamic_import_tests"] }, - "dynamicPaths": { + "dependencies": { "dynamic_import_tests": {"language": "js", "hasDecl": false}, "/path/to/static_core/tools/es2panda/test/parser/ets/dynamic_import_tests": {"language": "js", "hasDecl": true} } diff --git a/ets2panda/docs/import_export.md b/ets2panda/docs/import_export.md index d0c1c442137afa90c5c5ca5cd90544a260ebf0b7..9277ed82b6ccfe618fe2b7e55c896ef828ac48ed 100644 --- a/ets2panda/docs/import_export.md +++ b/ets2panda/docs/import_export.md @@ -113,7 +113,7 @@ The *importPath* is a string literal which can be points to a module (separate m Resolving these paths within the compiler is the responsibility of the *importPathManager*. In the process of parsing an import path, the string literal will be passed to the importPathManager which will resolve it as an absolute path and adds it to an own list, called *parseList_.* The latter list serves to let the compiler know what still needs to be parsed (handle and avoid duplications), and this list will be requested and traversed during the *ParseSources* call. The importPathManager also handles errors that can be caught before parsing, for example non-existent, incorrectly specified import paths, but not errors that can only be found after parsing (for example, the package folder should contains only package files that use the same package directive, etc.) -The importPath with the resolved path and two additional information - which is the language information and whether the imported element has a declaration or not - , will be stored in an ImportSource instance. The latter two information can be set under the dynamicPaths tag in arktsconfig.json, otherwise they will be assigned a default value (the lang member will be specified from the extension, hasDecl member will be true). This instance will be passed as a parameter during the allocation of the *ETSImportDeclaration* AST node, as well as the specifiers list resolved from the binding forms explained in the next section and the import kind (type or value). +The importPath with the resolved path and two additional information - which is the language information and whether the imported element has a declaration or not - , will be stored in an ImportSource instance. The latter two information can be set under the dependencies tag in arktsconfig.json, otherwise they will be assigned a default value (the lang member will be specified from the extension, hasDecl member will be true). This instance will be passed as a parameter during the allocation of the *ETSImportDeclaration* AST node, as well as the specifiers list resolved from the binding forms explained in the next section and the import kind (type or value). ## 5.2. Handle binding forms (allBinding|selectiveBindings|defaultBinding|typeBinding) diff --git a/ets2panda/driver/build_system/src/build/base_mode.ts b/ets2panda/driver/build_system/src/build/base_mode.ts index 5796c8a413e86cc30091445b14261ce76340750c..94741554801380b23db8accb9c3f8abe9a227790 100644 --- a/ets2panda/driver/build_system/src/build/base_mode.ts +++ b/ets2panda/driver/build_system/src/build/base_mode.ts @@ -573,7 +573,7 @@ export abstract class BaseMode { processed.add(currentFile); (this.dependencyFileMap?.dependants[currentFile] || []).forEach(dependant => { - // For the 1.1 declaration file referenced in dynamicPaths, if a path is detected as non-existent, it will be skipped. + // For the 1.1 declaration file referenced in dependencies, if a path is detected as non-existent, it will be skipped. const isFileExist = fs.existsSync(dependant); if (!isFileExist) { return; diff --git a/ets2panda/driver/build_system/src/build/generate_arktsconfig.ts b/ets2panda/driver/build_system/src/build/generate_arktsconfig.ts index b4d889ba36fe50a15e7fcebe3e68b8410f11654b..f95e5bd65f282ac8bad05a86f2d4abf1c56a3548 100644 --- a/ets2panda/driver/build_system/src/build/generate_arktsconfig.ts +++ b/ets2panda/driver/build_system/src/build/generate_arktsconfig.ts @@ -44,9 +44,9 @@ import { sdkConfigPrefix, } from '../pre_define'; -interface DynamicPathItem { +interface DependencyItem { language: string, - declPath: string, + path: string, ohmUrl: string } @@ -55,9 +55,8 @@ interface ArkTSConfigObject { package: string, baseUrl: string, paths: Record; - dependencies: string[] | undefined; entry?: string; - dynamicPaths: Record; + dependencies: Record; useEmptyPackage?: boolean; } }; @@ -197,20 +196,13 @@ export class ArkTSConfigGenerator { } } - private getDependenciesSection(moduleInfo: ModuleInfo, dependenciesSection: string[]): void { - let depModules: Map = moduleInfo.staticDepModuleInfos; - depModules.forEach((depModuleInfo: ModuleInfo) => { - dependenciesSection.push(depModuleInfo.arktsConfigFile); - }); - } - private getOhmurl(file: string, moduleInfo: ModuleInfo): string { let unixFilePath: string = file.replace(/\\/g, '/'); let ohmurl: string = moduleInfo.packageName + '/' + unixFilePath; return changeFileExtension(ohmurl, ''); } - private getDynamicPathSection(moduleInfo: ModuleInfo, dynamicPathSection: Record): void { + private getDependenciesSection(moduleInfo: ModuleInfo, dependenciesection: Record): void { let depModules: Map = moduleInfo.dynamicDepModuleInfos; depModules.forEach((depModuleInfo: ModuleInfo) => { @@ -222,16 +214,16 @@ export class ArkTSConfigGenerator { let declFilesObject = JSON.parse(fs.readFileSync(depModuleInfo.declFilesPath, 'utf-8')); Object.keys(declFilesObject.files).forEach((file: string) => { let ohmurl: string = this.getOhmurl(file, depModuleInfo); - dynamicPathSection[ohmurl] = { + dependenciesection[ohmurl] = { language: 'js', - declPath: declFilesObject.files[file].declPath, + path: declFilesObject.files[file].declPath, ohmUrl: declFilesObject.files[file].ohmUrl }; let absFilePath: string = path.resolve(depModuleInfo.moduleRootPath, file); let entryFileWithoutExtension: string = changeFileExtension(depModuleInfo.entryFile, ''); if (absFilePath === entryFileWithoutExtension) { - dynamicPathSection[depModuleInfo.packageName] = dynamicPathSection[ohmurl]; + dependenciesection[depModuleInfo.packageName] = dependenciesection[ohmurl]; } }); }); @@ -250,25 +242,21 @@ export class ArkTSConfigGenerator { this.logger.printErrorAndExit(logData); } let pathSection = this.getPathSection(moduleInfo); - let dependenciesSection: string[] = []; - this.getDependenciesSection(moduleInfo, dependenciesSection); - this.getAllFilesToPathSectionForHybrid(moduleInfo, buildConfig); - - let dynamicPathSection: Record = {}; + this.getAllFilesToPathSectionForHybrid(moduleInfo, buildConfig); + let dependenciesection: Record = {}; if (!enableDeclgenEts2Ts) { - this.getDynamicPathSection(moduleInfo, dynamicPathSection); + this.getDependenciesSection(moduleInfo, dependenciesection); } - this.processAlias(moduleInfo, dynamicPathSection); + this.processAlias(moduleInfo, dependenciesection); let baseUrl: string = path.resolve(moduleInfo.moduleRootPath, moduleInfo.sourceRoots[0]); let arktsConfig: ArkTSConfigObject = { compilerOptions: { package: moduleInfo.packageName, baseUrl: baseUrl, paths: pathSection, - dependencies: dependenciesSection.length === 0 ? undefined : dependenciesSection, entry: moduleInfo.entryFile, - dynamicPaths: dynamicPathSection + dependencies: dependenciesection } }; @@ -292,31 +280,31 @@ export class ArkTSConfigGenerator { fs.writeFileSync(moduleInfo.arktsConfigFile, JSON.stringify(arktsConfig, null, 2), 'utf-8'); } - private processAlias(moduleInfo: ModuleInfo, dynamicPathSection: Record): void { + private processAlias(moduleInfo: ModuleInfo, dependencySection: Record): void { const aliasForPkg: Map | undefined = this.aliasConfig?.get(moduleInfo.packageName); aliasForPkg?.forEach((aliasConfig, aliasName) => { if (aliasConfig.isStatic || aliasConfig.originalAPIName.startsWith('@kit')) { this.processStaticAlias(aliasName, aliasConfig); } else { - this.processDynamicAlias(aliasName, aliasConfig, dynamicPathSection); + this.processDynamicAlias(aliasName, aliasConfig, dependencySection); } }); this.dynamicSDKPaths.forEach(basePath => { if (fs.existsSync(basePath)) { - this.traverseDynamicPath(basePath, '', false, dynamicPathSection); + this.traverseDependencies(basePath, '', false, dependencySection); } else { this.logger.printWarn(`sdk path ${basePath} not exist.`); } }); } - private traverseDynamicPath( + private traverseDependencies( currentDir: string, relativePath: string, isExcludedDir: boolean, - dynamicPathSection: Record, + dependencySection: Record, allowedExtensions: string[] = ['.d.ets'] ): void { const items = fs.readdirSync(currentDir); @@ -327,7 +315,7 @@ export class ArkTSConfigGenerator { if (stat.isFile()) { if (this.isAllowedExtension(item, allowedExtensions)) { - this.processDynamicFile(itemPath, item, relativePath, isExcludedDir, dynamicPathSection); + this.processDynamicFile(itemPath, item, relativePath, isExcludedDir, dependencySection); } continue; } @@ -335,11 +323,11 @@ export class ArkTSConfigGenerator { if (stat.isDirectory()) { const isRuntimeAPI = path.basename(currentDir) === 'arkui' && item === 'runtime-api'; const newRelativePath = isRuntimeAPI ? '' : (relativePath ? `${relativePath}.${item}` : item); - this.traverseDynamicPath( + this.traverseDependencies( path.resolve(currentDir, item), newRelativePath, isExcludedDir || isRuntimeAPI, - dynamicPathSection, + dependencySection, allowedExtensions ); } @@ -364,16 +352,16 @@ export class ArkTSConfigGenerator { fileName: string, relativePath: string, isExcludedDir: boolean, - dynamicPathSection: Record + dependencySection: Record ): void { if (!this.isValidAPIFile(fileName)) return; const baseName = path.basename(fileName, '.d.ets'); const key = this.buildDynamicKey(baseName, relativePath, isExcludedDir); - dynamicPathSection[key] = { + dependencySection[key] = { language: 'js', - declPath: filePath, + path: filePath, ohmUrl: getOhmurlByApi(baseName) }; } @@ -384,7 +372,7 @@ export class ArkTSConfigGenerator { } } - private processDynamicAlias(aliasName: string, aliasConfig: AliasConfig, dynamicPathSection: Record) { + private processDynamicAlias(aliasName: string, aliasConfig: AliasConfig, dependencySection: Record) { const declPath = getInteropFilePathByApi(aliasConfig.originalAPIName, this.dynamicSDKPaths); if (declPath === '') { return; @@ -396,9 +384,9 @@ export class ArkTSConfigGenerator { ); this.logger.printError(logData); } - dynamicPathSection[aliasName] = { + dependencySection[aliasName] = { language: 'js', - declPath: declPath, + path: declPath, ohmUrl: getOhmurlByApi(aliasConfig.originalAPIName) } } diff --git a/ets2panda/evaluate/entityDeclarator.cpp b/ets2panda/evaluate/entityDeclarator.cpp index acd955e3088e1b39a4cd4642296f9b6890b4237b..02631fd53dc8ae873c6a7f4811fbfdc58a8f7478 100644 --- a/ets2panda/evaluate/entityDeclarator.cpp +++ b/ets2panda/evaluate/entityDeclarator.cpp @@ -86,7 +86,7 @@ ir::ETSImportDeclaration *EntityDeclarator::CreateIrImport(util::StringView path auto *spec = checker->AllocNode(imported, local); ArenaVector specifiers(1, spec, allocator->Adapter()); - return checker->AllocNode(source, importMetadata, std::move(specifiers)); + return checker->AllocNode(source, std::move(importMetadata), std::move(specifiers)); } void EntityDeclarator::InsertImportStatement(ir::Statement *importStatement, parser::Program *importerProgram) diff --git a/ets2panda/ir/ets/etsImportDeclaration.h b/ets2panda/ir/ets/etsImportDeclaration.h index 7f7e56683b221a2bc6ac9471678f65c41a3fe307..dc5d6d8094a6ac8e100e7117dcd0fa7e94be6512 100644 --- a/ets2panda/ir/ets/etsImportDeclaration.h +++ b/ets2panda/ir/ets/etsImportDeclaration.h @@ -27,9 +27,9 @@ class StringLiteral; class ETSImportDeclaration : public ImportDeclaration { public: - ETSImportDeclaration(ir::StringLiteral *importPath, util::ImportPathManager::ImportMetadata importMetadata, + ETSImportDeclaration(ir::StringLiteral *importPath, util::ImportPathManager::ImportMetadata &&importMetadata, ArenaVector &&specifiers, const ImportKinds importKinds = ImportKinds::ALL) - : ImportDeclaration(importPath, std::move(specifiers), importKinds), importMetadata_(importMetadata) + : ImportDeclaration(importPath, std::move(specifiers), importKinds), importMetadata_(std::move(importMetadata)) { SetType(AstNodeType::ETS_IMPORT_DECLARATION); } diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index efb296e96ba224af4d27ef1c8d5452e26a584066..7296238a191bd58e9ab89c873c62535564e23e7c 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -361,15 +361,23 @@ std::vector ETSParser::SearchForNotParsed(ArenaVectorMarkAsParsed(data.resolvedSource); return programs; } - util::DiagnosticMessageParams diagParams = {std::string(parseCandidate)}; - std::ifstream inputStream {std::string(parseCandidate)}; + + std::string parseCandidateStr {parseCandidate}; + util::DiagnosticMessageParams diagParams = {parseCandidateStr}; + std::ifstream inputStream {parseCandidateStr}; if (!inputStream) { DiagnosticEngine().LogDiagnostic(diagnostic::OPEN_FAILED, diagParams); return programs; // Error processing. } std::stringstream ss; ss << inputStream.rdbuf(); - std::string externalSource = ss.str(); + std::string externalSource; + if (data.IsExternalBinaryImport()) { + externalSource = data.declText; + } else { + externalSource = ss.str(); + } + auto preservedLang = GetContext().SetLanguage(data.lang); auto extSrc = Allocator()->New(externalSource, Allocator()); importPathManager_->MarkAsParsed(data.resolvedSource); diff --git a/ets2panda/parser/program/program.h b/ets2panda/parser/program/program.h index c29543942cadcf88358a2ac9db0e08e8f34a4169..c560db7fca6d8ca3d1c7002310aa171bf9bd75e6 100644 --- a/ets2panda/parser/program/program.h +++ b/ets2panda/parser/program/program.h @@ -48,7 +48,6 @@ class Checker; namespace ark::es2panda::parser { enum class ScriptKind { SCRIPT, MODULE, STDLIB }; -enum EntityType { CLASS_PROPERTY = 0, METHOD_DEFINITION = 1, CLASS_DEFINITION = 2, TS_INTERFACE_DECLARATION = 3 }; #ifndef NDEBUG constexpr uint32_t POISON_VALUE {0x12346789}; @@ -311,19 +310,8 @@ public: void AddNodeToETSNolintCollection(const ir::AstNode *node, const std::set &warningsCollection); bool NodeContainsETSNolint(const ir::AstNode *node, ETSWarnings warning); - std::vector> &DeclGenExportNodes() - { - // NOTE: ExportNodes is not supported now. - return declGenExportNodes_; - } - bool MergeExternalSource(const ExternalSource *externalSource); - void AddDeclGenExportNode(const std::string &declGenExportStr, ir::AstNode *node) - { - declGenExportNodes_.emplace_back(declGenExportStr, node); - } - // The name "IsDied", because correct value of canary is a necessary condition for the life of "Program", but // not sufficient bool IsDied() const @@ -388,7 +376,6 @@ private: bool isASTlowered_ {}; lexer::SourcePosition packageStartPosition_ {}; compiler::CFG *cfg_; - std::vector> declGenExportNodes_; ArenaVector functionScopes_; std::unordered_map> fileDependencies_; diff --git a/ets2panda/test/tsconfig/test-decl/check-decl-path/arktsconfig.in.decl.json b/ets2panda/test/tsconfig/test-decl/check-decl-path/arktsconfig.in.decl.json index abc17863c978e711115757a7bcdf7bdbd756f431..ee7ac03b2cb1ff93be876b4d8df9601a1508e0c8 100644 --- a/ets2panda/test/tsconfig/test-decl/check-decl-path/arktsconfig.in.decl.json +++ b/ets2panda/test/tsconfig/test-decl/check-decl-path/arktsconfig.in.decl.json @@ -5,8 +5,8 @@ "escompat": ["${PANDA_ROOT}/plugins/ets/stdlib/escompat"], "std": ["${PANDA_ROOT}/plugins/ets/stdlib/std"] }, - "dynamicPaths": { - "js": { "language": "js", "declPath": "${CMAKE_CURRENT_SOURCE_DIR}/wrong-path/js/index.ets", "ohmUrl": "${CMAKE_CURRENT_SOURCE_DIR}/${project}/js/index" } + "dependencies": { + "js": { "language": "js", "path": "${CMAKE_CURRENT_SOURCE_DIR}/wrong-path/js/index.ets", "ohmUrl": "${CMAKE_CURRENT_SOURCE_DIR}/${project}/js/index" } } } } \ No newline at end of file diff --git a/ets2panda/test/tsconfig/test-decl/check-export-decl/arktsconfig.in.decl.json b/ets2panda/test/tsconfig/test-decl/check-export-decl/arktsconfig.in.decl.json index 3e875c427d9787a2f9e6a5456b96b0c9e17b5e21..030c6d78f4d8cf61d80313e5d523d26f10715212 100644 --- a/ets2panda/test/tsconfig/test-decl/check-export-decl/arktsconfig.in.decl.json +++ b/ets2panda/test/tsconfig/test-decl/check-export-decl/arktsconfig.in.decl.json @@ -5,8 +5,8 @@ "escompat": ["${PANDA_ROOT}/plugins/ets/stdlib/escompat"], "std": ["${PANDA_ROOT}/plugins/ets/stdlib/std"] }, - "dynamicPaths": { - "js": { "language": "js", "declPath": "${CMAKE_CURRENT_SOURCE_DIR}/${project}/js/index.ets", "ohmUrl": "${CMAKE_CURRENT_SOURCE_DIR}/${project}/js/index" } + "dependencies": { + "js": { "language": "js", "path": "${CMAKE_CURRENT_SOURCE_DIR}/${project}/js/index.ets", "ohmUrl": "${CMAKE_CURRENT_SOURCE_DIR}/${project}/js/index" } } } } diff --git a/ets2panda/test/tsconfig/test-decl/check-extend-dynamic/arktsconfig.in.decl.json b/ets2panda/test/tsconfig/test-decl/check-extend-dynamic/arktsconfig.in.decl.json index 3e875c427d9787a2f9e6a5456b96b0c9e17b5e21..030c6d78f4d8cf61d80313e5d523d26f10715212 100644 --- a/ets2panda/test/tsconfig/test-decl/check-extend-dynamic/arktsconfig.in.decl.json +++ b/ets2panda/test/tsconfig/test-decl/check-extend-dynamic/arktsconfig.in.decl.json @@ -5,8 +5,8 @@ "escompat": ["${PANDA_ROOT}/plugins/ets/stdlib/escompat"], "std": ["${PANDA_ROOT}/plugins/ets/stdlib/std"] }, - "dynamicPaths": { - "js": { "language": "js", "declPath": "${CMAKE_CURRENT_SOURCE_DIR}/${project}/js/index.ets", "ohmUrl": "${CMAKE_CURRENT_SOURCE_DIR}/${project}/js/index" } + "dependencies": { + "js": { "language": "js", "path": "${CMAKE_CURRENT_SOURCE_DIR}/${project}/js/index.ets", "ohmUrl": "${CMAKE_CURRENT_SOURCE_DIR}/${project}/js/index" } } } } diff --git a/ets2panda/test/tsconfig/test-decl/resolve-dynamic-paths/arktsconfig.in.decl.json b/ets2panda/test/tsconfig/test-decl/resolve-dynamic-paths/arktsconfig.in.decl.json index 3e875c427d9787a2f9e6a5456b96b0c9e17b5e21..030c6d78f4d8cf61d80313e5d523d26f10715212 100644 --- a/ets2panda/test/tsconfig/test-decl/resolve-dynamic-paths/arktsconfig.in.decl.json +++ b/ets2panda/test/tsconfig/test-decl/resolve-dynamic-paths/arktsconfig.in.decl.json @@ -5,8 +5,8 @@ "escompat": ["${PANDA_ROOT}/plugins/ets/stdlib/escompat"], "std": ["${PANDA_ROOT}/plugins/ets/stdlib/std"] }, - "dynamicPaths": { - "js": { "language": "js", "declPath": "${CMAKE_CURRENT_SOURCE_DIR}/${project}/js/index.ets", "ohmUrl": "${CMAKE_CURRENT_SOURCE_DIR}/${project}/js/index" } + "dependencies": { + "js": { "language": "js", "path": "${CMAKE_CURRENT_SOURCE_DIR}/${project}/js/index.ets", "ohmUrl": "${CMAKE_CURRENT_SOURCE_DIR}/${project}/js/index" } } } } diff --git a/ets2panda/test/tsconfig/test-decl/typecheck-decl/arktsconfig.in.decl.json b/ets2panda/test/tsconfig/test-decl/typecheck-decl/arktsconfig.in.decl.json index 3e875c427d9787a2f9e6a5456b96b0c9e17b5e21..030c6d78f4d8cf61d80313e5d523d26f10715212 100644 --- a/ets2panda/test/tsconfig/test-decl/typecheck-decl/arktsconfig.in.decl.json +++ b/ets2panda/test/tsconfig/test-decl/typecheck-decl/arktsconfig.in.decl.json @@ -5,8 +5,8 @@ "escompat": ["${PANDA_ROOT}/plugins/ets/stdlib/escompat"], "std": ["${PANDA_ROOT}/plugins/ets/stdlib/std"] }, - "dynamicPaths": { - "js": { "language": "js", "declPath": "${CMAKE_CURRENT_SOURCE_DIR}/${project}/js/index.ets", "ohmUrl": "${CMAKE_CURRENT_SOURCE_DIR}/${project}/js/index" } + "dependencies": { + "js": { "language": "js", "path": "${CMAKE_CURRENT_SOURCE_DIR}/${project}/js/index.ets", "ohmUrl": "${CMAKE_CURRENT_SOURCE_DIR}/${project}/js/index" } } } } diff --git a/ets2panda/test/unit/arktsconfig-parser/arktsconfig_include.cpp b/ets2panda/test/unit/arktsconfig-parser/arktsconfig_include.cpp index 73e5d7bf6edcddb017175b5ba6440f9dc04ac750..ac4c43adef3fa63f8c8883e585704d16b27f0a69 100644 --- a/ets2panda/test/unit/arktsconfig-parser/arktsconfig_include.cpp +++ b/ets2panda/test/unit/arktsconfig-parser/arktsconfig_include.cpp @@ -66,8 +66,7 @@ TEST_P(ArkTsConfigInclude, CheckInclude) auto param = GetParam(); ark::es2panda::util::DiagnosticEngine de; auto config = ark::es2panda::ArkTsConfig {*param.path, de}; - std::unordered_set parsedSet; - ASSERT_EQ(config.Parse(parsedSet), param.expected); + ASSERT_EQ(config.Parse(), param.expected); } INSTANTIATE_TEST_SUITE_P(ArkTsConfigIncludeSuite, ArkTsConfigInclude, diff --git a/ets2panda/test/unit/dynamic/dynamic_call_test.cpp b/ets2panda/test/unit/dynamic/dynamic_call_test.cpp index 2d2494db78979868b096d846a116315c88458849..6adab4bdb4eaf0428ffe92f575d89453feb327fd 100644 --- a/ets2panda/test/unit/dynamic/dynamic_call_test.cpp +++ b/ets2panda/test/unit/dynamic/dynamic_call_test.cpp @@ -88,7 +88,7 @@ public: specifiers.emplace_back(specifier); util::ImportPathManager::ImportMetadata importMetadata {util::ImportFlags::NONE, Language::Id::JS, "", "", ""}; auto importDecl = util::NodeAllocator::Alloc( - Allocator(), Allocator()->New("/tmp"), importMetadata, std::move(specifiers)); + Allocator(), Allocator()->New("/tmp"), std::move(importMetadata), std::move(specifiers)); compiler::InitScopesPhaseETS::RunExternalNode(importDecl, varbinder); varbinder->BuildImportDeclaration(importDecl); auto var = varbinder->TopScope()->Find(specifierName); diff --git a/ets2panda/test/unit/lsp/get_compiler_options_diagnostics_test.cpp b/ets2panda/test/unit/lsp/get_compiler_options_diagnostics_test.cpp index b53807cd622157cec2f39b79fc412426a177bc2e..03bea20317dc336f856e95a2fb4e54e9cf29a212 100644 --- a/ets2panda/test/unit/lsp/get_compiler_options_diagnostics_test.cpp +++ b/ets2panda/test/unit/lsp/get_compiler_options_diagnostics_test.cpp @@ -61,8 +61,7 @@ public: ark::es2panda::util::DiagnosticEngine *diagnosticEngine = reinterpret_cast(ctx)->diagnosticEngine; auto config = ark::es2panda::ArkTsConfig {filePaths[1], *diagnosticEngine}; - std::unordered_set parsedConfigPath; - config.Parse(parsedConfigPath); + config.Parse(); ark::es2panda::lsp::GetOptionDiagnostics(ctx, diagnostics); initializer.DestroyContext(ctx); @@ -279,10 +278,10 @@ function A(a:number, b:number) { "paths": { "std": ["./path1"] }, - "dynamicPaths": { + "dependencies": { "dynamic_import_tests": { "language": "invalid_lang", - "hasDecl": true + "path": "path.d.ets" } } } @@ -317,10 +316,10 @@ function A(a:number, b:number) { "paths": { "std": ["./path1"] }, - "dynamicPaths": { + "dependencies": { "dynamic_import_tests": { "language": "ts", - "hasDecl": true + "path": "path.d.ets" } } } diff --git a/ets2panda/test/unit/plugin/CMakeLists.txt b/ets2panda/test/unit/plugin/CMakeLists.txt index 672aff08e47fc7bb6d04a499fb451dc6d7bcff1e..09b82624dd73418681d9ae148c463405de38862a 100644 --- a/ets2panda/test/unit/plugin/CMakeLists.txt +++ b/ets2panda/test/unit/plugin/CMakeLists.txt @@ -105,7 +105,6 @@ set(PLUGIN_TESTS "plugin_proceed_to_state_update_function_expression compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" "plugin_proceed_to_state_create_ets_new_expression compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" "plugin_proceed_to_state_log_diagnostic_with_suggestion compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" - "use_plugin_to_test_export_table compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" "plugin_proceed_to_state_check_jsdoc compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" "plugin_proceed_to_state_test_global_func_call_dump compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" "plugin_proceed_to_state_test_interface_duplicate_setter compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" @@ -134,19 +133,12 @@ foreach(TEST_DATA IN ITEMS ${PLUGIN_TESTS}) endif() panda_target_include_directories(${TEST_NAME} PRIVATE ${ES2PANDA_PATH} - PRIVATE ${PANDA_ROOT}/libpandafile - PRIVATE ${PANDA_ROOT}/assembler PRIVATE ${OUTPUT_DIR} PUBLIC ${CMAKE_CURRENT_BINARY_DIR} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} - PUBLIC ${CMAKE_SOURCE_DIR}/libpandabase - PUBLIC ${CMAKE_SOURCE_DIR}/runtime - PUBLIC ${CMAKE_BINARY_DIR}/libpandabase - PUBLIC ${CMAKE_BINARY_DIR}/libpandafile/include - PUBLIC ${CMAKE_BINARY_DIR}/abc2program ${CMAKE_BINARY_DIR} ) - panda_target_link_libraries(${TEST_NAME} es2panda-public arkassembler arkbase arkfile abc2program) + panda_target_link_libraries(${TEST_NAME} es2panda-public) endforeach() add_custom_target(es2panda-plugin-test) diff --git a/ets2panda/test/unit/plugin/use_plugin_to_test_export_table.cpp b/ets2panda/test/unit/plugin/use_plugin_to_test_export_table.cpp deleted file mode 100644 index 1bfb5a30effa8c3c2fcb7d418bc7b2b046e4f4c1..0000000000000000000000000000000000000000 --- a/ets2panda/test/unit/plugin/use_plugin_to_test_export_table.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/** - * 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. - */ - -#include -#include -#include "file.h" -#include "macros.h" -#include "os/file.h" -#include "public/es2panda_lib.h" -#include "util.h" -#include "parser/program/program.h" -#include "ir/statements/blockStatement.h" -#include "ir/astNode.h" -#include "ir/statements/classDeclaration.h" -#include "ir/base/classDefinition.h" -#include "ir/base/methodDefinition.h" -#include "public/public.h" -#include "util/options.h" -#include "abc2program/abc2program_driver.h" - -// NOLINTBEGIN - -static es2panda_Impl *impl = nullptr; - -namespace { -constexpr size_t CLASS_DEFINITION_INDEX = 1; -constexpr size_t METHOD_DEFINITION_INDEX = 0; -constexpr size_t METHOD_BODY_INDEX = 2; - -enum Const { - LITERAL_INDEX_0 = 0, - LITERAL_INDEX_1 = 1, - LITERAL_INDEX_2 = 2, - LITERAL_INDEX_3 = 3, - LITERAL_INDEX_4 = 4, - LITERAL_INDEX_5 = 5, - EXPECTED_VALUE_1 = 1, - EXPECTED_VALUE_2 = 2, -}; - -const std::string SOURCE_CODE = - " function foo():void {\n" - " }\n" - " class A{}\n"; - -const std::string EXPECTED_CLASS_DEFINITION = "class A {\n public constructor() {}\n \n}\n"; - -const std::string EXPECTED_METHOD_DEFINITION = "function foo(): void {}\n"; - -int CheckLiteralValues(ark::es2panda::public_lib::Context *ctx, const ark::pandasm::Program &prog) -{ - auto file = ark::panda_file::OpenPandaFile(ctx->config->options->GetOutput()); - if (!file) { - return TEST_ERROR_CODE; - } - - auto literalArrIt = prog.literalarrayTable.find("0"); - if (literalArrIt == prog.literalarrayTable.end()) { - return TEST_ERROR_CODE; - } - auto &literalArr = literalArrIt->second.literals; - if (EXPECTED_VALUE_2 != std::get(literalArr[LITERAL_INDEX_1].value) || - EXPECTED_VALUE_1 != std::get(literalArr[LITERAL_INDEX_4].value)) { - return TEST_ERROR_CODE; - } - - const auto offsetA = std::get(literalArr[LITERAL_INDEX_0].value); - const auto stringDataA = file->GetStringData(ark::panda_file::File::EntityId(offsetA)); - auto stringA = std::string(reinterpret_cast(stringDataA.data), stringDataA.utf16Length); - - const auto offsetFoo = std::get(literalArr[LITERAL_INDEX_3].value); - const auto stringDataFoo = file->GetStringData(ark::panda_file::File::EntityId(offsetFoo)); - auto stringFoo = std::string(reinterpret_cast(stringDataFoo.data), stringDataFoo.utf16Length); - - if (stringA != EXPECTED_CLASS_DEFINITION) { - return TEST_ERROR_CODE; - } - - if (stringFoo != EXPECTED_METHOD_DEFINITION) { - return TEST_ERROR_CODE; - } - - return 0; -} - -void ProcessProgram(ark::es2panda::parser::Program *programPtr) -{ - auto *classDef = programPtr->Ast()->Statements()[CLASS_DEFINITION_INDEX]->AsClassDeclaration()->Definition(); - programPtr->AddDeclGenExportNode(classDef->DumpEtsSrc(), classDef); - - auto *methodDef = programPtr->Ast() - ->Statements()[METHOD_DEFINITION_INDEX] - ->AsClassDeclaration() - ->Definition() - ->AsClassDefinition() - ->Body()[METHOD_BODY_INDEX] - ->AsMethodDefinition(); - programPtr->AddDeclGenExportNode(methodDef->DumpEtsSrc(), methodDef); -} -} // namespace - -int main(int argc, char **argv) -{ - if (argc < MIN_ARGC) { - return INVALID_ARGC_ERROR_CODE; - } - - if (GetImpl() == nullptr) { - return NULLPTR_IMPL_ERROR_CODE; - } - impl = GetImpl(); - const char **args = const_cast(&(argv[1])); - auto config = impl->CreateConfig(argc - 1, args); - auto config_ = reinterpret_cast(config); - const_cast(config_->options)->SetWithExportTable(true); - auto context = impl->CreateContextFromString(config, SOURCE_CODE.data(), argv[argc - 1]); - if (context == nullptr) { - return NULLPTR_CONTEXT_ERROR_CODE; - } - - impl->ProceedToState(context, ES2PANDA_STATE_PARSED); - CheckForErrors("PARSE", context); - - impl->ProceedToState(context, ES2PANDA_STATE_BOUND); - CheckForErrors("BOUND", context); - - impl->ProceedToState(context, ES2PANDA_STATE_CHECKED); - CheckForErrors("CHECKED", context); - - auto program = impl->ContextProgram(context); - auto programPtr = reinterpret_cast(program); - ProcessProgram(programPtr); - - impl->ProceedToState(context, ES2PANDA_STATE_LOWERED); - CheckForErrors("LOWERED", context); - - impl->ProceedToState(context, ES2PANDA_STATE_ASM_GENERATED); - CheckForErrors("ASM", context); - - impl->ProceedToState(context, ES2PANDA_STATE_BIN_GENERATED); - CheckForErrors("BIN", context); - - auto *ctx = reinterpret_cast(context); - auto abc2program = new ark::abc2program::Abc2ProgramDriver(); - abc2program->Compile("./use_plugin_to_test_export_table.abc"); - auto res = CheckLiteralValues(ctx, abc2program->GetProgram()); - impl->DestroyConfig(config); - return res; -} - -// NOLINTEND \ No newline at end of file diff --git a/ets2panda/util/arktsconfig.cpp b/ets2panda/util/arktsconfig.cpp index d58d6220f2dbc5a84093c83c40a0112985db0cfb..7ee0d89b8d7084987bce9ddd892bebdbca708703 100644 --- a/ets2panda/util/arktsconfig.cpp +++ b/ets2panda/util/arktsconfig.cpp @@ -164,8 +164,7 @@ static std::string ResolveConfigLocation(const std::string &relPath, const std:: } std::optional ArkTsConfig::ParseExtends(const std::string &configPath, const std::string &extends, - const std::string &configDir, - std::unordered_set &parsedConfigPath) + const std::string &configDir) { auto basePath = ResolveConfigLocation(extends, configDir); if (!Check(!basePath.empty(), diagnostic::UNRESOLVABLE_CONFIG_PATH, {extends})) { @@ -177,7 +176,7 @@ std::optional ArkTsConfig::ParseExtends(const std::string &configPa } auto base = ArkTsConfig(basePath, diagnosticEngine_); - if (!Check(base.Parse(parsedConfigPath), diagnostic::WRONG_BASE_CONFIG, {extends})) { + if (!Check(base.Parse(), diagnostic::WRONG_BASE_CONFIG, {extends})) { return {}; } @@ -185,19 +184,18 @@ std::optional ArkTsConfig::ParseExtends(const std::string &configPa } #endif // ARKTSCONFIG_USE_FILESYSTEM -static std::string ValidDynamicLanguages() +static std::string ValidLanguages() { JsonArrayBuilder builder; for (auto &l : Language::All()) { - if (l.IsDynamic()) { - builder.Add(l.ToString()); - } + builder.Add(l.ToString()); } return std::move(builder).Build(); } bool ArkTsConfig::ParsePaths(const JsonObject::JsonObjPointer *options, PathsMap &pathsMap, const std::string &baseUrl) { + // Paths semantic should be simplified #23246 auto paths = options->get()->GetValue("paths"); if (paths == nullptr) { return true; @@ -227,70 +225,82 @@ bool ArkTsConfig::ParsePaths(const JsonObject::JsonObjPointer *options, PathsMap return true; } -static constexpr auto LANGUAGE = "language"; // CC-OFF(G.NAM.03-CPP) project code style -static constexpr auto DECL_PATH = "declPath"; // CC-OFF(G.NAM.03-CPP) project code style -static constexpr auto OHM_URL = "ohmUrl"; // CC-OFF(G.NAM.03-CPP) project code style - -bool ArkTsConfig::ParseDynamicPaths(const JsonObject::JsonObjPointer *options, - std::map &dynamicPathsMap, - const std::string &baseUrl) -{ - if (options == nullptr) { - return true; - } - auto dynamicPaths = options->get()->GetValue("dynamicPaths"); - if (dynamicPaths == nullptr) { - return true; - } - for (size_t keyIdx = 0; keyIdx < dynamicPaths->get()->GetSize(); ++keyIdx) { - auto &key = dynamicPaths->get()->GetKeyByIndex(keyIdx); - auto data = dynamicPaths->get()->GetValue(key); - if (!ParseSingleDynamicPath(key, data, dynamicPathsMap, baseUrl)) { - return false; - } - } - return true; -} +static constexpr auto LANGUAGE = "language"; // CC-OFF(G.NAM.03-CPP) project code style +static constexpr auto PATH = "path"; // CC-OFF(G.NAM.03-CPP) project code style +static constexpr auto OHM_URL = "ohmUrl"; // CC-OFF(G.NAM.03-CPP) project code style -bool ArkTsConfig::ParseSingleDynamicPath(const std::string &key, const JsonObject::JsonObjPointer *data, - std::map &dynamicPathsMap, - const std::string &baseUrl) +bool ArkTsConfig::ParseDependency(size_t keyIdx, const std::unique_ptr *dependencies, + std::map &dependenciesMap) { + // NOTE: arktsconfig.json structure check should be added #22687 + auto &key = dependencies->get()->GetKeyByIndex(keyIdx); if (IsAbsolute(key)) { - diagnosticEngine_.LogDiagnostic(diagnostic::DYNAMIC_PATHS_ABSOLUTE, util::DiagnosticMessageParams {key}); + diagnosticEngine_.LogDiagnostic(diagnostic::DEPENDENCIES_ABSOLUTE, util::DiagnosticMessageParams {key}); } - if (!Check(data != nullptr, diagnostic::INVALID_VALUE, {"dynamic path", key})) { + + auto data = dependencies->get()->GetValue(key); + if (!Check(data != nullptr, diagnostic::INVALID_VALUE, {"dependency", key})) { return false; } + auto langValue = data->get()->GetValue(LANGUAGE); - if (!Check(langValue != nullptr, diagnostic::INVALID_LANGUAGE, {LANGUAGE, key, ValidDynamicLanguages()})) { - return false; + std::optional lang = std::nullopt; + if (langValue != nullptr) { + lang = Language::FromString(*langValue); + } else { + lang = Language {Language::Id::ETS}; } - auto lang = Language::FromString(*langValue); - if (!Check(lang && lang->IsDynamic(), diagnostic::INVALID_LANGUAGE, {LANGUAGE, key, ValidDynamicLanguages()})) { + const auto &diagParams = util::DiagnosticMessageParams {LANGUAGE, key, ValidLanguages()}; + if (!Check(lang != std::nullopt && lang->IsValid(), diagnostic::INVALID_LANGUAGE, diagParams)) { return false; } + auto isSupportLang = compiler::Signatures::Dynamic::IsSupported(*lang); - if (!Check(isSupportLang, diagnostic::UNSUPPORTED_LANGUAGE_FOR_INTEROP, {lang->ToString()})) { + if (lang->IsDynamic() && !Check(isSupportLang, diagnostic::UNSUPPORTED_LANGUAGE_FOR_INTEROP, {lang->ToString()})) { return false; } + auto ohmUrl = data->get()->GetValue(OHM_URL); - if (ohmUrl == nullptr) { + if (ohmUrl == nullptr && lang && lang->IsDynamic()) { diagnosticEngine_.LogDiagnostic(diagnostic::NO_OHMURL, util::DiagnosticMessageParams {key}); } std::string ohmUrlValue = (ohmUrl == nullptr) ? "" : *ohmUrl; - auto declPathValue = data->get()->GetValue(DECL_PATH); - std::string normalizedDeclPath {}; - if (declPathValue != nullptr) { - normalizedDeclPath = IsAbsolute(*declPathValue) ? ark::os::GetAbsolutePath(*declPathValue) - : MakeAbsolute(*declPathValue, baseUrl); - if (!Check(ark::os::IsFileExists(normalizedDeclPath), diagnostic::INVALID_DYNAMIC_PATH, {key})) { + + auto pathValue = data->get()->GetValue(PATH); + std::string normalizedPath {}; + // NOTE(itrubachev): path in dependencies must be mandatory. Need to fix interop tests + if (pathValue != nullptr) { + normalizedPath = + IsAbsolute(*pathValue) ? ark::os::GetAbsolutePath(*pathValue) : MakeAbsolute(*pathValue, baseUrl_); + if (!Check(ark::os::IsFileExists(normalizedPath), diagnostic::INVALID_PATH, {key})) { + return false; + } + } else { + // NOTE(itrubachev): path in dependencies must be mandatory. Now it can be not specified only for interop + if (!Check(lang && lang->IsDynamic(), diagnostic::INVALID_PATH, {key})) { + return false; + } + } + auto res = dependenciesMap.insert({key, ArkTsConfig::ExternalModuleData(*lang, normalizedPath, ohmUrlValue)}); + return Check(res.second, diagnostic::DUPLICATED_DEPENDENCIES, {normalizedPath, key}); +} + +bool ArkTsConfig::ParseDependencies(const JsonObject::JsonObjPointer *options, + std::map &dependenciesMap) +{ + if (options == nullptr) { + return true; + } + auto dependencies = options->get()->GetValue(DEPENDENCIES); + if (dependencies == nullptr) { + return true; + } + for (size_t keyIdx = 0; keyIdx < dependencies->get()->GetSize(); ++keyIdx) { + if (!ParseDependency(keyIdx, dependencies, dependenciesMap)) { return false; } } - auto res = dynamicPathsMap.insert( - {ark::os::NormalizePath(key), ArkTsConfig::DynamicImportData(*lang, normalizedDeclPath, ohmUrlValue)}); - return Check(res.second, diagnostic::DUPLICATED_DYNAMIC_PATH, {normalizedDeclPath, key}); + return true; } template @@ -314,19 +324,6 @@ bool ArkTsConfig::ParseCollection(const JsonObject *config, Collection &out, con return true; } -void ArkTsConfig::ResolveConfigDependencies(std::unordered_map> &dependencies, - std::vector &dependencyPaths, - std::unordered_set &parsedConfigPath) -{ - for (auto dependency : dependencyPaths) { - auto config = std::make_shared(std::string_view(dependency), diagnosticEngine_); - if (!Check(config->Parse(parsedConfigPath), diagnostic::EMPTY_LIST, {dependency})) { - continue; - } - dependencies.emplace(config->Package(), std::move(config)); - } -} - std::optional ArkTsConfig::ReadConfig(const std::string &path) { std::ifstream inputStream(path); @@ -346,27 +343,19 @@ static std::string ValueOrEmptyString(const JsonObject::JsonObjPointer *json, co } static void ResolvePathInDependenciesImpl(ArkTsConfig *arktsConfig, - std::map, CompareByLength> &paths, - std::unordered_map &entries) + std::map, CompareByLength> &paths) { for (const auto &dependencyPath : arktsConfig->Paths()) { paths.emplace(dependencyPath.first, dependencyPath.second); } - if (!arktsConfig->Entry().empty()) { - entries.emplace(arktsConfig->Package(), arktsConfig->Entry()); - } - for (const auto &config : arktsConfig->Dependencies()) { - ResolvePathInDependenciesImpl(config.second.get(), paths, entries); - } } void ArkTsConfig::ResolveAllDependenciesInArkTsConfig() { - ResolvePathInDependenciesImpl(this, paths_, entries_); + ResolvePathInDependenciesImpl(this, paths_); } -bool ArkTsConfig::ParseCompilerOptions(std::string &arktsConfigDir, std::unordered_set &parsedConfigPath, - const JsonObject *arktsConfig) +bool ArkTsConfig::ParseCompilerOptions(std::string &arktsConfigDir, const JsonObject *arktsConfig) { auto compilerOptions = arktsConfig->GetValue(COMPILER_OPTIONS); // Parse "package" @@ -377,45 +366,25 @@ bool ArkTsConfig::ParseCompilerOptions(std::string &arktsConfigDir, std::unorder outDir_ = MakeAbsolute(ValueOrEmptyString(compilerOptions, OUT_DIR), arktsConfigDir); rootDir_ = MakeAbsolute(ValueOrEmptyString(compilerOptions, ROOT_DIR), arktsConfigDir); - // Parse "entry" - if (compilerOptions->get()->HasKey(ENTRY)) { - entry_ = MakeAbsolute(ValueOrEmptyString(compilerOptions, ENTRY), baseUrl_); - } - // Parse "useUrl" if (compilerOptions->get()->HasKey(USE_EMPTY_PACKAGE)) { useUrl_ = *(compilerOptions->get()->GetValue(USE_EMPTY_PACKAGE)); } - // Parse "dependencies" - auto concatPath = [this](const auto &val) { return MakeAbsolute(val, baseUrl_); }; - std::vector dependencyPaths; - if (compilerOptions->get()->HasKey(DEPENDENCIES)) { - ParseCollection(compilerOptions->get(), dependencyPaths, DEPENDENCIES, concatPath); - } - if (!dependencyPaths.empty()) { - ResolveConfigDependencies(dependencies_, dependencyPaths, parsedConfigPath); - } // Parse "paths" if (!ParsePaths(compilerOptions, paths_, baseUrl_)) { return false; } - // Parse "dynamicPaths" - if (!ParseDynamicPaths(compilerOptions, dynamicPaths_, baseUrl_)) { + // Parse "dependencies" + if (!ParseDependencies(compilerOptions, dependencies_)) { return false; } return true; } // CC-OFFNXT(huge_method[C++], G.FUN.01-CPP, G.FUD.05) solid logic -bool ArkTsConfig::Parse(std::unordered_set &parsedConfigPath) +bool ArkTsConfig::Parse() { - // For circurlar dependencies, just skip parsing - if (parsedConfigPath.find(configPath_) != parsedConfigPath.end()) { - return true; - } - parsedConfigPath.emplace(configPath_); - ES2PANDA_ASSERT(!isParsed_); isParsed_ = true; auto arktsConfigDir = ParentPath(ark::os::GetAbsolutePath(configPath_)); @@ -439,7 +408,7 @@ bool ArkTsConfig::Parse(std::unordered_set &parsedConfigPath) if (!Check(extends != nullptr, diagnostic::INVALID_JSON_TYPE, {EXTENDS, "string"})) { return false; } - const auto &base = ParseExtends(configPath_, *extends, arktsConfigDir, parsedConfigPath); + const auto &base = ParseExtends(configPath_, *extends, arktsConfigDir); if (!base.has_value()) { return false; } @@ -448,8 +417,7 @@ bool ArkTsConfig::Parse(std::unordered_set &parsedConfigPath) #endif // ARKTSCONFIG_USE_FILESYSTEM // Parse "compilerOptions" - if (arktsConfig->HasKey(COMPILER_OPTIONS) && - !ParseCompilerOptions(arktsConfigDir, parsedConfigPath, arktsConfig.get())) { + if (arktsConfig->HasKey(COMPILER_OPTIONS) && !ParseCompilerOptions(arktsConfigDir, arktsConfig.get())) { return false; } @@ -514,13 +482,9 @@ std::optional ArkTsConfig::ResolvePath(std::string_view path, bool return std::nullopt; }; - auto tryResolveWithDynamicPaths = [this, &path]() -> std::optional { - auto normalizedPath = ark::os::NormalizePath(std::string(path)); - for (const auto &[dynPath, _] : dynamicPaths_) { - // NOTE(dkofanov): #23877. Fail, if there is no direct match of normalized dynamic module path. - // It may be worth to take an attempt to resolve 'path' as relative to some defined dynamicPath in order to - // keep 'arktsconfig.json's smaller. - if (normalizedPath == dynPath) { + auto tryResolveWithDependencies = [this, &path]() -> std::optional { + for (const auto &[dynPath, _] : dependencies_) { + if (path == dynPath) { return dynPath; } } @@ -528,7 +492,7 @@ std::optional ArkTsConfig::ResolvePath(std::string_view path, bool }; if (isDynamic) { - auto result = tryResolveWithDynamicPaths(); + auto result = tryResolveWithDependencies(); if (result != std::nullopt) { return result; } @@ -539,7 +503,7 @@ std::optional ArkTsConfig::ResolvePath(std::string_view path, bool if (result != std::nullopt) { return result; } - return tryResolveWithDynamicPaths(); + return tryResolveWithDependencies(); } #ifdef ARKTSCONFIG_USE_FILESYSTEM diff --git a/ets2panda/util/arktsconfig.h b/ets2panda/util/arktsconfig.h index fec474785a06fc2237606dc25adce0ad5d7f9aff..a6ef154dee9865f4947e2ee008ef8f143dfe7584 100644 --- a/ets2panda/util/arktsconfig.h +++ b/ets2panda/util/arktsconfig.h @@ -89,10 +89,10 @@ public: }; #endif // ARKTSCONFIG_USE_FILESYSTEM - class DynamicImportData { + class ExternalModuleData { public: - explicit DynamicImportData(Language lang, std::string declPath, std::string ohmUrl) - : lang_(lang), declPath_(std::move(declPath)), ohmUrl_(std::move(ohmUrl)) + explicit ExternalModuleData(Language lang, std::string path, std::string ohmUrl) + : lang_(lang), path_(std::move(path)), ohmUrl_(std::move(ohmUrl)) { } @@ -101,9 +101,9 @@ public: return lang_; } - std::string_view DeclPath() const + std::string_view Path() const { - return declPath_; + return path_; } std::string_view OhmUrl() const @@ -113,7 +113,7 @@ public: private: Language lang_; - std::string declPath_ {}; + std::string path_ {}; std::string ohmUrl_ {}; }; @@ -121,7 +121,7 @@ public: : configPath_(configPath), diagnosticEngine_(de) { } - bool Parse(std::unordered_set &parsedConfigPath); + bool Parse(); std::optional ResolvePath(std::string_view path, bool isDynamic = false) const; @@ -148,22 +148,6 @@ public: { return outDir_; } - const std::unordered_map> &Dependencies() const - { - return dependencies_; - } - void ResetDependencies() - { - return dependencies_.clear(); - } - const std::string &Entry() const - { - return entry_; - } - const std::unordered_map &Entries() const - { - return entries_; - } const std::vector &Files() const { return files_; @@ -176,9 +160,9 @@ public: { return paths_; } - const std::map &DynamicPaths() const + const std::map &Dependencies() const { - return dynamicPaths_; + return dependencies_; } #ifdef ARKTSCONFIG_USE_FILESYSTEM const std::vector &Include() const @@ -194,23 +178,14 @@ public: bool Check(bool cond, const diagnostic::DiagnosticKind &diag, const util::DiagnosticMessageParams ¶ms); private: - bool ParseCompilerOptions(std::string &arktsConfigDir, std::unordered_set &parsedConfigPath, - const JsonObject *arktsConfig); + bool ParseCompilerOptions(std::string &arktsConfigDir, const JsonObject *arktsConfig); std::optional ParseExtends(const std::string &configPath, const std::string &extends, - const std::string &configDir, - std::unordered_set &parsedConfigPath); + const std::string &configDir); bool ParsePaths(const JsonObject::JsonObjPointer *options, PathsMap &pathsMap, const std::string &baseUrl); - bool ParseDynamicPaths(const JsonObject::JsonObjPointer *options, - std::map &dynamicPathsMap, - const std::string &baseUrl); - bool ParseSingleDynamicPath(const std::string &key, const JsonObject::JsonObjPointer *data, - std::map &dynamicPathsMap, - const std::string &baseUrl); + bool ParseDependencies(const JsonObject::JsonObjPointer *options, + std::map &dependenciesMap); template bool ParseCollection(const JsonObject *config, Collection &out, const std::string &target, Function &&constructor); - void ResolveConfigDependencies(std::unordered_map> &dependencies, - std::vector &dependencyPaths, - std::unordered_set &parsedConfigPath); std::optional ReadConfig(const std::string &path); private: @@ -225,9 +200,10 @@ private: static constexpr const char *OUT_DIR = "outDir"; static constexpr const char *ROOT_DIR = "rootDir"; static constexpr const char *DEPENDENCIES = "dependencies"; // CC-OFF(G.NAM.03,G.NAM.03-CPP) project code style - static constexpr const char *ENTRY = "entry"; // CC-OFF(G.NAM.03,G.NAM.03-CPP) project code style void Inherit(const ArkTsConfig &base); + bool ParseDependency(size_t keyIdx, const std::unique_ptr *dependencies, + std::map &dependenciesMap); bool isParsed_ = false; std::string configPath_; @@ -237,13 +213,9 @@ private: bool useUrl_ = false; std::string outDir_ {}; std::string rootDir_ {}; - std::string entry_ {}; PathsMap paths_ {}; - std::map dynamicPaths_ {}; + std::map dependencies_ {}; std::vector files_ {}; - std::unordered_map> dependencies_ {}; - // key: package name; value: entry's absolute path - std::unordered_map entries_; #ifdef ARKTSCONFIG_USE_FILESYSTEM std::vector include_ {}; std::vector exclude_ {}; diff --git a/ets2panda/util/diagnostic/arktsconfig_error.yaml b/ets2panda/util/diagnostic/arktsconfig_error.yaml index 2568bcd28449904e0a620df461f0554a248af0c4..e03085e195fe54e94504b6cdda1d2d643efcb11c 100644 --- a/ets2panda/util/diagnostic/arktsconfig_error.yaml +++ b/ets2panda/util/diagnostic/arktsconfig_error.yaml @@ -44,7 +44,7 @@ arkts_config_error: id: 8 message: Invalid {} value for '{}' with key '{}' -- name: DUPLICATED_DYNAMIC_PATH +- name: DUPLICATED_DEPENDENCIES id: 9 message: Duplicated dynamic path '{}' for key '{}' @@ -76,6 +76,10 @@ arkts_config_error: id: 16 message: Invalid destination file -- name: INVALID_DYNAMIC_PATH +- name: INVALID_PATH id: 17 - message: Invalid dynamic path '{}' + message: Invalid path for '{}' in dependencies + +- name: DEPENDENCIES_ABSOLUTE + id: 18 + message: "Don't use absolute path '{}' as key in 'dependencies'" \ No newline at end of file diff --git a/ets2panda/util/diagnostic/warning.yaml b/ets2panda/util/diagnostic/warning.yaml index ceea39765e799ccd919fee66c12b6981b939f5ac..e8164fa8858489fd7b4f94596d6500b968e76236 100644 --- a/ets2panda/util/diagnostic/warning.yaml +++ b/ets2panda/util/diagnostic/warning.yaml @@ -48,10 +48,6 @@ warning: id: 9 message: "Type alias generic parameter '{}' is not used in type annotation" -- name: DYNAMIC_PATHS_ABSOLUTE - id: 10 - message: "Don't use absolute path '{}' as key in 'dynamicPaths'" - - name: NO_OHMURL id: 11 message: "'ohmUrl' for module '{}' wasn't specified" diff --git a/ets2panda/util/importPathManager.cpp b/ets2panda/util/importPathManager.cpp index ae0e0b61c667f5aed3e51f57fa87adde4d1683e1..248d985b5269b032a6455bfe0165c748acddf002 100644 --- a/ets2panda/util/importPathManager.cpp +++ b/ets2panda/util/importPathManager.cpp @@ -25,6 +25,10 @@ #include "parser/program/program.h" #include "ir/expressions/literals/stringLiteral.h" +#include "abc2program_driver.h" +#include "checker/types/signature.h" +#include "compiler/lowering/ets/declGenPhase.h" + #ifdef USE_UNIX_SYSCALL #include #include @@ -58,6 +62,55 @@ static bool IsAbsolute(const std::string &path) #endif // ARKTSCONFIG_USE_FILESYSTEM } +void ImportPathManager::ProcessExternalModuleImport(ImportMetadata &importData) +{ + ES2PANDA_ASSERT(!IsAbsolute(std::string(importData.resolvedSource))); + auto it = arktsConfig_->Dependencies().find(std::string(importData.resolvedSource)); + ES2PANDA_ASSERT(it != arktsConfig_->Dependencies().cend()); + const auto &externalModuleImportData = it->second; + importData.lang = externalModuleImportData.GetLanguage().GetId(); + importData.declPath = externalModuleImportData.Path(); + + // process .d.ets "path" in "dependencies" + // process emptry "path" in dependencies, since in interop we allow imports without typecheck + if (!Helpers::EndsWith(std::string(externalModuleImportData.Path()), ".abc")) { + importData.importFlags |= ImportFlags::EXTERNAL_SOURCE_IMPORT; + importData.ohmUrl = externalModuleImportData.OhmUrl(); + return; + } + + // process .abc "path" in "dependencies" + ES2PANDA_ASSERT(Helpers::EndsWith(std::string(externalModuleImportData.Path()), ".abc")); + importData.importFlags |= ImportFlags::EXTERNAL_BINARY_IMPORT; + abc2program::Abc2ProgramDriver driver; + driver.Compile(std::string {externalModuleImportData.Path()}); + pandasm::Program &prog = driver.GetProgram(); + + // NOTE(itrubachev): support binary file after ark_link #26280 + auto etsGlobalRecord = std::find_if(prog.recordTable.begin(), prog.recordTable.end(), [](auto &record) { + auto annotations = record.second.metadata->GetAnnotations(); + auto moduleDeclAnno = std::find_if(annotations.begin(), annotations.end(), [](auto &anno) { + return anno.GetName() == compiler::DeclGenPhase::MODULE_DECLARATION_ANNOTATION; + }); + return moduleDeclAnno != annotations.end(); + }); + ES2PANDA_ASSERT(etsGlobalRecord != prog.recordTable.end()); + // rely on the following mangling: .ETSGLOBAL + auto etsGlobalSuffix = std::string(".") + std::string(compiler::Signatures::ETS_GLOBAL); + ES2PANDA_ASSERT(Helpers::EndsWith(etsGlobalRecord->second.name, etsGlobalSuffix)); + auto moduleName = + etsGlobalRecord->second.name.substr(0, etsGlobalRecord->second.name.size() - etsGlobalSuffix.size()); + importData.ohmUrl = moduleName; + + auto annotations = etsGlobalRecord->second.metadata->GetAnnotations(); + auto moduleDeclarationAnno = std::find_if(annotations.begin(), annotations.end(), [](auto &anno) { + return anno.GetName() == compiler::DeclGenPhase::MODULE_DECLARATION_ANNOTATION; + }); + ES2PANDA_ASSERT(moduleDeclarationAnno != annotations.end()); + auto declText = moduleDeclarationAnno->GetElements()[0].GetValue()->GetAsScalar()->GetValue(); + importData.declText = declText; +} + ImportPathManager::ImportMetadata ImportPathManager::GatherImportMetadata(parser::Program *program, ImportFlags importFlags, ir::StringLiteral *importPath) @@ -68,7 +121,7 @@ ImportPathManager::ImportMetadata ImportPathManager::GatherImportMetadata(parser // instead of 'AbsoluteName'. isDynamic_ = program->ModuleInfo().isDeclForDynamicStaticInterop; auto curModulePath = isDynamic_ ? program->ModuleInfo().moduleName : program->AbsoluteName(); - auto [resolvedImportPath, resolvedIsDynamic] = ResolvePath(curModulePath.Utf8(), importPath); + auto [resolvedImportPath, resolvedIsExternalModule] = ResolvePath(curModulePath.Utf8(), importPath); if (resolvedImportPath.empty()) { ES2PANDA_ASSERT(diagnosticEngine_.IsAnyError()); return ImportMetadata {util::ImportFlags::NONE, Language::Id::COUNT, ERROR_LITERAL}; @@ -78,14 +131,8 @@ ImportPathManager::ImportMetadata ImportPathManager::GatherImportMetadata(parser ImportMetadata importData {importFlags}; importData.resolvedSource = resolvedImportPath; - if (resolvedIsDynamic) { - ES2PANDA_ASSERT(!IsAbsolute(std::string(importData.resolvedSource))); - auto it = arktsConfig_->DynamicPaths().find(std::string(importData.resolvedSource)); - ES2PANDA_ASSERT(it != arktsConfig_->DynamicPaths().cend()); - const auto &dynImportData = it->second; - importData.lang = dynImportData.GetLanguage().GetId(); - importData.declPath = dynImportData.DeclPath(); - importData.ohmUrl = dynImportData.OhmUrl(); + if (resolvedIsExternalModule) { + ProcessExternalModuleImport(importData); } else { ES2PANDA_ASSERT(IsAbsolute(std::string(importData.resolvedSource))); importData.lang = ToLanguage(program->Extension()).GetId(); @@ -126,10 +173,6 @@ ImportPathManager::ResolvedPathRes ImportPathManager::ResolvePath(std::string_vi diagnosticEngine_.LogDiagnostic(diagnostic::EMPTY_IMPORT_PATH, util::DiagnosticMessageParams {}); return {*importPath}; } - const auto &entriesMap = arktsConfig_->Entries(); - if (auto it = entriesMap.find(importPath->Str().Mutf8()); it != entriesMap.cend()) { - return {UString(it->second, allocator_).View().Utf8()}; - } if (IsRelativePath(*importPath)) { const size_t pos = curModulePath.find_last_of("/\\"); ES2PANDA_ASSERT(pos != std::string::npos); @@ -222,11 +265,12 @@ void ImportPathManager::AddImplicitPackageImportToParseList(StringView packageDi srcPos_ = srcPos; ES2PANDA_ASSERT( IsAbsolute(packageDir.Mutf8())); // This should be an absolute path for 'AddToParseList' be able to resolve it. - AddToParseList({util::ImportFlags::IMPLICIT_PACKAGE_IMPORT, Language::Id::ETS, packageDir.Utf8(), - util::ImportPathManager::DUMMY_PATH}); + auto importMetadata = ImportMetadata {util::ImportFlags::IMPLICIT_PACKAGE_IMPORT, Language::Id::ETS, + packageDir.Utf8(), util::ImportPathManager::DUMMY_PATH}; + AddToParseList(importMetadata); } -void ImportPathManager::AddToParseList(const ImportMetadata importMetadata) +void ImportPathManager::AddToParseList(const ImportMetadata &importMetadata) { auto resolvedPath = importMetadata.resolvedSource; bool isDeclForDynamic = !IsAbsolute(std::string(resolvedPath)); // Avoiding interpreting dynamic-path as directory. @@ -307,14 +351,14 @@ StringView ImportPathManager::GetRealPath(StringView path) const return UString(realPath, allocator_).View(); } -std::string ImportPathManager::TryMatchDynamicPath(std::string_view fixedPath) const +std::string ImportPathManager::TryMatchDependencies(std::string_view fixedPath) const { // Probably, 'NormalizePath' should be moved to 'AppendExtensionOrIndexFileIfOmitted'. auto normalizedPath = ark::os::NormalizePath(std::string(fixedPath)); std::replace_if( normalizedPath.begin(), normalizedPath.end(), [&](auto &c) { return c == pathDelimiter_[0]; }, '/'); // NOTE(dkofanov): #23877. See also 'arktsconfig.cpp'. - if (arktsConfig_->DynamicPaths().find(normalizedPath) != arktsConfig_->DynamicPaths().cend()) { + if (arktsConfig_->Dependencies().find(normalizedPath) != arktsConfig_->Dependencies().cend()) { return normalizedPath; } return {}; @@ -342,7 +386,7 @@ ImportPathManager::ResolvedPathRes ImportPathManager::AppendExtensionOrIndexFile std::replace_if( fixedPath.begin(), fixedPath.end(), [&](auto &c) { return ((delim != c) && ((c == '\\') || (c == '/'))); }, delim); - if (auto resolvedDynamic = TryMatchDynamicPath(fixedPath); !resolvedDynamic.empty()) { + if (auto resolvedDynamic = TryMatchDependencies(fixedPath); !resolvedDynamic.empty()) { return {UString(resolvedDynamic, allocator_).View().Utf8(), true}; } @@ -416,22 +460,6 @@ util::StringView ImportPathManager::FormModuleNameSolelyByAbsolutePath(const uti return util::UString(name, allocator_).View(); } -template -static std::string TryFormDynamicModuleName(const DynamicPaths &dynPaths, const ModuleNameFormer &tryFormModuleName) -{ - for (auto const &[unitName, did] : dynPaths) { - if (did.DeclPath().empty()) { - // NOTE(dkofanov): related to #23698. Current assumption: if 'declPath' is absent, it is a pure-dynamic - // source, and, as soon it won't be parsed, no module should be created. - continue; - } - if (auto res = tryFormModuleName(unitName, did.DeclPath()); res) { - return res.value(); - } - } - return ""; -} - util::StringView ImportPathManager::FormModuleName(const util::Path &path, const lexer::SourcePosition &srcPos) { srcPos_ = srcPos; @@ -444,6 +472,10 @@ util::StringView ImportPathManager::FormModuleName(const util::Path &path) return FormModuleNameSolelyByAbsolutePath(path); } + if (!parseList_.empty() && parseList_[0].importData.IsExternalBinaryImport()) { + return util::UString(parseList_[0].importData.ohmUrl, allocator_).View(); + } + if (arktsConfig_->Package().empty() && !arktsConfig_->UseUrl()) { return path.GetFileName(); } @@ -460,13 +492,6 @@ util::StringView ImportPathManager::FormModuleName(const util::Path &path) return FormUnitName(unitName) + (relativePath.empty() || FormUnitName(unitName).empty() ? relativePath : ("." + relativePath)); }; - - for (auto const &[unitName, unitPath] : arktsConfig_->Entries()) { - if (unitPath == filePath) { - return util::UString(unitName, allocator_).View(); - } - } - if (auto res = tryFormModuleName(arktsConfig_->Package(), arktsConfig_->BaseUrl() + pathDelimiter_.data()); res) { return util::UString(res.value(), allocator_).View(); } @@ -483,9 +508,6 @@ util::StringView ImportPathManager::FormModuleName(const util::Path &path) return util::UString(res.value(), allocator_).View(); } } - if (auto dmn = TryFormDynamicModuleName(arktsConfig_->DynamicPaths(), tryFormModuleName); !dmn.empty()) { - return util::UString(dmn, allocator_).View(); - } // NOTE (hurton): as a last step, try resolving using the BaseUrl again without a path delimiter at the end if (auto res = tryFormModuleName(arktsConfig_->Package(), arktsConfig_->BaseUrl()); res) { return util::UString(res.value(), allocator_).View(); @@ -522,12 +544,6 @@ util::StringView ImportPathManager::FormRelativePath(const util::Path &path) return path.GetFileNameWithExtension(); } - for (auto const &[unitName, unitPath] : arktsConfig_->Entries()) { - if (unitPath == filePath) { - return util::UString(unitName, allocator_).View(); - } - } - if (auto res = tryFormRelativePath(arktsConfig_->BaseUrl(), arktsConfig_->Package()); res) { return util::UString(res.value(), allocator_).View(); } @@ -538,7 +554,7 @@ util::StringView ImportPathManager::FormRelativePath(const util::Path &path) } } - for (auto const &[unitName, unitPath] : arktsConfig_->DynamicPaths()) { + for (auto const &[unitName, unitPath] : arktsConfig_->Dependencies()) { if (auto res = tryFormRelativePath(unitName, unitName); res) { return util::UString(res.value(), allocator_).View(); } diff --git a/ets2panda/util/importPathManager.h b/ets2panda/util/importPathManager.h index 169960dff2f4533702a06388d342749e11489e7b..48026693ef57206b2bcae20e49c0f3cbc149c95b 100644 --- a/ets2panda/util/importPathManager.h +++ b/ets2panda/util/importPathManager.h @@ -37,6 +37,8 @@ enum class ImportFlags { NONE = 0U, DEFAULT_IMPORT = 1U << 1U, IMPLICIT_PACKAGE_IMPORT = 1U << 2U, + EXTERNAL_BINARY_IMPORT = 1U << 3U, // means .abc file in "path" in "dependencies" + EXTERNAL_SOURCE_IMPORT = 1U << 4U // means .d.ets file in "path" in "dependencies" }; } // namespace ark::es2panda::util @@ -79,7 +81,8 @@ public: Language::Id lang {Language::Id::COUNT}; std::string_view resolvedSource {}; std::string_view declPath {}; - std::string_view ohmUrl {}; + std::string ohmUrl {}; + std::string declText {}; // NOLINTEND(misc-non-private-member-variables-in-classes) bool HasSpecifiedDeclPath() const @@ -92,6 +95,16 @@ public: return (importFlags & ImportFlags::IMPLICIT_PACKAGE_IMPORT) != 0; } + bool IsExternalBinaryImport() const + { + return (importFlags & ImportFlags::EXTERNAL_BINARY_IMPORT) != 0; + } + + bool IsExternalSourceImport() const + { + return (importFlags & ImportFlags::EXTERNAL_SOURCE_IMPORT) != 0; + } + bool IsValid() const; }; @@ -140,7 +153,7 @@ public: ir::StringLiteral *importPath); void AddImplicitPackageImportToParseList(StringView packageDir, const lexer::SourcePosition &srcPos); - // API version for resolving paths. Kept only for API compatibility. Doesn't support 'dynamicPath'. + // API version for resolving paths. Kept only for API compatibility. Doesn't support 'dependencies'. util::StringView ResolvePathAPI(StringView curModulePath, ir::StringLiteral *importPath) const; void MarkAsParsed(StringView path); @@ -156,18 +169,19 @@ private: // `resolvedPath` is a realpath - if static path was resolved. // NOLINTBEGIN(misc-non-private-member-variables-in-classes) std::string_view resolvedPath; - bool resolvedIsDynamic {false}; + bool resolvedIsExternalModule {false}; // NOLINTEND(misc-non-private-member-variables-in-classes) }; ResolvedPathRes ResolvePath(std::string_view curModulePath, ir::StringLiteral *importPath) const; ResolvedPathRes ResolveAbsolutePath(const ir::StringLiteral &importPathNode) const; std::string_view DirOrDirWithIndexFile(StringView dir) const; ResolvedPathRes AppendExtensionOrIndexFileIfOmitted(StringView basePath) const; - std::string TryMatchDynamicPath(std::string_view fixedPath) const; + std::string TryMatchDependencies(std::string_view fixedPath) const; StringView GetRealPath(StringView path) const; + void ProcessExternalModuleImport(ImportMetadata &importData); public: - void AddToParseList(ImportMetadata importMetadata); + void AddToParseList(const ImportMetadata &importMetadata); #ifdef USE_UNIX_SYSCALL void UnixWalkThroughDirectoryAndAddToParseList(ImportMetadata importMetadata); #endif diff --git a/ets2panda/util/language.h b/ets2panda/util/language.h index aeeaf47177bb359657467a639db6d19f9c8ad6ba..e7604963e542e3ab688803f2ff35aa534bfc878c 100644 --- a/ets2panda/util/language.h +++ b/ets2panda/util/language.h @@ -77,6 +77,17 @@ public: ES2PANDA_UNREACHABLE(); } + bool IsValid() const + { + for (auto [id, _, isDynamic] : ID_TABLE) { + if (id_ == id) { + return true; + } + } + + return false; + } + bool operator==(const Language &l) const { return id_ == l.id_; diff --git a/ets2panda/util/options.cpp b/ets2panda/util/options.cpp index 9f42bc27ab6b00253434bd595348cb5f457bbad6..680847e510b78218222df44ca41a3eda34e1d345 100644 --- a/ets2panda/util/options.cpp +++ b/ets2panda/util/options.cpp @@ -392,15 +392,12 @@ bool Options::ProcessEtsSpecificOptions() std::optional Options::ParseArktsConfig() { auto config = ArkTsConfig {GetArktsconfig(), diagnosticEngine_}; - std::unordered_set parsedConfigPath; - if (!config.Parse(parsedConfigPath)) { + if (!config.Parse()) { diagnosticEngine_.LogDiagnostic(diagnostic::INVALID_ARKTSCONFIG, util::DiagnosticMessageParams {util::StringView(GetArktsconfig())}); return std::nullopt; } config.ResolveAllDependenciesInArkTsConfig(); - // Don't need dependencies anymore, since all necessary information have been moved to current config - config.ResetDependencies(); return std::make_optional(config); } diff --git a/ets2panda/util/options.yaml b/ets2panda/util/options.yaml index c017d1347e1b16f92ab880eb576581e9676d0749..fb662ff9f4baa908e8646db6e0237c147d087205 100644 --- a/ets2panda/util/options.yaml +++ b/ets2panda/util/options.yaml @@ -95,11 +95,6 @@ options: default: false description: Dump debug info -- name: with-export-table - type: bool - default: false - description: enable abc file with export table info - - name: opt-level type: int default: 0 @@ -183,6 +178,11 @@ options: default: "" description: Output path for generated static declaration files +- name: emit-declaration + type: bool + default: false + description: Emit declaration to .abc file + - name: thread type: int default: 0