From 88251c7e6bf21ce03b118da5819da270eaa163b7 Mon Sep 17 00:00:00 2001 From: Vivien Voros Date: Tue, 7 May 2024 11:26:46 +0200 Subject: [PATCH] Fix folder import if index.ts file is missing Solved the missing index.ts/index.ets file issue by importing folder, which does not contain package. Fixes internal issue #16778 Change-Id: If7b5e62394c837fe148f213dbd7a089f7e74df69 Signed-off-by: Vivien Voros --- ets2panda/parser/ETSparser.cpp | 16 +- .../file-expected.txt | 353 ++++++++++++++++++ .../folderWithoutIndexAndPackage/file.ets | 16 + .../import_folder-expected.txt | 211 +++++++++++ .../ets/folder_import_index/import_folder.ets | 16 + ets2panda/util/importPathManager.cpp | 21 ++ ets2panda/util/importPathManager.h | 3 +- ets2panda/varbinder/ETSBinder.cpp | 5 +- 8 files changed, 631 insertions(+), 10 deletions(-) create mode 100644 ets2panda/test/parser/ets/folder_import_index/folderWithoutIndexAndPackage/file-expected.txt create mode 100644 ets2panda/test/parser/ets/folder_import_index/folderWithoutIndexAndPackage/file.ets create mode 100644 ets2panda/test/parser/ets/folder_import_index/import_folder-expected.txt create mode 100644 ets2panda/test/parser/ets/folder_import_index/import_folder.ets diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index 2646d717a0..017504eaf6 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -151,6 +151,10 @@ void ETSParser::ParseProgram(ScriptKind kind) // NOTE(user): handle multiple sourceFiles } + importPathManager_->InsertModuleInfo( + GetProgram()->AbsoluteName(), + util::ImportPathManager::ModuleInfo {(IsETSModule()) ? GetProgram()->FileName() : util::StringView(), false}); + ArenaVector statements(Allocator()->Adapter()); auto decl = ParsePackageDeclaration(); if (decl != nullptr) { @@ -2357,16 +2361,14 @@ ir::Statement *ETSParser::ParseFunctionStatement([[maybe_unused]] const Statemen ir::ETSPackageDeclaration *ETSParser::ParsePackageDeclaration() { auto startLoc = Lexer()->GetToken().Start(); - if (Lexer()->GetToken().Type() != lexer::TokenType::KEYW_PACKAGE) { if (!IsETSModule() && GetProgram()->IsEntryPoint()) { - // NOTE(rsipka): consider adding a filename name as module name to entry points as well - importPathManager_->InsertModuleInfo(GetProgram()->AbsoluteName(), - util::ImportPathManager::ModuleInfo {util::StringView(""), false}); return nullptr; } - importPathManager_->InsertModuleInfo(GetProgram()->AbsoluteName(), + + importPathManager_->UpdateModuleInfo(GetProgram()->AbsoluteName(), util::ImportPathManager::ModuleInfo {GetProgram()->FileName(), false}); + GetProgram()->SetPackageName(GetProgram()->FileName()); return nullptr; } @@ -2385,9 +2387,7 @@ ir::ETSPackageDeclaration *ETSParser::ParsePackageDeclaration() GetProgram()->SetPackageName(packageName); // NOTE(rsipka): handle these two cases, check that is it really required - importPathManager_->InsertModuleInfo(GetProgram()->AbsoluteName(), - util::ImportPathManager::ModuleInfo {packageName, true}); - importPathManager_->InsertModuleInfo(GetProgram()->ResolvedFilePath(), + importPathManager_->UpdateModuleInfo(GetProgram()->AbsoluteName(), util::ImportPathManager::ModuleInfo {packageName, true}); return packageDeclaration; diff --git a/ets2panda/test/parser/ets/folder_import_index/folderWithoutIndexAndPackage/file-expected.txt b/ets2panda/test/parser/ets/folder_import_index/folderWithoutIndexAndPackage/file-expected.txt new file mode 100644 index 0000000000..98c2ee556d --- /dev/null +++ b/ets2panda/test/parser/ets/folder_import_index/folderWithoutIndexAndPackage/file-expected.txt @@ -0,0 +1,353 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 5 + }, + "end": { + "line": 16, + "column": 6 + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 10, + "loc": { + "start": { + "line": 16, + "column": 15 + }, + "end": { + "line": 16, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 5 + }, + "end": { + "line": 16, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 5 + }, + "end": { + "line": 16, + "column": 17 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 5 + }, + "end": { + "line": 16, + "column": 6 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 16, + "column": 12 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 5 + }, + "end": { + "line": 16, + "column": 17 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 17, + "column": 1 + } + } +} diff --git a/ets2panda/test/parser/ets/folder_import_index/folderWithoutIndexAndPackage/file.ets b/ets2panda/test/parser/ets/folder_import_index/folderWithoutIndexAndPackage/file.ets new file mode 100644 index 0000000000..31df2698c7 --- /dev/null +++ b/ets2panda/test/parser/ets/folder_import_index/folderWithoutIndexAndPackage/file.ets @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 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. + */ + +let a : int = 10; diff --git a/ets2panda/test/parser/ets/folder_import_index/import_folder-expected.txt b/ets2panda/test/parser/ets/folder_import_index/import_folder-expected.txt new file mode 100644 index 0000000000..bff7d1250c --- /dev/null +++ b/ets2panda/test/parser/ets/folder_import_index/import_folder-expected.txt @@ -0,0 +1,211 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ImportDeclaration", + "source": { + "type": "StringLiteral", + "value": "./folderWithoutIndexAndPackage", + "loc": { + "start": { + "line": 16, + "column": 22 + }, + "end": { + "line": 16, + "column": 54 + } + } + }, + "specifiers": [ + { + "type": "ImportNamespaceSpecifier", + "local": { + "type": "Identifier", + "name": "all", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 13 + }, + "end": { + "line": 16, + "column": 16 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 8 + }, + "end": { + "line": 16, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 54 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 17, + "column": 1 + } + } +} +SyntaxError: Cannot find package in directory: ./folderWithoutIndexAndPackage [import_folder.ets:16:22] diff --git a/ets2panda/test/parser/ets/folder_import_index/import_folder.ets b/ets2panda/test/parser/ets/folder_import_index/import_folder.ets new file mode 100644 index 0000000000..7c93ae2d1e --- /dev/null +++ b/ets2panda/test/parser/ets/folder_import_index/import_folder.ets @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 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 * as all from "./folderWithoutIndexAndPackage" diff --git a/ets2panda/util/importPathManager.cpp b/ets2panda/util/importPathManager.cpp index 9b3ecd26f8..24f0ded001 100644 --- a/ets2panda/util/importPathManager.cpp +++ b/ets2panda/util/importPathManager.cpp @@ -126,6 +126,8 @@ void ImportPathManager::UnixWalkThroughDirectoryAndAddToParseList(const StringVi void ImportPathManager::AddToParseList(const StringView &resolvedPath, bool isDefaultImport) { if (ark::os::file::File::IsDirectory(resolvedPath.Mutf8())) { + InsertModuleInfo(resolvedPath, util::ImportPathManager::ModuleInfo {StringView(), false}); + #ifdef USE_UNIX_SYSCALL UnixWalkThroughDirectoryAndAddToParseList(resolvedPath, isDefaultImport); #else @@ -146,6 +148,8 @@ void ImportPathManager::AddToParseList(const StringView &resolvedPath, bool isDe } } + InsertModuleInfo(resolvedPath, util::ImportPathManager::ModuleInfo {StringView(), false}); + auto &dynamicPaths = arktsConfig_->DynamicPaths(); if (auto it = dynamicPaths.find(resolvedPath.Mutf8()); it != dynamicPaths.cend()) { parseList_.emplace(parseList_.begin(), ParseInfo {resolvedPath, false}); @@ -204,6 +208,23 @@ void ImportPathManager::InsertModuleInfo(const util::StringView &path, moduleList_.insert({path, moduleInfo}); } +void ImportPathManager::UpdateModuleInfo(const util::StringView &path, + const util::ImportPathManager::ModuleInfo &moduleInfo) +{ + auto it = moduleList_.find(path); + ASSERT(it != moduleList_.end()); + + it->second = moduleInfo; + if (moduleInfo.isPackageModule) { + auto pdir = moduleList_.find(UString(ark::os::GetParentDir(path.Mutf8()), allocator_).View()); + if (pdir != moduleList_.end()) { + pdir->second = moduleInfo; + } else { + InsertModuleInfo(UString(ark::os::GetParentDir(path.Mutf8()), allocator_).View(), moduleInfo); + } + } +} + const ArenaMap &ImportPathManager::ModuleList() const { return moduleList_; diff --git a/ets2panda/util/importPathManager.h b/ets2panda/util/importPathManager.h index ceddf99643..3a246ca001 100644 --- a/ets2panda/util/importPathManager.h +++ b/ets2panda/util/importPathManager.h @@ -61,8 +61,9 @@ public: StringView ResolvePath(const StringView ¤tModulePath, const StringView &importPath) const; void AddToParseList(const StringView &path, bool isDefaultImport); const ArenaVector &ParseList(); + void InsertModuleInfo(const util::StringView &path, const util::ImportPathManager::ModuleInfo &moduleInfo); ImportData GetImportData(const util::StringView &path, const ScriptExtension &extension) const; - void InsertModuleInfo(const util::StringView &path, const ModuleInfo &moduleInfo); + void UpdateModuleInfo(const util::StringView &path, const ModuleInfo &moduleInfo); const ArenaMap &ModuleList() const; void MarkAsParsed(const StringView &path); diff --git a/ets2panda/varbinder/ETSBinder.cpp b/ets2panda/varbinder/ETSBinder.cpp index 6d61725646..eae8f5d4b4 100644 --- a/ets2panda/varbinder/ETSBinder.cpp +++ b/ets2panda/varbinder/ETSBinder.cpp @@ -682,7 +682,10 @@ ArenaVector ETSBinder::GetExternalProgram(const util::StringV { const auto &extRecords = globalRecordTable_.Program()->ExternalSources(); - auto [name, _] = GetModuleInfo(sourceName); + auto [name, isPackage] = GetModuleInfo(sourceName); + if (ark::os::file::File::IsDirectory(sourceName.Mutf8()) && !isPackage) { + ThrowError(importPath->Start(), "Cannot find package in directory: " + importPath->Str().Mutf8()); + } auto res = extRecords.find(name); if (res == extRecords.end()) { ThrowError(importPath->Start(), "Cannot find import: " + importPath->Str().Mutf8()); -- Gitee