diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index f8f1ec7e37942851ef8706f99b100afe5a047649..87be7c3425145ed8e0f26f2d3bb08cf250faf95e 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -3600,6 +3600,70 @@ checker::Type *ETSAnalyzer::Check(ir::TSNonNullExpression *expr) const return expr->TsType(); } +// Helps to prevent searching for the imported file among external sources if it is the entry program +static parser::Program *SelectEntryOrExternalProgram(varbinder::ETSBinder *etsBinder, + const util::StringView &importPath) +{ + if (importPath.Is(etsBinder->GetGlobalRecordTable()->Program()->AbsoluteName().Mutf8())) { + return etsBinder->GetGlobalRecordTable()->Program(); + } + + auto programList = etsBinder->GetProgramList(importPath); + return !programList.empty() ? programList.front() : nullptr; +} + +static varbinder::Variable *FindNameForImportNamespace(ETSChecker *checker, util::StringView &searchName, + ETSObjectType *baseType) +{ + /* This function try to find name1.name2, name1.A in file file1.ets, + * ./file1.ets: + * import * as name1 from "./file2" + * + * ./file2.ets: + * import * as name2 from "./file3" + * import {A} from "./file3" + * export {name2} + * export {A} + * + * ./file3.ets + * export class A{} + * + * 1. Find in file2->program->ast->scope first + * 2. Find in varbinder->selectiveExportAliasMultimap second + * if both found, return variable + */ + auto declNode = baseType->GetDeclNode(); + if (!declNode->IsIdentifier()) { + return nullptr; + } + if (declNode->Parent() == nullptr || declNode->Parent()->Parent() == nullptr) { + return nullptr; + } + auto importDeclNode = declNode->Parent()->Parent(); + if (!importDeclNode->IsETSImportDeclaration()) { + return nullptr; + } + + auto importDecl = importDeclNode->AsETSImportDeclaration(); + + parser::Program *program = SelectEntryOrExternalProgram( + static_cast(checker->VarBinder()), importDecl->ImportMetadata().resolvedSource); + + auto &bindings = program->Ast()->Scope()->Bindings(); + + if (auto result = bindings.find(searchName); result != bindings.end()) { + auto &sMap = checker->VarBinder() + ->AsETSBinder() + ->GetSelectiveExportAliasMultimap() + .find(importDecl->ImportMetadata().resolvedSource) + ->second; + if (auto it = sMap.find(searchName); it != sMap.end()) { + return result->second; + } + } + return nullptr; +} + checker::Type *ETSAnalyzer::Check(ir::TSQualifiedName *expr) const { ETSChecker *checker = GetETSChecker(); @@ -3614,6 +3678,10 @@ checker::Type *ETSAnalyzer::Check(ir::TSQualifiedName *expr) const } varbinder::Variable *prop = baseType->AsETSObjectType()->GetProperty(searchName, checker::PropertySearchFlags::SEARCH_DECL); + + if (prop == nullptr) { + prop = FindNameForImportNamespace(GetETSChecker(), searchName, baseType->AsETSObjectType()); + } // NOTE(dslynko): in debugger evaluation mode must lazily generate module's properties here. if (prop == nullptr) { checker->LogError(diagnostic::NONEXISTENT_TYPE, {expr->Right()->Name()}, expr->Right()->Start()); diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/importExportDecls.cpp b/ets2panda/compiler/lowering/ets/topLevelStmts/importExportDecls.cpp index aa76dbdc4501ac5ca7613deefe713b487ccb93d5..2a56cb3782bed90e6032a17d471df696290e2c38 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/importExportDecls.cpp +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/importExportDecls.cpp @@ -214,10 +214,14 @@ void ImportExportDecls::VisitETSImportDeclaration(ir::ETSImportDeclaration *impo if (spec->IsImportSpecifier()) { importedSpecifiersForExportCheck_.emplace(spec->AsImportSpecifier()->Local()->Name(), spec->AsImportSpecifier()->Imported()->Name()); - } - if (spec->IsImportDefaultSpecifier()) { + } else if (spec->IsImportDefaultSpecifier()) { importedSpecifiersForExportCheck_.emplace(spec->AsImportDefaultSpecifier()->Local()->Name(), spec->AsImportDefaultSpecifier()->Local()->Name()); + } else if (spec->IsImportNamespaceSpecifier()) { + importedSpecifiersForExportCheck_.emplace(spec->AsImportNamespaceSpecifier()->Local()->Name(), + spec->AsImportNamespaceSpecifier()->Local()->Name()); + } else { + ES2PANDA_UNREACHABLE(); } } } diff --git a/ets2panda/test/isolated_declgen/eitest_import_all_1.ets b/ets2panda/test/isolated_declgen/eitest_import_all_1.ets new file mode 100644 index 0000000000000000000000000000000000000000..569fa53b4dd472ebefa698402a7ea487ee26a5c1 --- /dev/null +++ b/ets2panda/test/isolated_declgen/eitest_import_all_1.ets @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as ns from "./eitest_import_all_2" +const f: ns.qw.Root.Foo = new ns.qw.Root.Foo() \ No newline at end of file diff --git a/ets2panda/test/isolated_declgen/eitest_import_all_1_ne.ets b/ets2panda/test/isolated_declgen/eitest_import_all_1_ne.ets new file mode 100644 index 0000000000000000000000000000000000000000..8350e64f9112d6920edac99072e60f4d6b6a3258 --- /dev/null +++ b/ets2panda/test/isolated_declgen/eitest_import_all_1_ne.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as ns from "./eitest_import_all_2_ne" +const f: ns.qw.Root.Foo = {x:10} + +/* @@? eitest_import_all_1_ne.ets:17:13 Error TypeError: 'qw' type does not exist. */ +/* @@? eitest_import_all_1_ne.ets:17:16 Error TypeError: 'Root' type does not exist. */ +/* @@? eitest_import_all_1_ne.ets:17:21 Error TypeError: 'Foo' type does not exist. */ \ No newline at end of file diff --git a/ets2panda/test/isolated_declgen/eitest_import_all_2.ets b/ets2panda/test/isolated_declgen/eitest_import_all_2.ets new file mode 100644 index 0000000000000000000000000000000000000000..831223c23953eca24ab809a859f490ef758b3e5b --- /dev/null +++ b/ets2panda/test/isolated_declgen/eitest_import_all_2.ets @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as qw from "./eitest_import_all_3" +export {qw} \ No newline at end of file diff --git a/ets2panda/test/isolated_declgen/eitest_import_all_2_ne.ets b/ets2panda/test/isolated_declgen/eitest_import_all_2_ne.ets new file mode 100644 index 0000000000000000000000000000000000000000..8035ef478c3a0121593b5c91afe7331888d37519 --- /dev/null +++ b/ets2panda/test/isolated_declgen/eitest_import_all_2_ne.ets @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as qw from "./eitest_import_all_3" \ No newline at end of file diff --git a/ets2panda/test/isolated_declgen/eitest_import_all_3.ets b/ets2panda/test/isolated_declgen/eitest_import_all_3.ets new file mode 100644 index 0000000000000000000000000000000000000000..2327e442364fbe5998b075926efb0d0c3e557297 --- /dev/null +++ b/ets2panda/test/isolated_declgen/eitest_import_all_3.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export namespace Root{ + export class Foo{ + x:number=1 + } +} +export class B{} \ No newline at end of file diff --git a/ets2panda/test/isolated_declgen/eitest_import_all_4.ets b/ets2panda/test/isolated_declgen/eitest_import_all_4.ets new file mode 100644 index 0000000000000000000000000000000000000000..ff520593414d86d3d70a089601e03dbdf1864700 --- /dev/null +++ b/ets2panda/test/isolated_declgen/eitest_import_all_4.ets @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as ns from "./eitest_import_all_5" +const t: ns.B = new ns.B() \ No newline at end of file diff --git a/ets2panda/test/isolated_declgen/eitest_import_all_4_ne.ets b/ets2panda/test/isolated_declgen/eitest_import_all_4_ne.ets new file mode 100644 index 0000000000000000000000000000000000000000..57e068b6d1bbbefc29e614a1e875dd9c75349b0c --- /dev/null +++ b/ets2panda/test/isolated_declgen/eitest_import_all_4_ne.ets @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as ns from "./eitest_import_all_5_ne" +const t: ns.B = new ns.B() + +/* @@? eitest_import_all_4_ne.ets:17:13 Error TypeError: 'B' type does not exist. */ \ No newline at end of file diff --git a/ets2panda/test/isolated_declgen/eitest_import_all_5.ets b/ets2panda/test/isolated_declgen/eitest_import_all_5.ets new file mode 100644 index 0000000000000000000000000000000000000000..a2b2bca713b192ab65963211687d26d575083f0d --- /dev/null +++ b/ets2panda/test/isolated_declgen/eitest_import_all_5.ets @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {B} from "./eitest_import_all_3" +export {B} \ No newline at end of file diff --git a/ets2panda/test/isolated_declgen/eitest_import_all_5_ne.ets b/ets2panda/test/isolated_declgen/eitest_import_all_5_ne.ets new file mode 100644 index 0000000000000000000000000000000000000000..98c9624c5faf7a4f8c604fc8c82a122d94b012fa --- /dev/null +++ b/ets2panda/test/isolated_declgen/eitest_import_all_5_ne.ets @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {B} from "./eitest_import_all_3" \ No newline at end of file