From 3ec04d5e907436a5ceb8f833c7138d2ee8ced199 Mon Sep 17 00:00:00 2001 From: xuxinjie4 Date: Wed, 4 Dec 2024 18:14:38 +0800 Subject: [PATCH] Implement namespace and refactor etsscript Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/IB9NSQ?from=project-issue Description: Need to support namespace in arkts2.0 Signed-off-by: xuxinjie4 --- ets2panda/BUILD.gn | 8 +- ets2panda/CMakeLists.txt | 4 +- .../ast_verifier/checkConstProperties.cpp | 3 +- .../ast_verifier/everyChildHasValidParent.cpp | 4 +- ets2panda/ast_verifier/helpers.cpp | 12 +- ets2panda/ast_verifier/nodeHasParent.cpp | 6 +- ets2panda/checker/ETSAnalyzer.cpp | 16 +- ets2panda/checker/ETSAnalyzerUnreachable.cpp | 4 +- ets2panda/checker/ETSchecker.h | 4 + ets2panda/checker/SemanticAnalyzer.h | 4 +- ets2panda/checker/TSAnalyzerUnreachable.cpp | 14 +- ets2panda/checker/ets/assignAnalyzer.cpp | 4 +- ets2panda/checker/ets/dynamic.cpp | 4 +- ets2panda/checker/ets/helpers.cpp | 74 +++---- ets2panda/checker/ets/object.cpp | 50 ++++- ets2panda/checker/ets/typeCheckingHelpers.cpp | 7 +- ets2panda/checker/ets/typeCreation.cpp | 2 +- ets2panda/checker/ets/utilityTypeHandlers.cpp | 19 +- ets2panda/compiler/core/ASTCompiler.h | 4 +- .../compiler/core/ETSCompilerUnrechable.cpp | 14 +- ets2panda/compiler/core/ETSemitter.cpp | 2 +- .../compiler/core/JSCompilerUnreachable.cpp | 14 +- .../compiler/lowering/ets/enumLowering.cpp | 88 +++++---- .../compiler/lowering/ets/enumLowering.h | 16 +- .../ets/topLevelStmts/globalClassHandler.cpp | 185 ++++++++++++++++-- .../ets/topLevelStmts/globalClassHandler.h | 18 +- .../ets/topLevelStmts/globalDeclTransformer.h | 18 +- .../ets/topLevelStmts/importExportDecls.cpp | 30 ++- .../ets/topLevelStmts/importExportDecls.h | 3 + .../lowering/scopesInit/scopesInitPhase.cpp | 4 +- .../lowering/scopesInit/scopesInitPhase.h | 2 +- ets2panda/evaluate/scopedDebugInfoPlugin.cpp | 7 +- ets2panda/ir/annotationAllowed.h | 7 +- ets2panda/ir/astNodeMapping.h | 6 +- ets2panda/ir/base/classDefinition.h | 19 +- ets2panda/ir/base/namespaceDefinition.cpp | 122 ------------ ets2panda/ir/base/namespaceDefinition.h | 165 ---------------- .../ir/ets/{etsScript.h => etsModule.cpp} | 56 +++--- ets2panda/ir/ets/etsModule.h | 111 +++++++++++ ets2panda/ir/ts/tsQualifiedName.cpp | 6 +- ets2panda/ir/visitor/IterateAstVisitor.h | 3 +- ets2panda/parser/ETSparser.cpp | 31 ++- ets2panda/parser/ETSparser.h | 24 ++- ets2panda/parser/ETSparserAnnotations.cpp | 22 ++- ets2panda/parser/ETSparserClasses.cpp | 5 +- ets2panda/parser/ETSparserEnums.cpp | 4 +- ets2panda/parser/ETSparserNamespaces.cpp | 152 +++++++------- ets2panda/parser/ETSparserStatements.cpp | 22 ++- ets2panda/parser/ETSparserTypes.cpp | 2 +- ets2panda/public/CMakeLists.txt | 4 +- .../public/headers_parser/supported_types.py | 4 +- .../ast/compiler/ets/ambient_namesapce01.sts | 22 +++ .../ast/compiler/ets/ambient_namesapce02.sts | 22 +++ .../ast/compiler/ets/ambient_namesapce03.sts | 24 +++ .../ast/compiler/ets/ambient_namesapce04.sts | 24 +++ .../ast/compiler/ets/ambient_namesapce05.sts | 25 +++ .../ast/compiler/ets/ambient_namesapce06.sts | 27 +++ .../ast/compiler/ets/ambient_namesapce07.sts | 23 +++ ...notationUsage_conflict_for_namespace01.sts | 28 +++ ...notationUsage_conflict_for_namespace02.sts | 28 +++ ...otationUsage_duplicate_for_namespace01.sts | 34 ++++ ...otationUsage_duplicate_for_namespace02.sts | 34 ++++ .../ets/namespace_export_invalid01.sts | 23 +++ .../ets/namespace_export_invalid02.sts | 23 +++ .../ets/namespace_tests/namespace.sts | 25 +++ .../namespace_access_violation.sts | 68 +++++++ ...access_violation_circular_dependencies.sts | 25 +++ .../namespace_access_violation_conflicts.sts | 24 +++ .../namespace_access_violation_exports.sts | 23 +++ ...pace_access_violation_import_conflicts.sts | 29 +++ ...space_access_violation_merge_conflicts.sts | 21 ++ ...mespace_access_violation_nested_scopes.sts | 64 ++++++ ...ce_access_violation_non_exported_merge.sts | 29 +++ ...pace_access_violation_scope_resolution.sts | 25 +++ ...pace_access_violation_undefined_scopes.sts | 27 +++ .../namespace_ambient_export01.sts} | 11 +- .../namespace_ambient_export02.sts | 18 ++ .../namespace_ambient_export03.sts | 21 ++ .../namespace_ambient_export04.sts | 19 ++ .../namespace_tests/namespace_as_type01.sts | 22 +++ .../namespace_tests/namespace_as_type02.sts | 27 +++ .../namespace_tests/namespace_as_type03.sts | 24 +++ .../namespace_tests/namespace_as_type04.sts | 24 +++ .../namespace_tests/namespace_as_type05.sts | 25 +++ .../namespace_tests/namespace_as_type06.sts | 26 +++ .../namespace_tests/namespace_as_type07.sts | 29 +++ .../namespace_tests/namespace_as_type08.sts | 23 +++ .../namespace_tests/namespace_as_type09.sts | 24 +++ .../namespace_tests/namespace_as_type10.sts | 24 +++ .../namespace_tests/namespace_as_type11.sts | 22 +++ .../namespace_tests/namespace_as_type12.sts | 23 +++ .../namespace_bad_merged01.sts | 26 +++ .../namespace_bad_merged02.sts | 33 ++++ .../namespace_merge_conflicts.sts | 36 ++++ .../compiler/ets/namespace_tests/src01.sts | 22 +++ .../compiler/ets/namespace_tests/src02.sts | 25 +++ .../ast/parser/ets/declare_namespace_5.sts | 18 +- .../ast/parser/ets/namespace_badtoken01.sts | 23 +++ .../ast/parser/ets/namespace_badtoken02.sts | 18 ++ .../ast/parser/ets/namespace_badtoken03.sts | 18 ++ .../ast/parser/ets/namespace_badtoken04.sts | 22 +++ .../annotationForNamespace.sts | 29 +++ .../ets/namespace_tests/namespace_basic.sts | 43 ++++ .../namespace_deeplt_nested.sts | 35 ++++ .../namespace_execution_statements_test01.sts | 85 ++++++++ .../namespace_execution_statements_test02.sts | 100 ++++++++++ .../namespace_tests/namespace_merge_test.sts | 37 ++++ .../ets/namespace_tests/namespace_merged.sts | 32 +++ .../ets/namespace_tests/namespace_nested.sts} | 71 +++---- .../namespace_tests/namespace_qualified.sts | 49 +++++ .../namespace_with_annotations.sts} | 81 ++++---- .../nested_namespace_plus_equal.sts | 24 +++ .../ets-runtime/ets-runtime-ignored.txt | 3 + .../srcdumper/srcdumper-ets-ignored.txt | 16 ++ ets2panda/test/unit/extern_flag_test.cpp | 57 ++++-- ...ceed_to_state_update_statements_lambda.cpp | 2 +- .../plugin_conversion_rule_part_iii.cpp | 32 +-- ..._verifier_private_access_negative_test.cpp | 32 +-- ...verifier_protected_access_correct_test.cpp | 8 +- ...erifier_protected_access_negative_test.cpp | 28 +-- .../unit/public/ast_verifier_short_test.cpp | 8 +- ets2panda/test/utils/asm_test.cpp | 12 +- ets2panda/test/utils/asm_test.h | 4 +- ets2panda/varbinder/ETSBinder.cpp | 78 +++++--- ets2panda/varbinder/ETSBinder.h | 4 +- ets2panda/varbinder/scope.cpp | 43 ++-- ets2panda/varbinder/variableFlags.h | 3 +- 127 files changed, 2765 insertions(+), 860 deletions(-) delete mode 100644 ets2panda/ir/base/namespaceDefinition.cpp delete mode 100644 ets2panda/ir/base/namespaceDefinition.h rename ets2panda/ir/ets/{etsScript.h => etsModule.cpp} (45%) create mode 100644 ets2panda/ir/ets/etsModule.h create mode 100644 ets2panda/test/ast/compiler/ets/ambient_namesapce01.sts create mode 100644 ets2panda/test/ast/compiler/ets/ambient_namesapce02.sts create mode 100644 ets2panda/test/ast/compiler/ets/ambient_namesapce03.sts create mode 100644 ets2panda/test/ast/compiler/ets/ambient_namesapce04.sts create mode 100644 ets2panda/test/ast/compiler/ets/ambient_namesapce05.sts create mode 100644 ets2panda/test/ast/compiler/ets/ambient_namesapce06.sts create mode 100644 ets2panda/test/ast/compiler/ets/ambient_namesapce07.sts create mode 100644 ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_conflict_for_namespace01.sts create mode 100644 ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_conflict_for_namespace02.sts create mode 100644 ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_duplicate_for_namespace01.sts create mode 100644 ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_duplicate_for_namespace02.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_export_invalid01.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_export_invalid02.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_circular_dependencies.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_conflicts.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_exports.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_import_conflicts.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_merge_conflicts.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_nested_scopes.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_non_exported_merge.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_scope_resolution.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_undefined_scopes.sts rename ets2panda/{ir/ets/etsScript.cpp => test/ast/compiler/ets/namespace_tests/namespace_ambient_export01.sts} (80%) create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_ambient_export02.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_ambient_export03.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_ambient_export04.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type01.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type02.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type03.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type04.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type05.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type06.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type07.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type08.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type09.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type10.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type11.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type12.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_bad_merged01.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_bad_merged02.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/namespace_merge_conflicts.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/src01.sts create mode 100644 ets2panda/test/ast/compiler/ets/namespace_tests/src02.sts create mode 100644 ets2panda/test/ast/parser/ets/namespace_badtoken01.sts create mode 100644 ets2panda/test/ast/parser/ets/namespace_badtoken02.sts create mode 100644 ets2panda/test/ast/parser/ets/namespace_badtoken03.sts create mode 100644 ets2panda/test/ast/parser/ets/namespace_badtoken04.sts create mode 100644 ets2panda/test/runtime/ets/annotation_tests/annotationForNamespace.sts create mode 100644 ets2panda/test/runtime/ets/namespace_tests/namespace_basic.sts create mode 100644 ets2panda/test/runtime/ets/namespace_tests/namespace_deeplt_nested.sts create mode 100644 ets2panda/test/runtime/ets/namespace_tests/namespace_execution_statements_test01.sts create mode 100644 ets2panda/test/runtime/ets/namespace_tests/namespace_execution_statements_test02.sts create mode 100644 ets2panda/test/runtime/ets/namespace_tests/namespace_merge_test.sts create mode 100644 ets2panda/test/runtime/ets/namespace_tests/namespace_merged.sts rename ets2panda/{ir/statements/namespaceDeclaration.h => test/runtime/ets/namespace_tests/namespace_nested.sts} (30%) create mode 100644 ets2panda/test/runtime/ets/namespace_tests/namespace_qualified.sts rename ets2panda/{ir/statements/namespaceDeclaration.cpp => test/runtime/ets/namespace_tests/namespace_with_annotations.sts} (33%) create mode 100644 ets2panda/test/runtime/ets/namespace_tests/nested_namespace_plus_equal.sts diff --git a/ets2panda/BUILD.gn b/ets2panda/BUILD.gn index 857227d23f..bc88941325 100644 --- a/ets2panda/BUILD.gn +++ b/ets2panda/BUILD.gn @@ -267,7 +267,6 @@ libes2panda_sources = [ "ir/base/decorator.cpp", "ir/base/metaProperty.cpp", "ir/base/methodDefinition.cpp", - "ir/base/namespaceDefinition.cpp", "ir/base/property.cpp", "ir/base/scriptFunction.cpp", "ir/base/scriptFunctionSignature.cpp", @@ -282,6 +281,7 @@ libes2panda_sources = [ "ir/ets/etsFunctionType.cpp", "ir/ets/etsImportSource.cpp", "ir/ets/etsLaunchExpression.cpp", + "ir/ets/etsModule.cpp", "ir/ets/etsNeverType.cpp", "ir/ets/etsNewArrayInstanceExpression.cpp", "ir/ets/etsNewClassInstanceExpression.cpp", @@ -291,7 +291,6 @@ libes2panda_sources = [ "ir/ets/etsParameterExpression.cpp", "ir/ets/etsPrimitiveType.cpp", "ir/ets/etsReExportDeclaration.cpp", - "ir/ets/etsScript.cpp", "ir/ets/etsStringLiteralType.cpp", "ir/ets/etsStructDeclaration.cpp", "ir/ets/etsTuple.cpp", @@ -367,7 +366,6 @@ libes2panda_sources = [ "ir/statements/ifStatement.cpp", "ir/statements/labelledStatement.cpp", "ir/statements/loopStatement.cpp", - "ir/statements/namespaceDeclaration.cpp", "ir/statements/returnStatement.cpp", "ir/statements/switchCaseStatement.cpp", "ir/statements/switchStatement.cpp", @@ -618,7 +616,7 @@ HEADERS_TO_BE_PARSED = [ "checker/types/type.h", "checker/types/ts/booleanLiteralType.h", "checker/types/ts/anyType.h", - "ir/ets/etsScript.h", + "ir/ets/etsModule.h", "ir/ts/tsInferType.h", "ir/ts/tsMappedType.h", "ir/statements/debuggerStatement.h", @@ -1000,7 +998,7 @@ ES2PANDA_API_GENERATED = [ "$LIBGEN_DIR/gen/headers/ir/base/decorator.yaml", "$LIBGEN_DIR/gen/headers/ir/ts/tsTypeLiteral.yaml", "$LIBGEN_DIR/gen/headers/ir/expressions/newExpression.yaml", - "$LIBGEN_DIR/gen/headers/ir/ets/etsScript.yaml", + "$LIBGEN_DIR/gen/headers/ir/ets/etsModule.yaml", "$LIBGEN_DIR/gen/headers/ir/base/spreadElement.yaml", "$LIBGEN_DIR/gen/headers/varbinder/variable.yaml", "$LIBGEN_DIR/gen/headers/varbinder/scope.yaml", diff --git a/ets2panda/CMakeLists.txt b/ets2panda/CMakeLists.txt index c943f5bd43..9cafa1b144 100644 --- a/ets2panda/CMakeLists.txt +++ b/ets2panda/CMakeLists.txt @@ -261,7 +261,6 @@ set(ES2PANDA_LIB_SRC ir/base/decorator.cpp ir/base/metaProperty.cpp ir/base/methodDefinition.cpp - ir/base/namespaceDefinition.cpp ir/base/property.cpp ir/base/scriptFunction.cpp ir/base/scriptFunctionSignature.cpp @@ -338,7 +337,6 @@ set(ES2PANDA_LIB_SRC ir/statements/ifStatement.cpp ir/statements/labelledStatement.cpp ir/statements/loopStatement.cpp - ir/statements/namespaceDeclaration.cpp ir/statements/returnStatement.cpp ir/statements/switchCaseStatement.cpp ir/statements/switchStatement.cpp @@ -360,7 +358,7 @@ set(ES2PANDA_LIB_SRC ir/ets/etsPrimitiveType.cpp ir/ets/etsNullishTypes.cpp ir/ets/etsNeverType.cpp - ir/ets/etsScript.cpp + ir/ets/etsModule.cpp ir/ets/etsStringLiteralType.cpp ir/ets/etsTuple.cpp ir/ets/etsTypeReference.cpp diff --git a/ets2panda/ast_verifier/checkConstProperties.cpp b/ets2panda/ast_verifier/checkConstProperties.cpp index 3fc41f3c91..b35435ee17 100644 --- a/ets2panda/ast_verifier/checkConstProperties.cpp +++ b/ets2panda/ast_verifier/checkConstProperties.cpp @@ -25,8 +25,7 @@ namespace ark::es2panda::compiler::ast_verifier { { if (ast->IsClassProperty()) { auto parent = ast->Parent(); - if (parent != nullptr && parent->IsClassDefinition() && - parent->AsClassDefinition()->Ident()->Name() == Signatures::ETS_GLOBAL) { + if (parent != nullptr && parent->IsClassDefinition() && parent->AsClassDefinition()->IsModule()) { return {CheckDecision::CORRECT, CheckAction::CONTINUE}; } auto property = ast->AsClassProperty(); diff --git a/ets2panda/ast_verifier/everyChildHasValidParent.cpp b/ets2panda/ast_verifier/everyChildHasValidParent.cpp index a494884d95..64508a29d0 100644 --- a/ets2panda/ast_verifier/everyChildHasValidParent.cpp +++ b/ets2panda/ast_verifier/everyChildHasValidParent.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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 @@ -21,7 +21,7 @@ namespace ark::es2panda::compiler::ast_verifier { CheckResult EveryChildHasValidParent::operator()(const ir::AstNode *ast) { auto result = std::make_tuple(CheckDecision::CORRECT, CheckAction::CONTINUE); - if (ast->IsETSScript()) { + if (ast->IsETSModule()) { return result; } diff --git a/ets2panda/ast_verifier/helpers.cpp b/ets2panda/ast_verifier/helpers.cpp index 80ad53928c..580446f4c2 100644 --- a/ets2panda/ast_verifier/helpers.cpp +++ b/ets2panda/ast_verifier/helpers.cpp @@ -19,7 +19,7 @@ #include "checker/types/type.h" #include "checker/types/ets/etsObjectType.h" #include "ir/statements/blockStatement.h" -#include "ir/ets/etsScript.h" +#include "ir/ets/etsModule.h" #include "parser/program/program.h" #include "ir/expressions/memberExpression.h" #include "ir/expressions/callExpression.h" @@ -130,20 +130,18 @@ bool IsStringType(const ir::AstNode *ast) bool IsVisibleInternalNode(const ir::AstNode *ast, const ir::AstNode *objTypeDeclNode) { - // NOTE(orlovskymaxim) This relies on the fact, that GetTopStatement has no bugs, that is not the case for now - if (!ast->GetTopStatement()->IsETSScript()) { + if (!ast->GetTopStatement()->IsETSModule()) { return false; } - auto *currentTopStatement = ast->GetTopStatement()->AsETSScript(); + auto *currentTopStatement = ast->GetTopStatement()->AsETSModule(); auto *currentProgram = currentTopStatement->Program(); if (currentProgram == nullptr) { return false; } - // NOTE(orlovskymaxim) This relies on the fact, that GetTopStatement has no bugs, that is not the case for now - if (!objTypeDeclNode->GetTopStatement()->IsETSScript()) { + if (!objTypeDeclNode->GetTopStatement()->IsETSModule()) { return false; } - auto *objectTopStatement = objTypeDeclNode->GetTopStatement()->AsETSScript(); + auto *objectTopStatement = objTypeDeclNode->GetTopStatement()->AsETSModule(); auto *objectProgram = objectTopStatement->Program(); if (objectProgram == nullptr) { return false; diff --git a/ets2panda/ast_verifier/nodeHasParent.cpp b/ets2panda/ast_verifier/nodeHasParent.cpp index d5b2dd9132..52f59b43cd 100644 --- a/ets2panda/ast_verifier/nodeHasParent.cpp +++ b/ets2panda/ast_verifier/nodeHasParent.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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 @@ -21,9 +21,9 @@ namespace ark::es2panda::compiler::ast_verifier { CheckResult NodeHasParent::operator()(const ir::AstNode *ast) { - const auto isEtsScript = ast->IsETSScript() || (ast->IsBlockStatement() && ast->AsBlockStatement()->IsProgram()); + const auto isETSModule = ast->IsETSModule() || (ast->IsBlockStatement() && ast->AsBlockStatement()->IsProgram()); const auto hasParent = ast->Parent() != nullptr; - if (!isEtsScript && !hasParent) { + if (!isETSModule && !hasParent) { AddCheckMessage("NULL_PARENT", *ast); return {CheckDecision::INCORRECT, CheckAction::CONTINUE}; } diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index c734502afe..3261ec4fe4 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -23,7 +23,6 @@ #include "checker/types/ets/etsTupleType.h" #include "checker/types/ets/etsAsyncFuncReturnType.h" #include "evaluate/scopedDebugInfoPlugin.h" -#include "ir/statements/namespaceDeclaration.h" #include "compiler/lowering/util.h" #include @@ -2068,19 +2067,6 @@ checker::Type *ETSAnalyzer::Check(ir::NullLiteral *expr) const return expr->TsType(); } -checker::Type *ETSAnalyzer::Check(ir::NamespaceDeclaration *st) const -{ - ETSChecker *checker = GetETSChecker(); - st->Definition()->Check(checker); - return ReturnTypeForStatement(st); -} - -checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::NamespaceDefinition *st) const -{ - // NOTE It is Typed node, but not a Statement and not a Expression - return nullptr; -} - checker::Type *ETSAnalyzer::Check(ir::NumberLiteral *expr) const { ETSChecker *checker = GetETSChecker(); @@ -2978,6 +2964,8 @@ checker::Type *ETSAnalyzer::Check(ir::TSQualifiedName *expr) const return checker->GlobalTypeError(); } + checker->ValidateNamespaceProperty(prop, baseType->AsETSObjectType(), expr->Right()); + if (expr->Right()->Name().Is(searchName.Mutf8()) && prop->Declaration()->Node()->HasExportAlias()) { checker->LogTypeError({"Cannot find imported element '", searchName, "' exported with alias"}, expr->Right()->Start()); diff --git a/ets2panda/checker/ETSAnalyzerUnreachable.cpp b/ets2panda/checker/ETSAnalyzerUnreachable.cpp index 87f16ee367..30a668d0f4 100644 --- a/ets2panda/checker/ETSAnalyzerUnreachable.cpp +++ b/ets2panda/checker/ETSAnalyzerUnreachable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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 @@ -63,7 +63,7 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSSignatureDeclaration *n UNREACHABLE(); } // from ets folder -checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSScript *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSModule *node) const { UNREACHABLE(); } diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index 3705cc5df7..17812a03b5 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -517,6 +517,8 @@ public: void SetrModuleObjectTsType(ir::Identifier *local, checker::ETSObjectType *moduleObjType); Type *GetReferencedTypeFromBase(Type *baseType, ir::Expression *name); Type *GetReferencedTypeBase(ir::Expression *name); + Type *ResolveReferencedType(varbinder::LocalVariable *refVar, const ir::Expression *name); + bool HandleDynamicImport(ir::Expression *name); Type *GetTypeFromInterfaceReference(varbinder::Variable *var); Type *GetTypeFromTypeAliasReference(varbinder::Variable *var); Type *GetTypeFromClassReference(varbinder::Variable *var); @@ -619,6 +621,8 @@ public: void CheckBoxedSourceTypeAssignable(TypeRelation *relation, Type *source, Type *target); void CheckUnboxedSourceTypeWithWideningAssignable(TypeRelation *relation, Type *source, Type *target); void CheckValidGenericTypeParameter(Type *argType, const lexer::SourcePosition &pos); + void ValidateNamespaceProperty(varbinder::Variable *property, const ETSObjectType *target, + const ir::Identifier *ident); void ValidateResolvedProperty(varbinder::LocalVariable **property, const ETSObjectType *target, const ir::Identifier *ident, PropertySearchFlags flags); bool IsValidSetterLeftSide(const ir::MemberExpression *member); diff --git a/ets2panda/checker/SemanticAnalyzer.h b/ets2panda/checker/SemanticAnalyzer.h index 373aee7684..2f1e348fe9 100644 --- a/ets2panda/checker/SemanticAnalyzer.h +++ b/ets2panda/checker/SemanticAnalyzer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 @@ -45,7 +45,7 @@ #include "ir/ets/etsPackageDeclaration.h" #include "ir/ets/etsParameterExpression.h" #include "ir/ets/etsPrimitiveType.h" -#include "ir/ets/etsScript.h" +#include "ir/ets/etsModule.h" #include "ir/ets/etsStringLiteralType.h" #include "ir/ets/etsNeverType.h" #include "ir/ets/etsNullishTypes.h" diff --git a/ets2panda/checker/TSAnalyzerUnreachable.cpp b/ets2panda/checker/TSAnalyzerUnreachable.cpp index 0e0fc69702..1ab907e2da 100644 --- a/ets2panda/checker/TSAnalyzerUnreachable.cpp +++ b/ets2panda/checker/TSAnalyzerUnreachable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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 @@ -69,7 +69,7 @@ checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TemplateElement *expr) con } // from ets folder -checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSScript *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSModule *expr) const { UNREACHABLE(); } @@ -409,14 +409,4 @@ checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::DummyNode *node) const { UNREACHABLE(); } - -checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::NamespaceDeclaration *expr) const -{ - UNREACHABLE(); -} - -checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::NamespaceDefinition *expr) const -{ - UNREACHABLE(); -} } // namespace ark::es2panda::checker diff --git a/ets2panda/checker/ets/assignAnalyzer.cpp b/ets2panda/checker/ets/assignAnalyzer.cpp index d298aeac68..a02dc5494c 100644 --- a/ets2panda/checker/ets/assignAnalyzer.cpp +++ b/ets2panda/checker/ets/assignAnalyzer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 @@ -507,7 +507,7 @@ void AssignAnalyzer::ProcessClassDefStaticFields(const ir::ClassDefinition *clas } // verify all static const fields got initailized - if (classDef != globalClass_) { + if (!classDef->IsModule()) { for (int i = firstAdr_; i < nextAdr_; i++) { const ir::AstNode *var = varDecls_[i]; if (var->IsStatic() && (var->IsConst() || CHECK_ALL_PROPERTIES)) { diff --git a/ets2panda/checker/ets/dynamic.cpp b/ets2panda/checker/ets/dynamic.cpp index a1abbc2702..925230c31c 100644 --- a/ets2panda/checker/ets/dynamic.cpp +++ b/ets2panda/checker/ets/dynamic.cpp @@ -52,7 +52,7 @@ void ProcessCheckerNode(ETSChecker *checker, ir::AstNode *node) auto scope = compiler::NearestScope(node); if (scope->IsGlobalScope()) { // NOTE(aleksisch): All classes are contained in ETSGlobal class scope (not just Global scope), - // however it's parent is ETSScript. It should be fixed + // however it's parent is ETSModule. It should be fixed scope = checker->VarBinder()->Program()->GlobalClassScope(); } @@ -75,7 +75,7 @@ void ProcessScopesNode(ETSChecker *checker, ir::AstNode *node) auto *scope = compiler::NearestScope(node); if (scope->IsGlobalScope()) { // NOTE(aleksisch): All classes are contained in ETSGlobal scope, - // however it's parent is ETSScript (not ETSGlobal). It should be fixed + // however it's parent is ETSModule (not ETSGlobal). It should be fixed scope = checker->VarBinder()->Program()->GlobalClassScope(); } auto expressionCtx = varbinder::LexicalScope::Enter(checker->VarBinder(), scope); diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index e5dcc18339..8249fa3887 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -81,6 +81,10 @@ void ETSChecker::WrongContextErrorClassifyByType(ir::Identifier *ident) identCategoryName = "Class"; break; } + case varbinder::VariableFlags::NAMESPACE: { + identCategoryName = "Namespace"; + break; + } case varbinder::VariableFlags::METHOD: { identCategoryName = "Function"; break; @@ -1393,51 +1397,53 @@ Type *ETSChecker::GetReferencedTypeBase(ir::Expression *name) ASSERT(name->IsIdentifier() && name->AsIdentifier()->Variable() != nullptr); - // NOTE: kbaladurin. forbid usage imported entities as types without declarations - auto *importData = VarBinder()->AsETSBinder()->DynamicImportDataForVar(name->AsIdentifier()->Variable()); - if (importData != nullptr && importData->import->IsPureDynamic()) { - name->SetTsType(GlobalBuiltinDynamicType(importData->import->Language())); + if (HandleDynamicImport(name)) { return name->TsType(); } auto *refVar = name->AsIdentifier()->Variable()->AsLocalVariable(); + auto *tsType = ResolveReferencedType(refVar, name); + + name->SetTsType(tsType); + return tsType; +} + +bool ETSChecker::HandleDynamicImport(ir::Expression *name) +{ + auto *importData = VarBinder()->AsETSBinder()->DynamicImportDataForVar(name->AsIdentifier()->Variable()); + if (importData != nullptr && importData->import->IsPureDynamic()) { + name->SetTsType(GlobalBuiltinDynamicType(importData->import->Language())); + return true; + } + return false; +} - checker::Type *tsType = nullptr; +Type *ETSChecker::ResolveReferencedType(varbinder::LocalVariable *refVar, const ir::Expression *name) +{ switch (refVar->Declaration()->Node()->Type()) { - case ir::AstNodeType::TS_INTERFACE_DECLARATION: { - tsType = GetTypeFromInterfaceReference(refVar); - break; - } + case ir::AstNodeType::TS_INTERFACE_DECLARATION: + return GetTypeFromInterfaceReference(refVar); case ir::AstNodeType::CLASS_DECLARATION: case ir::AstNodeType::STRUCT_DECLARATION: - case ir::AstNodeType::CLASS_DEFINITION: { - tsType = GetTypeFromClassReference(refVar); - break; - } - case ir::AstNodeType::TS_ENUM_DECLARATION: { - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - tsType = GetTypeFromEnumReference(refVar); - break; - } - case ir::AstNodeType::TS_TYPE_PARAMETER: { - tsType = GetTypeFromTypeParameterReference(refVar, name->Start()); - break; - } - case ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION: { - tsType = GetTypeFromTypeAliasReference(refVar); - break; - } - case ir::AstNodeType::ANNOTATION_DECLARATION: { + case ir::AstNodeType::CLASS_DEFINITION: + if (refVar->Declaration()->Node()->AsClassDefinition()->IsNamespaceTransformed()) { + LogTypeError({"Namespace '", refVar->Name(), "' cannot be used as a type."}, name->Start()); + return GlobalTypeError(); + } + return GetTypeFromClassReference(refVar); + case ir::AstNodeType::TS_ENUM_DECLARATION: + return GetTypeFromEnumReference(refVar); + case ir::AstNodeType::TS_TYPE_PARAMETER: + return GetTypeFromTypeParameterReference(refVar, name->Start()); + case ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION: + return GetTypeFromTypeAliasReference(refVar); + case ir::AstNodeType::ANNOTATION_DECLARATION: LogTypeError("Annotations cannot be used as a type.", name->Start()); - tsType = GlobalTypeError(); - break; - } - default: { + return GlobalTypeError(); + + default: UNREACHABLE(); - } } - name->SetTsType(tsType); - return tsType; } void ETSChecker::ConcatConstantString(util::UString &target, Type *type) diff --git a/ets2panda/checker/ets/object.cpp b/ets2panda/checker/ets/object.cpp index d8c0e710c6..c03ac021a1 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -520,6 +520,11 @@ static void ResolveDeclaredDeclsOfObject(ETSChecker *checker, const ETSObjectTyp it->AddFlag(checker->GetAccessFlagFromNode(it->Declaration()->Node())); type->AddProperty(it->AsLocalVariable()); } + for (auto &[_, it] : scope->TypeAliasScope()->Bindings()) { + (void)_; + it->AddFlag(checker->GetAccessFlagFromNode(it->Declaration()->Node())); + type->AddProperty(it->AsLocalVariable()); + } } void ETSChecker::ResolveDeclaredMembersOfObject(const ETSObjectType *type) @@ -1051,7 +1056,7 @@ void ETSChecker::CheckClassDefinition(ir::ClassDefinition *classDef) classType->AddObjectFlag(checker::ETSObjectFlags::INNER); } - classDef->IsGlobal() ? classType->AddObjectFlag(checker::ETSObjectFlags::GLOBAL) + classDef->IsModule() ? classType->AddObjectFlag(checker::ETSObjectFlags::GLOBAL) : CheckLocalClass(classDef, newStatus); checker::ScopeContext scopeCtx(this, classDef->Scope()); @@ -1590,10 +1595,41 @@ Type *ETSChecker::TryToInstantiate(Type *const type, ArenaAllocator *const alloc return returnType; } +void ETSChecker::ValidateNamespaceProperty(varbinder::Variable *property, const ETSObjectType *target, + const ir::Identifier *ident) +{ + ir::AstNode *parent = nullptr; + if (property->TsType() != nullptr && property->TsType()->IsETSFunctionType()) { + auto funcType = property->TsType()->AsETSFunctionType(); + property = funcType->CallSignatures()[0]->OwnerVar(); + } + + if (property->Declaration() == nullptr) { + return; + } + + auto node = property->Declaration()->Node(); + if (node == nullptr) { + return; + } + + if (node->IsClassDefinition()) { + parent = node->Parent()->Parent(); + } else if (node->Parent() != nullptr) { + parent = node->Parent(); + } + + if (parent != nullptr && parent->IsClassDefinition() && parent->AsClassDefinition()->IsNamespaceTransformed() && + !(node->IsExported() || node->IsExportedType() || node->IsDefaultExported())) { + LogTypeError({"'", ident->Name(), "' is not exported in '", target->Name(), "'"}, ident->Start()); + } +} + void ETSChecker::ValidateResolvedProperty(varbinder::LocalVariable **property, const ETSObjectType *const target, const ir::Identifier *const ident, const PropertySearchFlags flags) { if (*property != nullptr) { + ValidateNamespaceProperty(*property, target, ident); return; } @@ -1704,6 +1740,12 @@ PropertySearchFlags ETSChecker::GetSearchFlags(const ir::MemberExpression *const { auto searchFlag = GetInitialSearchFlags(memberExpr); searchFlag |= PropertySearchFlags::SEARCH_IN_BASE | PropertySearchFlags::SEARCH_IN_INTERFACES; + if (targetRef != nullptr && targetRef->Declaration() != nullptr && + targetRef->Declaration()->Node()->IsClassDefinition() && + targetRef->Declaration()->Node()->AsClassDefinition()->IsNamespaceTransformed()) { + return searchFlag; + } + if (targetRef != nullptr && (targetRef->HasFlag(varbinder::VariableFlags::CLASS_OR_INTERFACE) || (targetRef->HasFlag(varbinder::VariableFlags::TYPE_ALIAS) && targetRef->TsType()->Variable() != nullptr && @@ -2059,8 +2101,12 @@ void ETSChecker::CheckProperties(ETSObjectType *classType, ir::ClassDefinition * targetType = "class"; } else if (it->HasFlag(varbinder::VariableFlags::INTERFACE)) { targetType = "interface"; - } else { + } else if (it->HasFlag(varbinder::VariableFlags::NAMESPACE)) { + targetType = "namespace"; + } else if (it->HasFlag(varbinder::VariableFlags::ENUM_LITERAL)) { targetType = "enum"; + } else { + UNREACHABLE(); } if (interfaceFound != nullptr) { diff --git a/ets2panda/checker/ets/typeCheckingHelpers.cpp b/ets2panda/checker/ets/typeCheckingHelpers.cpp index 6d596bf95c..05ed95695b 100644 --- a/ets2panda/checker/ets/typeCheckingHelpers.cpp +++ b/ets2panda/checker/ets/typeCheckingHelpers.cpp @@ -684,7 +684,9 @@ Type *ETSChecker::GetTypeFromClassReference(varbinder::Variable *var) return var->TsType(); } - auto *classType = BuildBasicClassProperties(var->Declaration()->Node()->AsClassDefinition()); + auto classDef = var->Declaration()->Node()->AsClassDefinition(); + + auto *classType = BuildBasicClassProperties(classDef); var->SetTsType(classType); return classType; } @@ -822,7 +824,8 @@ void ETSChecker::CheckAmbientAnnotation(ir::AnnotationDeclaration *annoImpl, ir: } auto *fieldDecl = fieldDeclIter->second; - if (field->TsType() != fieldDecl->TsType()) { + fieldDecl->Check(this); + if (!Relation()->IsIdenticalTo(field->TsType(), fieldDecl->TsType())) { LogTypeError({"Field '", fieldName, "' has a type mismatch with the ambient annotation '", annoDecl->GetBaseName()->Name(), "'."}, field->TypeAnnotation()->Start()); diff --git a/ets2panda/checker/ets/typeCreation.cpp b/ets2panda/checker/ets/typeCreation.cpp index 137fe0f661..26b327239f 100644 --- a/ets2panda/checker/ets/typeCreation.cpp +++ b/ets2panda/checker/ets/typeCreation.cpp @@ -26,7 +26,7 @@ #include "generated/signatures.h" #include "ir/base/classDefinition.h" #include "ir/base/scriptFunction.h" -#include "ir/ets/etsScript.h" +#include "ir/ets/etsModule.h" #include "ir/expressions/identifier.h" #include "ir/ts/tsEnumDeclaration.h" #include "ir/ts/tsEnumMember.h" diff --git a/ets2panda/checker/ets/utilityTypeHandlers.cpp b/ets2panda/checker/ets/utilityTypeHandlers.cpp index 2a68c70ae8..0a0e2c3463 100644 --- a/ets2panda/checker/ets/utilityTypeHandlers.cpp +++ b/ets2panda/checker/ets/utilityTypeHandlers.cpp @@ -46,26 +46,31 @@ Type *ETSChecker::HandleUtilityTypeParameterNode(const ir::TSTypeParameterInstan return GlobalTypeError(); } - Type *bareType = possiblyTypeParam.value()->Check(this); - if (!bareType->IsETSReferenceType()) { + Type *baseType = possiblyTypeParam.value()->Check(this); + + if (baseType->IsTypeError()) { + return baseType; + } + + if (!baseType->IsETSReferenceType()) { LogTypeError("Only reference types can be converted to utility types.", typeParams->Start()); return GlobalTypeError(); } if (utilityType == compiler::Signatures::PARTIAL_TYPE_NAME) { - return CreatePartialType(bareType); + return CreatePartialType(baseType); } if (utilityType == compiler::Signatures::READONLY_TYPE_NAME) { - return GetReadonlyType(bareType); + return GetReadonlyType(baseType); } if (utilityType == compiler::Signatures::REQUIRED_TYPE_NAME) { - return HandleRequiredType(bareType); + return HandleRequiredType(baseType); } LogTypeError("This utility type is not yet implemented.", typeParams->Start()); - return bareType; + return baseType; } // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -89,7 +94,7 @@ static std::pair GetPartialClassName(ETSChec static std::pair GetPartialClassProgram(ETSChecker *checker, ir::AstNode *typeNode) { - auto classDefProgram = typeNode->GetTopStatement()->AsETSScript()->Program(); + auto classDefProgram = typeNode->GetTopStatement()->AsETSModule()->Program(); if (classDefProgram == checker->VarBinder()->Program()) { return {classDefProgram, checker->VarBinder()->AsETSBinder()->GetGlobalRecordTable()}; } diff --git a/ets2panda/compiler/core/ASTCompiler.h b/ets2panda/compiler/core/ASTCompiler.h index a98667aae8..b770414000 100644 --- a/ets2panda/compiler/core/ASTCompiler.h +++ b/ets2panda/compiler/core/ASTCompiler.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2024 Huawei Device Co., Ltd. + * Copyright (c) 2021 - 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 @@ -45,7 +45,7 @@ #include "ir/ets/etsPackageDeclaration.h" #include "ir/ets/etsParameterExpression.h" #include "ir/ets/etsPrimitiveType.h" -#include "ir/ets/etsScript.h" +#include "ir/ets/etsModule.h" #include "ir/ets/etsStructDeclaration.h" #include "ir/ets/etsTypeReference.h" #include "ir/ets/etsTypeReferencePart.h" diff --git a/ets2panda/compiler/core/ETSCompilerUnrechable.cpp b/ets2panda/compiler/core/ETSCompilerUnrechable.cpp index 8a0436eb84..48d308d866 100644 --- a/ets2panda/compiler/core/ETSCompilerUnrechable.cpp +++ b/ets2panda/compiler/core/ETSCompilerUnrechable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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 @@ -87,7 +87,7 @@ void ETSCompiler::Compile([[maybe_unused]] const ir::TSSignatureDeclaration *nod UNREACHABLE(); } -void ETSCompiler::Compile([[maybe_unused]] const ir::ETSScript *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::ETSModule *node) const { UNREACHABLE(); } @@ -503,14 +503,4 @@ void ETSCompiler::Compile([[maybe_unused]] const ir::DummyNode *node) const { UNREACHABLE(); } - -void ETSCompiler::Compile([[maybe_unused]] const ir::NamespaceDeclaration *st) const -{ - UNREACHABLE(); -} - -void ETSCompiler::Compile([[maybe_unused]] const ir::NamespaceDefinition *st) const -{ - UNREACHABLE(); -} } // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/core/ETSemitter.cpp b/ets2panda/compiler/core/ETSemitter.cpp index f7516d6e45..674c1e75c4 100644 --- a/ets2panda/compiler/core/ETSemitter.cpp +++ b/ets2panda/compiler/core/ETSemitter.cpp @@ -536,7 +536,7 @@ void ETSEmitter::GenClassRecord(const ir::ClassDefinition *classDef, bool extern std::vector annotations = GenAnnotations(classDef); if (!annotations.empty()) { - classRecord.metadata->SetAnnotations(std::move(annotations)); + classRecord.metadata->AddAnnotations(annotations); } Program()->recordTable.emplace(classRecord.name, std::move(classRecord)); diff --git a/ets2panda/compiler/core/JSCompilerUnreachable.cpp b/ets2panda/compiler/core/JSCompilerUnreachable.cpp index d47e73180f..4572b53535 100644 --- a/ets2panda/compiler/core/JSCompilerUnreachable.cpp +++ b/ets2panda/compiler/core/JSCompilerUnreachable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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 @@ -88,7 +88,7 @@ void JSCompiler::Compile([[maybe_unused]] const ir::TSSignatureDeclaration *node UNREACHABLE(); } // from ets folder -void JSCompiler::Compile([[maybe_unused]] const ir::ETSScript *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::ETSModule *expr) const { UNREACHABLE(); } @@ -513,14 +513,4 @@ void JSCompiler::Compile([[maybe_unused]] const ir::DummyNode *node) const { UNREACHABLE(); } - -void JSCompiler::Compile([[maybe_unused]] const ir::NamespaceDeclaration *st) const -{ - UNREACHABLE(); -} - -void JSCompiler::Compile([[maybe_unused]] const ir::NamespaceDefinition *st) const -{ - UNREACHABLE(); -} } // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/enumLowering.cpp b/ets2panda/compiler/lowering/ets/enumLowering.cpp index 79877f8c0e..781cd1b87b 100644 --- a/ets2panda/compiler/lowering/ets/enumLowering.cpp +++ b/ets2panda/compiler/lowering/ets/enumLowering.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2024 Huawei Device Co., Ltd. + * Copyright (c) 2021 - 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 @@ -166,25 +166,29 @@ ir::Identifier *EnumLoweringPhase::CreateEnumNamesArray(const ir::TSEnumDeclarat // clang-format on } -ir::ClassDeclaration *EnumLoweringPhase::CreateClass(ir::TSEnumDeclaration *const enumDecl) +ir::ClassDeclaration *EnumLoweringPhase::CreateClass(ir::TSEnumDeclaration *const enumDecl, + const DeclarationFlags flags) { auto *ident = Allocator()->New(GetEnumClassName(checker_, enumDecl).View(), Allocator()); - - bool localDeclaration = (enumDecl->Parent() != nullptr && enumDecl->Parent()->IsBlockStatement()); auto *classDef = checker_->AllocNode( Allocator(), ident, - localDeclaration ? ir::ClassDefinitionModifiers::CLASS_DECL | ir::ClassDefinitionModifiers::LOCAL - : ir::ClassDefinitionModifiers::CLASS_DECL, + flags.isLocal ? ir::ClassDefinitionModifiers::CLASS_DECL | ir::ClassDefinitionModifiers::LOCAL + : ir::ClassDefinitionModifiers::CLASS_DECL, enumDecl->IsDeclare() ? ir::ModifierFlags::DECLARE : ir::ModifierFlags::NONE, Language(Language::Id::ETS)); auto *classDecl = checker_->AllocNode(classDef, Allocator()); - if (localDeclaration) { + if (flags.isLocal) { enumDecl->Parent()->AsBlockStatement()->Statements().push_back(classDecl); classDecl->SetParent(enumDecl->Parent()); - } else { + } else if (flags.isNamespace) { + enumDecl->Parent()->AsClassDefinition()->Body().push_back(classDecl); + classDecl->SetParent(enumDecl->Parent()); + } else if (flags.isTopLevel) { program_->Ast()->Statements().push_back(classDecl); classDecl->SetParent(program_->Ast()); + } else { // Maybe support local enums in the future + UNREACHABLE(); } classDef->SetOrigEnumDecl(enumDecl); @@ -290,9 +294,33 @@ void EnumLoweringPhase::CreateCtorForEnumClass(ir::ClassDefinition *const enumCl enumClass->Body().push_back(methodDef); } -void EnumLoweringPhase::CreateEnumIntClassFromEnumDeclaration(ir::TSEnumDeclaration *const enumDecl) +void EnumLoweringPhase::ProcessEnumClassDeclaration(ir::TSEnumDeclaration *const enumDecl, + const DeclarationFlags &flags, ir::ClassDeclaration *enumClassDecl) +{ + if (flags.isLocal) { + auto localCtx = varbinder::LexicalScope::Enter(varbinder_, NearestScope(enumDecl->Parent())); + InitScopesPhaseETS::RunExternalNode(enumClassDecl, varbinder_); + } else if (flags.isTopLevel) { + auto localCtx = varbinder::LexicalScope::Enter(varbinder_, program_->GlobalScope()); + InitScopesPhaseETS::RunExternalNode(enumClassDecl, varbinder_); + auto *ident = enumClassDecl->Definition()->Ident(); + auto *var = varbinder_->GetScope()->FindLocal(ident->Name(), varbinder::ResolveBindingOptions::BINDINGS); + ident->SetVariable(var); + } else if (flags.isNamespace) { + auto localCtx = varbinder::LexicalScope::Enter(varbinder_, enumDecl->Parent()->Scope()); + InitScopesPhaseETS::RunExternalNode(enumClassDecl, varbinder_); + auto *ident = enumClassDecl->Definition()->Ident(); + auto *var = varbinder_->GetScope()->FindLocal(ident->Name(), varbinder::ResolveBindingOptions::DECLARATION); + ident->SetVariable(var); + } else { + UNREACHABLE(); + } +} + +void EnumLoweringPhase::CreateEnumIntClassFromEnumDeclaration(ir::TSEnumDeclaration *const enumDecl, + const DeclarationFlags flags) { - auto *const enumClassDecl = CreateClass(enumDecl); + auto *const enumClassDecl = CreateClass(enumDecl, flags); auto *const enumClass = enumClassDecl->Definition(); auto *const namesArrayIdent = CreateEnumNamesArray(enumDecl, enumClass); @@ -319,21 +347,13 @@ void EnumLoweringPhase::CreateEnumIntClassFromEnumDeclaration(ir::TSEnumDeclarat CreateEnumFromIntMethod(enumDecl, enumClass, boxedItemsArrayIdent, checker::ETSEnumType::BOXED_FROM_INT_METHOD_NAME, GetEnumClassName(checker_, enumDecl).View()); - if (enumDecl->Parent() != nullptr && enumDecl->Parent()->IsBlockStatement()) { - auto localCtx = varbinder::LexicalScope::Enter(varbinder_, NearestScope(enumDecl->Parent())); - InitScopesPhaseETS::RunExternalNode(enumClassDecl, varbinder_); - } else { - auto localCtx = varbinder::LexicalScope::Enter(varbinder_, program_->GlobalScope()); - InitScopesPhaseETS::RunExternalNode(enumClassDecl, varbinder_); - auto *ident = enumClass->Ident(); - auto *var = varbinder_->GetScope()->FindLocal(ident->Name(), varbinder::ResolveBindingOptions::BINDINGS); - ident->SetVariable(var); - } + ProcessEnumClassDeclaration(enumDecl, flags, enumClassDecl); } -void EnumLoweringPhase::CreateEnumStringClassFromEnumDeclaration(ir::TSEnumDeclaration *const enumDecl) +void EnumLoweringPhase::CreateEnumStringClassFromEnumDeclaration(ir::TSEnumDeclaration *const enumDecl, + const DeclarationFlags flags) { - auto *const enumClassDecl = CreateClass(enumDecl); + auto *const enumClassDecl = CreateClass(enumDecl, flags); auto *const enumClass = enumClassDecl->Definition(); auto *const namesArrayIdent = CreateEnumNamesArray(enumDecl, enumClass); @@ -357,16 +377,16 @@ void EnumLoweringPhase::CreateEnumStringClassFromEnumDeclaration(ir::TSEnumDecla CreateEnumFromIntMethod(enumDecl, enumClass, boxedItemsArrayIdent, checker::ETSEnumType::BOXED_FROM_INT_METHOD_NAME, GetEnumClassName(checker_, enumDecl).View()); - if (enumDecl->Parent() != nullptr && enumDecl->Parent()->IsBlockStatement()) { - auto localCtx = varbinder::LexicalScope::Enter(varbinder_, NearestScope(enumDecl->Parent())); - InitScopesPhaseETS::RunExternalNode(enumClassDecl, varbinder_); - } else { - auto localCtx = varbinder::LexicalScope::Enter(varbinder_, program_->GlobalScope()); - InitScopesPhaseETS::RunExternalNode(enumClassDecl, varbinder_); - auto *ident = enumClass->Ident(); - auto *var = varbinder_->GetScope()->FindLocal(ident->Name(), varbinder::ResolveBindingOptions::BINDINGS); - ident->SetVariable(var); - } + ProcessEnumClassDeclaration(enumDecl, flags, enumClassDecl); +} + +static EnumLoweringPhase::DeclarationFlags GetDeclFlags(ir::TSEnumDeclaration *const enumDecl) +{ + return {enumDecl->Parent() != nullptr && enumDecl->Parent()->IsETSModule() && + enumDecl->Parent()->AsETSModule()->IsETSScript(), + enumDecl->Parent() != nullptr && enumDecl->Parent()->IsBlockStatement(), + enumDecl->Parent() != nullptr && enumDecl->Parent()->IsClassDefinition() && + enumDecl->Parent()->AsClassDefinition()->IsNamespaceTransformed()}; } bool EnumLoweringPhase::PerformForModule(public_lib::Context *ctx, parser::Program *program) @@ -387,10 +407,10 @@ bool EnumLoweringPhase::PerformForModule(public_lib::Context *ctx, parser::Progr if (auto *const itemInit = enumDecl->Members().front()->AsTSEnumMember()->Init(); itemInit->IsNumberLiteral() && CheckEnumMemberType(enumDecl->Members(), hasLoggedError)) { - CreateEnumIntClassFromEnumDeclaration(enumDecl); + CreateEnumIntClassFromEnumDeclaration(enumDecl, GetDeclFlags(enumDecl)); } else if (itemInit->IsStringLiteral() && CheckEnumMemberType(enumDecl->Members(), hasLoggedError)) { - CreateEnumStringClassFromEnumDeclaration(enumDecl); + CreateEnumStringClassFromEnumDeclaration(enumDecl, GetDeclFlags(enumDecl)); } else if (!hasLoggedError) { LogSyntaxError("Invalid enum initialization value", itemInit->Start()); isPerformedSuccess = false; diff --git a/ets2panda/compiler/lowering/ets/enumLowering.h b/ets2panda/compiler/lowering/ets/enumLowering.h index fec8918be4..c91cc73373 100644 --- a/ets2panda/compiler/lowering/ets/enumLowering.h +++ b/ets2panda/compiler/lowering/ets/enumLowering.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2024 Huawei Device Co., Ltd. + * Copyright (c) 2021 - 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 @@ -23,6 +23,12 @@ namespace ark::es2panda::compiler { class EnumLoweringPhase : public PhaseForDeclarations { public: + struct DeclarationFlags { + bool isTopLevel; + bool isLocal; + bool isNamespace; + }; + EnumLoweringPhase() noexcept = default; std::string_view Name() const override { @@ -55,14 +61,16 @@ private: bool CheckEnumMemberType(const ArenaVector &enumMembers, bool &hasLoggedError); [[nodiscard]] ir::ScriptFunction *MakeFunction(FunctionInfo &&functionInfo); - ir::ClassDeclaration *CreateClass(ir::TSEnumDeclaration *const enumDecl); + ir::ClassDeclaration *CreateClass(ir::TSEnumDeclaration *const enumDecl, const DeclarationFlags flags); ir::ClassProperty *CreateOrdinalField(ir::ClassDefinition *const enumClass); void CreateCCtorForEnumClass(ir::ClassDefinition *const enumClass); void CreateCtorForEnumClass(ir::ClassDefinition *const enumClass); ir::ScriptFunction *CreateFunctionForCtorOfEnumClass(ir::ClassDefinition *const enumClass); - void CreateEnumIntClassFromEnumDeclaration(ir::TSEnumDeclaration *const enumDecl); - void CreateEnumStringClassFromEnumDeclaration(ir::TSEnumDeclaration *const enumDecl); + void ProcessEnumClassDeclaration(ir::TSEnumDeclaration *const enumDecl, const DeclarationFlags &flags, + ir::ClassDeclaration *enumClassDecl); + void CreateEnumIntClassFromEnumDeclaration(ir::TSEnumDeclaration *const enumDecl, const DeclarationFlags flags); + void CreateEnumStringClassFromEnumDeclaration(ir::TSEnumDeclaration *const enumDecl, const DeclarationFlags flags); static void AppendParentNames(util::UString &qualifiedName, const ir::AstNode *const node); template [[nodiscard]] ir::Identifier *MakeArray(const ir::TSEnumDeclaration *const enumDecl, ir::ClassDefinition *enumClass, diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp b/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp index c655d2bc1d..9e1812cac0 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp @@ -31,11 +31,158 @@ #include "ir/statements/blockStatement.h" #include "util/helpers.h" #include "util/ustring.h" +#include "utils/arena_containers.h" namespace ark::es2panda::compiler { using util::NodeAllocator; +void GlobalClassHandler::AddStaticBlockToClass(ir::AstNode *node) +{ + if (node->IsClassDefinition() && !node->AsClassDefinition()->IsDeclare()) { + auto classDef = node->AsClassDefinition(); + if (auto staticBlock = CreateStaticBlock(classDef); staticBlock != nullptr) { + classDef->Body().emplace_back(staticBlock); // NOTE(vpukhov): inserted to end for some reason + staticBlock->SetParent(classDef); + } + } +} + +ir::ClassDeclaration *GlobalClassHandler::CreateTransformedClass(ir::ETSModule *ns) +{ + auto className = ns->Ident()->Name(); + auto *ident = NodeAllocator::Alloc(allocator_, className, allocator_); + ident->SetRange(ns->Ident()->Range()); + + auto *classDef = NodeAllocator::Alloc( + allocator_, allocator_, ident, ir::ClassDefinitionModifiers::CLASS_DECL, ir::ModifierFlags::ABSTRACT, + Language(Language::Id::ETS)); + classDef->SetRange(ns->Range()); + classDef->AddModifier(ns->Modifiers()); + auto *classDecl = NodeAllocator::Alloc(allocator_, classDef, allocator_); + classDecl->AddModifier(ns->Modifiers()); + classDef->SetNamespaceTransformed(); + ArenaVector annotations {allocator_->Adapter()}; + for (auto *anno : ns->Annotations()) { + auto clone = anno->Clone(allocator_, classDef); + annotations.push_back(clone); + } + classDef->SetAnnotations(std::move(annotations)); + return classDecl; +} + +void GlobalClassHandler::SetupGlobalMethods(ir::ClassDefinition *globalClass, + ArenaVector &&initStatements, bool isDeclare) +{ + auto const insertInGlobal = [globalClass](ir::AstNode *node) { + globalClass->Body().insert(globalClass->Body().begin(), node); + node->SetParent(globalClass); + }; + + if (!isDeclare) { + ir::MethodDefinition *initMethod = + CreateGlobalMethod(compiler::Signatures::INIT_METHOD, std::move(initStatements)); + insertInGlobal(initMethod); + if (!initMethod->Function()->Body()->AsBlockStatement()->Statements().empty()) { + AddInitCallFromStaticBlock(globalClass, initMethod); + } + } +} + +void GlobalClassHandler::MergeNamespace(ArenaVector &namespaces, parser::ETSParser *parser) +{ + ArenaUnorderedMap nsMap {allocator_->Adapter()}; + for (auto it = namespaces.begin(); it != namespaces.end();) { + auto *ns = *it; + auto res = nsMap.find(ns->Ident()->Name()); + if (res != nsMap.end()) { + if (res->second->Modifiers() != ns->Modifiers()) { + parser->LogSyntaxError("Unable to merge namespaces '" + ns->Ident()->Name().Mutf8() + + "', because their modifiers are different.", + ns->Start()); + } + if (!res->second->Annotations().empty() && !ns->Annotations().empty()) { + parser->LogSyntaxError("Annotation conflict! Multiple namespace declarations for '" + + ns->Ident()->Name().Mutf8() + "' cannot each have annotations.", + ns->Start()); + } else if (!ns->Annotations().empty()) { + ASSERT(res->second->Annotations().empty()); + res->second->SetAnnotations(std::move(ns->Annotations())); + } + for (auto *statement : ns->Statements()) { + res->second->Statements().emplace_back(statement); + } + namespaces.erase(it); + } else { + nsMap.insert({ns->Ident()->Name(), ns}); + ++it; + } + } +} + +ArenaVector GlobalClassHandler::TransformNamespaces(ArenaVector &namespaces, + parser::Program *program) +{ + ArenaVector classDecls {allocator_->Adapter()}; + MergeNamespace(namespaces, program->VarBinder()->GetContext()->parser->AsETSParser()); + for (auto ns : namespaces) { + classDecls.emplace_back(TransformNamespace(ns, program)); + } + return classDecls; +} + +ir::ClassDeclaration *GlobalClassHandler::TransformNamespace(ir::ETSModule *ns, parser::Program *program) +{ + ir::ClassDeclaration *const globalDecl = CreateTransformedClass(ns); + ir::ClassDefinition *const globalClass = globalDecl->Definition(); + + ArenaVector statements(allocator_->Adapter()); + ArenaVector namespaces(allocator_->Adapter()); + auto &body = ns->Statements(); + for (auto *statement : body) { + statement->Iterate([this](ir::AstNode *node) { AddStaticBlockToClass(node); }); + } + + auto stmts = CollectProgramGlobalStatements(body, globalClass); + statements.emplace_back(GlobalStmts {program, std::move(stmts)}); + AddStaticBlockToClass(globalClass); + const ModuleDependencies md {allocator_->Adapter()}; + auto initStatements = FormInitMethodStatements(program, &md, std::move(statements)); + SetupGlobalMethods(globalClass, std::move(initStatements), ns->IsDeclare()); + + // remove namespaceDecl from orginal node + auto end = std::remove_if(body.begin(), body.end(), [&namespaces](ir::AstNode *node) { + if (node->IsETSModule()) { + namespaces.emplace_back(node->AsETSModule()); + return true; + } + return false; + }); + body.erase(end, body.end()); + auto globalClasses = TransformNamespaces(namespaces, program); + for (auto *cls : globalClasses) { + globalClass->Body().emplace_back(cls); + cls->SetParent(globalClass); + } + + // Add rest statement, such as type declaration + for (auto *statement : body) { + globalClass->Body().emplace_back(statement); + statement->SetParent(globalClass); + } + body.clear(); + return globalDecl; +} + +void GlobalClassHandler::CollectProgramGlobalClasses(parser::Program *program, ArenaVector namespaces) +{ + auto classDecls = TransformNamespaces(namespaces, program); + for (auto cls : classDecls) { + program->Ast()->Statements().push_back(cls); + cls->SetParent(program->Ast()); + } +} + void GlobalClassHandler::SetupGlobalClass(const ArenaVector &programs, const ModuleDependencies *moduleDependencies) { @@ -45,25 +192,25 @@ void GlobalClassHandler::SetupGlobalClass(const ArenaVector & ir::ClassDeclaration *const globalDecl = CreateGlobalClass(); ir::ClassDefinition *const globalClass = globalDecl->Definition(); - auto addStaticBlock = [this](ir::AstNode *node) { - if (node->IsClassDefinition() && !node->AsClassDefinition()->IsDeclare()) { - auto classDef = node->AsClassDefinition(); - if (auto staticBlock = CreateStaticBlock(classDef); staticBlock != nullptr) { - classDef->Body().emplace_back(staticBlock); // NOTE(vpukhov): inserted to end for some reason - staticBlock->SetParent(classDef); - } - } - }; - parser::Program *const globalProgram = programs.front(); // NOTE(vpukhov): a clash inside program list is possible ASSERT(globalProgram->IsPackage() || programs.size() == 1); ArenaVector statements(allocator_->Adapter()); + ArenaVector namespaces(allocator_->Adapter()); for (auto program : programs) { - program->Ast()->IterateRecursively(addStaticBlock); - auto stmts = CollectProgramGlobalStatements(program, globalClass); + program->Ast()->IterateRecursively([this](ir::AstNode *node) { AddStaticBlockToClass(node); }); + auto &body = program->Ast()->Statements(); + auto stmts = CollectProgramGlobalStatements(body, globalClass); + auto end = std::remove_if(body.begin(), body.end(), [&namespaces](ir::AstNode *node) { + if (node->IsETSModule() && node->AsETSModule()->IsNamespace()) { + namespaces.emplace_back(node->AsETSModule()); + return true; + } + return false; + }); + body.erase(end, body.end()); statements.emplace_back(GlobalStmts {program, std::move(stmts)}); program->SetGlobalClass(globalClass); } @@ -72,9 +219,11 @@ void GlobalClassHandler::SetupGlobalClass(const ArenaVector & globalDecl->SetParent(globalProgram->Ast()); globalClass->SetGlobalInitialized(); + CollectProgramGlobalClasses(globalProgram, namespaces); + // NOTE(vpukhov): stdlib checks are to be removed - do not extend the existing logic if (globalProgram->Kind() != parser::ScriptKind::STDLIB) { - addStaticBlock(globalClass); + AddStaticBlockToClass(globalClass); if (!util::Helpers::IsStdLib(globalProgram)) { auto initStatements = FormInitMethodStatements(globalProgram, moduleDependencies, std::move(statements)); SetupGlobalMethods(globalProgram, std::move(initStatements)); @@ -240,7 +389,7 @@ ir::ClassStaticBlock *GlobalClassHandler::CreateStaticBlock(ir::ClassDefinition } } - if (!hasStaticField && !classDef->IsGlobal()) { + if (!hasStaticField && !classDef->IsModule()) { return nullptr; } @@ -266,21 +415,19 @@ ir::ClassStaticBlock *GlobalClassHandler::CreateStaticBlock(ir::ClassDefinition return staticBlock; } -ArenaVector GlobalClassHandler::CollectProgramGlobalStatements(parser::Program *program, +ArenaVector GlobalClassHandler::CollectProgramGlobalStatements(ArenaVector &stmts, ir::ClassDefinition *classDef) { - auto ast = program->Ast(); auto globalDecl = GlobalDeclTransformer(allocator_); - auto statements = globalDecl.TransformStatements(ast->Statements()); + auto statements = globalDecl.TransformStatements(stmts); classDef->AddProperties(util::Helpers::ConvertVector(statements.classProperties)); - globalDecl.FilterDeclarations(ast->Statements()); + globalDecl.FilterDeclarations(stmts); return std::move(statements.initStatements); } ir::ClassDeclaration *GlobalClassHandler::CreateGlobalClass() { auto *ident = NodeAllocator::Alloc(allocator_, compiler::Signatures::ETS_GLOBAL, allocator_); - auto *classDef = NodeAllocator::Alloc(allocator_, allocator_, ident, ir::ClassDefinitionModifiers::GLOBAL, ir::ModifierFlags::ABSTRACT, Language(Language::Id::ETS)); diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.h b/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.h index 8121cb759f..58746a0287 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.h +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.h @@ -47,6 +47,15 @@ private: * @param init_statements statements which should be executed */ void SetupGlobalMethods(parser::Program *program, ArenaVector &&statements); + void AddStaticBlockToClass(ir::AstNode *node); + void CollectProgramGlobalClasses(parser::Program *program, ArenaVector namespaces); + ir::ClassDeclaration *TransformNamespace(ir::ETSModule *ns, parser::Program *program); + ir::ClassDeclaration *CreateTransformedClass(ir::ETSModule *ns); + void SetupGlobalMethods(ir::ClassDefinition *globalClass, ArenaVector &&initStatements, + bool isDeclare); + ArenaVector TransformNamespaces(ArenaVector &namespaces, + parser::Program *program); + void MergeNamespace(ArenaVector &namespaces, parser::ETSParser *parser); ir::ClassDeclaration *CreateGlobalClass(); ir::ClassStaticBlock *CreateStaticBlock(ir::ClassDefinition *classDef); @@ -60,14 +69,7 @@ private: void FormDependentInitTriggers(ArenaVector &statements, const ModuleDependencies *moduleDependencies); - /** - * - * @param program leave only declarations here - * @param class_def add new properties such as methods and fields - * @param addInitializer $init$ should contain global variable initializers - * @return Statements, which should be executed before the start - */ - ArenaVector CollectProgramGlobalStatements(parser::Program *program, + ArenaVector CollectProgramGlobalStatements(ArenaVector &stmts, ir::ClassDefinition *classDef); ir::Identifier *RefIdent(const util::StringView &name); diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/globalDeclTransformer.h b/ets2panda/compiler/lowering/ets/topLevelStmts/globalDeclTransformer.h index 10b60f2bd6..ccaab2b86c 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/globalDeclTransformer.h +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/globalDeclTransformer.h @@ -24,12 +24,18 @@ namespace ark::es2panda::compiler { class GlobalDeclTransformer : public ir::visitor::CustomAstVisitor { const std::unordered_set typeDecl_ = { - ir::AstNodeType::CLASS_DECLARATION, ir::AstNodeType::STRUCT_DECLARATION, - ir::AstNodeType::TS_ENUM_DECLARATION, ir::AstNodeType::TS_INTERFACE_DECLARATION, - ir::AstNodeType::ETS_PACKAGE_DECLARATION, ir::AstNodeType::ETS_IMPORT_DECLARATION, - ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION, ir::AstNodeType::EXPORT_ALL_DECLARATION, - ir::AstNodeType::EXPORT_NAMED_DECLARATION, ir::AstNodeType::REEXPORT_STATEMENT, - ir::AstNodeType::NAMESPACE_DECLARATION, ir::AstNodeType::ANNOTATION_DECLARATION, + ir::AstNodeType::CLASS_DECLARATION, + ir::AstNodeType::STRUCT_DECLARATION, + ir::AstNodeType::TS_ENUM_DECLARATION, + ir::AstNodeType::TS_INTERFACE_DECLARATION, + ir::AstNodeType::ETS_PACKAGE_DECLARATION, + ir::AstNodeType::ETS_IMPORT_DECLARATION, + ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION, + ir::AstNodeType::EXPORT_ALL_DECLARATION, + ir::AstNodeType::EXPORT_NAMED_DECLARATION, + ir::AstNodeType::REEXPORT_STATEMENT, + ir::AstNodeType::ETS_MODULE, + ir::AstNodeType::ANNOTATION_DECLARATION, }; const std::unordered_set propertiesDecl_ = { diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/importExportDecls.cpp b/ets2panda/compiler/lowering/ets/topLevelStmts/importExportDecls.cpp index 2cd2c7679b..64afe2111a 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/importExportDecls.cpp +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/importExportDecls.cpp @@ -31,6 +31,21 @@ void ImportExportDecls::ParseDefaultSources() varbinder_->SetDefaultImports(std::move(imports)); } +void ImportExportDecls::ProcessProgramStatements(parser::Program *program, + const ArenaVector &statements, + GlobalClassHandler::ModuleDependencies &moduleDependencies) +{ + for (auto stmt : statements) { + if (stmt->IsETSModule()) { + ProcessProgramStatements(program, stmt->AsETSModule()->Statements(), moduleDependencies); + } + stmt->Accept(this); + if (stmt->IsExportNamedDeclaration()) { + PopulateAliasMap(stmt->AsExportNamedDeclaration(), program->SourceFilePath()); + } + } +} + GlobalClassHandler::ModuleDependencies ImportExportDecls::HandleGlobalStmts(ArenaVector &programs) { VerifySingleExportDefault(programs); @@ -43,12 +58,7 @@ GlobalClassHandler::ModuleDependencies ImportExportDecls::HandleGlobalStmts(Aren fieldMap_.clear(); exportNameMap_.clear(); exportedTypes_.clear(); - for (auto stmt : program->Ast()->Statements()) { - stmt->Accept(this); - if (stmt->IsExportNamedDeclaration()) { - PopulateAliasMap(stmt->AsExportNamedDeclaration(), program->SourceFilePath()); - } - } + ProcessProgramStatements(program, program->Ast()->Statements(), moduleDependencies); for (auto const &[exportName, startLoc] : exportNameMap_) { const bool isType = exportedTypes_.find(exportName) != exportedTypes_.end(); util::StringView originalName = varbinder_->FindNameInAliasMap(program->SourceFilePath(), exportName); @@ -153,6 +163,14 @@ void ImportExportDecls::VisitAnnotationDeclaration(ir::AnnotationDeclaration *an fieldMap_.emplace(annotationDecl->GetBaseName()->Name(), annotationDecl); } +void ImportExportDecls::VisitETSModule(ir::ETSModule *etsModule) +{ + if (etsModule->IsETSScript()) { + return; + } + fieldMap_.emplace(etsModule->Ident()->Name(), etsModule); +} + void ImportExportDecls::VisitExportNamedDeclaration(ir::ExportNamedDeclaration *exportDecl) { for (auto spec : exportDecl->Specifiers()) { diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/importExportDecls.h b/ets2panda/compiler/lowering/ets/topLevelStmts/importExportDecls.h index 291fd87f43..494c4a3d06 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/importExportDecls.h +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/importExportDecls.h @@ -56,6 +56,8 @@ public: * @param global_stmts program global statements */ GlobalClassHandler::ModuleDependencies HandleGlobalStmts(ArenaVector &programs); + void ProcessProgramStatements(parser::Program *program, const ArenaVector &statements, + GlobalClassHandler::ModuleDependencies &moduleDependencies); void VerifyTypeExports(const ArenaVector &programs); void VerifyType(ir::Statement *stmt, parser::Program *program, std::set &exportedTypes, std::set &exportedStatements, @@ -78,6 +80,7 @@ private: void VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration *interfaceDecl) override; void VisitETSImportDeclaration(ir::ETSImportDeclaration *importDecl) override; void VisitAnnotationDeclaration(ir::AnnotationDeclaration *annotationDecl) override; + void VisitETSModule(ir::ETSModule *etsModule) override; private: varbinder::ETSBinder *varbinder_ {nullptr}; diff --git a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp index a88b805202..42996453e3 100644 --- a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp +++ b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp @@ -801,7 +801,7 @@ void InitScopesPhaseETS::HandleProgram(parser::Program *program) } ASSERT(program->Ast() != nullptr); - HandleETSScript(program->Ast()); + HandleETSModule(program->Ast()); } void InitScopesPhaseETS::BindVarDecl(ir::Identifier *binding, ir::Expression *init, varbinder::Decl *decl, @@ -1113,7 +1113,7 @@ void InitScopesPhaseETS::AddGlobalToBinder(parser::Program *program) globalId->SetVariable(var); } -void InitScopesPhaseETS::HandleETSScript(ir::BlockStatement *script) +void InitScopesPhaseETS::HandleETSModule(ir::BlockStatement *script) { for (auto decl : script->Statements()) { if (decl->IsETSImportDeclaration()) { diff --git a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.h b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.h index 452306629f..a87ac260b3 100644 --- a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.h +++ b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.h @@ -323,7 +323,7 @@ public: private: void HandleProgram(parser::Program *program); - void HandleETSScript(ir::BlockStatement *script); + void HandleETSModule(ir::BlockStatement *script); void ParseGlobalClass(ir::ClassDefinition *global); diff --git a/ets2panda/evaluate/scopedDebugInfoPlugin.cpp b/ets2panda/evaluate/scopedDebugInfoPlugin.cpp index 8a28e5fe74..c95de5cd91 100644 --- a/ets2panda/evaluate/scopedDebugInfoPlugin.cpp +++ b/ets2panda/evaluate/scopedDebugInfoPlugin.cpp @@ -406,9 +406,10 @@ parser::Program *ScopedDebugInfoPlugin::CreateEmptyProgram(std::string_view sour parser::Program *program = allocator->New(allocator, GetETSBinder()); program->SetSource({sourceFilePath, "", globalProgram_->SourceFileFolder().Utf8(), true}); program->SetPackageInfo(moduleName, parser::ModuleKind::MODULE); - auto *etsScript = - allocator->New(allocator, ArenaVector(allocator->Adapter()), program); - program->SetAst(etsScript); + auto *emptyIdent = allocator->New("", allocator); + auto *etsModule = allocator->New(allocator, ArenaVector(allocator->Adapter()), + emptyIdent, ir::ModuleFlag::ETSSCRIPT, program); + program->SetAst(etsModule); helpers::AddExternalProgram(globalProgram_, program, moduleName); proxyProgramsCache_.AddProgram(program); diff --git a/ets2panda/ir/annotationAllowed.h b/ets2panda/ir/annotationAllowed.h index b2eadd5ff4..6a32ca01ca 100644 --- a/ets2panda/ir/annotationAllowed.h +++ b/ets2panda/ir/annotationAllowed.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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 @@ -77,6 +77,11 @@ protected: { } + explicit AnnotationAllowed(ArenaAllocator *const allocator, ArenaVector &&statementList) + : T(allocator, std::move(statementList)), annotations_(allocator->Adapter()) + { + } + void AddAnnotations(AnnotationUsage *const annotations) { annotations_.emplace_back(annotations); diff --git a/ets2panda/ir/astNodeMapping.h b/ets2panda/ir/astNodeMapping.h index 4195bcbc1c..ffb3a21a89 100644 --- a/ets2panda/ir/astNodeMapping.h +++ b/ets2panda/ir/astNodeMapping.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 @@ -68,8 +68,6 @@ _(META_PROPERTY_EXPRESSION, MetaProperty) \ _(METHOD_DEFINITION, MethodDefinition) \ _(NAMED_TYPE, NamedType) \ - _(NAMESPACE_DECLARATION, NamespaceDeclaration) \ - _(NAMESPACE_DEFINITION, NamespaceDefinition) \ _(NEW_EXPRESSION, NewExpression) \ _(NULL_LITERAL, NullLiteral) \ _(UNDEFINED_LITERAL, UndefinedLiteral) \ @@ -102,7 +100,7 @@ _(ETS_IMPORT_DECLARATION, ETSImportDeclaration) \ _(ETS_PARAMETER_EXPRESSION, ETSParameterExpression) \ _(ETS_TUPLE, ETSTuple) \ - _(ETS_SCRIPT, ETSScript) \ + _(ETS_MODULE, ETSModule) \ _(SUPER_EXPRESSION, SuperExpression) \ _(STRUCT_DECLARATION, ETSStructDeclaration) \ _(SWITCH_CASE_STATEMENT, SwitchCaseStatement) \ diff --git a/ets2panda/ir/base/classDefinition.h b/ets2panda/ir/base/classDefinition.h index 010735b42a..b0e9e63d50 100644 --- a/ets2panda/ir/base/classDefinition.h +++ b/ets2panda/ir/base/classDefinition.h @@ -51,7 +51,9 @@ enum class ClassDefinitionModifiers : uint32_t { FROM_EXTERNAL = 1U << 10U, LOCAL = 1U << 11U, CLASSDEFINITION_CHECKED = 1U << 12U, - DECLARATION_ID_REQUIRED = DECLARATION | ID_REQUIRED + NAMESPACE_TRANSFORMED = 1U << 13U, + DECLARATION_ID_REQUIRED = DECLARATION | ID_REQUIRED, + ETS_MODULE = NAMESPACE_TRANSFORMED | GLOBAL }; } // namespace ark::es2panda::ir @@ -223,6 +225,16 @@ public: return (modifiers_ & ClassDefinitionModifiers::ANONYMOUS) != 0; } + [[nodiscard]] bool IsNamespaceTransformed() const noexcept + { + return (modifiers_ & ClassDefinitionModifiers::NAMESPACE_TRANSFORMED) != 0; + } + + [[nodiscard]] bool IsModule() const noexcept + { + return IsGlobal() || IsNamespaceTransformed(); + } + [[nodiscard]] es2panda::Language Language() const noexcept { return lang_; @@ -248,6 +260,11 @@ public: modifiers_ |= ClassDefinitionModifiers::ANONYMOUS; } + void SetNamespaceTransformed() noexcept + { + modifiers_ |= ClassDefinitionModifiers::NAMESPACE_TRANSFORMED; + } + [[nodiscard]] ClassDefinitionModifiers Modifiers() const noexcept { return modifiers_; diff --git a/ets2panda/ir/base/namespaceDefinition.cpp b/ets2panda/ir/base/namespaceDefinition.cpp deleted file mode 100644 index 4e859d9ff3..0000000000 --- a/ets2panda/ir/base/namespaceDefinition.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/** - * Copyright (c) 2021-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. - */ - -#include "namespaceDefinition.h" - -#include "checker/TSchecker.h" -#include "checker/ETSchecker.h" -#include "compiler/core/ETSGen.h" -#include "compiler/core/pandagen.h" -#include "ir/astDump.h" -#include "ir/srcDump.h" -#include "ir/base/classStaticBlock.h" -#include "ir/base/methodDefinition.h" -#include "ir/base/scriptFunction.h" -#include "ir/expressions/identifier.h" -#include "ir/ts/tsClassImplements.h" - -namespace ark::es2panda::ir { -const FunctionExpression *NamespaceDefinition::Ctor() const -{ - return ctor_ != nullptr ? ctor_->Value()->AsFunctionExpression() : nullptr; -} - -void NamespaceDefinition::TransformChildren(const NodeTransformer &cb, std::string_view transformationName) -{ - if (ident_ != nullptr) { - if (auto *transformedNode = cb(ident_); ident_ != transformedNode) { - ident_->SetTransformedNode(transformationName, transformedNode); - ident_ = transformedNode->AsIdentifier(); - } - } - - for (auto *&it : VectorIterationGuard(body_)) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode; - } - } -} - -void NamespaceDefinition::Iterate(const NodeTraverser &cb) const -{ - if (ident_ != nullptr) { - cb(ident_); - } - - // NOLINTNEXTLINE(modernize-loop-convert) - for (size_t ix = 0; ix < body_.size(); ix++) { - cb(body_[ix]); - } -} - -void NamespaceDefinition::SetIdent(ir::Identifier *ident) noexcept -{ - ident_ = ident; - if (ident_ != nullptr) { - ident_->SetParent(this); - } -} - -void NamespaceDefinition::Dump(ir::AstDumper *dumper) const -{ - dumper->Add({{"id", AstDumper::Nullish(ident_)}, {"body", body_}}); -} - -void NamespaceDefinition::Dump([[maybe_unused]] ir::SrcDumper *dumper) const -{ - ASSERT(ident_ != nullptr); - - if (IsExported()) { - dumper->Add("export "); - } - - dumper->Add(" {"); - if (!body_.empty()) { - dumper->IncrIndent(); - dumper->Endl(); - for (auto elem : body_) { - elem->Dump(dumper); - if (elem == body_.back()) { - dumper->DecrIndent(); - } - dumper->Endl(); - } - } - dumper->Add("}"); - dumper->Endl(); -} - -void NamespaceDefinition::Compile(compiler::PandaGen *pg) const -{ - pg->GetAstCompiler()->Compile(this); -} - -void NamespaceDefinition::Compile(compiler::ETSGen *etsg) const -{ - etsg->GetAstCompiler()->Compile(this); -} - -checker::Type *NamespaceDefinition::Check(checker::TSChecker *checker) -{ - return checker->GetAnalyzer()->Check(this); -} - -checker::VerifiedType NamespaceDefinition::Check(checker::ETSChecker *checker) -{ - return {this, checker->GetAnalyzer()->Check(this)}; -} - -} // namespace ark::es2panda::ir diff --git a/ets2panda/ir/base/namespaceDefinition.h b/ets2panda/ir/base/namespaceDefinition.h deleted file mode 100644 index 6a2b776c14..0000000000 --- a/ets2panda/ir/base/namespaceDefinition.h +++ /dev/null @@ -1,165 +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. - */ - -#ifndef ES2PANDA_PARSER_INCLUDE_AST_NAMESPACE_DEFINITION_H -#define ES2PANDA_PARSER_INCLUDE_AST_NAMESPACE_DEFINITION_H - -#include "varbinder/scope.h" -#include "varbinder/variable.h" -#include "ir/astNode.h" -#include "ir/expressions/identifier.h" -#include "util/language.h" - -namespace ark::es2panda::ir { -class ClassElement; -class Identifier; -class MethodDefinition; -class TSTypeParameterDeclaration; -class TSTypeParameterInstantiation; -class TSClassImplements; -class TSIndexSignature; - -class NamespaceDefinition : public TypedAstNode { -public: - NamespaceDefinition() = delete; - ~NamespaceDefinition() override = default; - - NO_COPY_SEMANTIC(NamespaceDefinition); - NO_MOVE_SEMANTIC(NamespaceDefinition); - - explicit NamespaceDefinition(Identifier *ident, ArenaVector &&body, MethodDefinition *ctor, - ModifierFlags flags, Language lang) - : TypedAstNode(AstNodeType::NAMESPACE_DEFINITION, flags), - - ident_(ident), - ctor_(ctor), - body_(std::move(body)), - lang_(lang) - { - } - - [[nodiscard]] bool IsScopeBearer() const noexcept override - { - return true; - } - - [[nodiscard]] varbinder::LocalScope *Scope() const noexcept override - { - return scope_; - } - - void SetScope(varbinder::LocalScope *scope) - { - ASSERT(scope_ == nullptr); - scope_ = scope; - } - - void ClearScope() noexcept override - { - scope_ = nullptr; - } - - [[nodiscard]] const Identifier *Ident() const noexcept - { - return ident_; - } - - [[nodiscard]] Identifier *Ident() noexcept - { - return ident_; - } - - void SetIdent(ir::Identifier *ident) noexcept; - - [[nodiscard]] const util::StringView &PrivateId() const noexcept - { - return internalName_; - } - - [[nodiscard]] const util::StringView &InternalName() const noexcept - { - return internalName_; - } - - void SetInternalName(util::StringView internalName) noexcept - { - internalName_ = internalName; - } - - [[nodiscard]] es2panda::Language Language() const noexcept - { - return lang_; - } - - [[nodiscard]] MethodDefinition *Ctor() noexcept - { - return ctor_; - } - - void SetCtor(MethodDefinition *ctor) - { - ctor_ = ctor; - } - - void AddProperties(ArenaVector &&body) - { - for (auto *prop : body) { - prop->SetParent(this); - } - - body_.insert(body_.end(), body.begin(), body.end()); - } - - [[nodiscard]] ArenaVector &Body() noexcept - { - return body_; - } - - [[nodiscard]] const ArenaVector &Body() const noexcept - { - return body_; - } - - const FunctionExpression *Ctor() const; - bool HasPrivateMethod() const; - bool HasComputedInstanceField() const; - bool HasMatchingPrivateKey(const util::StringView &name) const; - - void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) override; - void Iterate(const NodeTraverser &cb) const override; - - void Dump(ir::AstDumper *dumper) const override; - void Dump(ir::SrcDumper *dumper) const override; - void Compile(compiler::PandaGen *pg) const override; - void Compile(compiler::ETSGen *etsg) const override; - checker::Type *Check(checker::TSChecker *checker) override; - checker::VerifiedType Check(checker::ETSChecker *checker) override; - - void Accept(ASTVisitorT *v) override - { - v->Accept(this); - } - -private: - varbinder::LocalScope *scope_ {nullptr}; - util::StringView internalName_ {}; - Identifier *ident_ {}; - MethodDefinition *ctor_ {}; - ArenaVector body_; - es2panda::Language lang_; -}; -} // namespace ark::es2panda::ir - -#endif diff --git a/ets2panda/ir/ets/etsScript.h b/ets2panda/ir/ets/etsModule.cpp similarity index 45% rename from ets2panda/ir/ets/etsScript.h rename to ets2panda/ir/ets/etsModule.cpp index b5620aba1a..f765341a91 100644 --- a/ets2panda/ir/ets/etsScript.h +++ b/ets2panda/ir/ets/etsModule.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * 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 @@ -13,38 +13,40 @@ * limitations under the License. */ -#ifndef ES2PANDA_IR_ETS_SCRIPT_H -#define ES2PANDA_IR_ETS_SCRIPT_H - -#include "ir/statements/blockStatement.h" - -namespace ark::es2panda::parser { -class Program; -} // namespace ark::es2panda::parser +#include "etsModule.h" namespace ark::es2panda::ir { -class ETSScript : public BlockStatement { -public: - explicit ETSScript(ArenaAllocator *allocator, ArenaVector &&statementList, parser::Program *program) - : BlockStatement(allocator, std::move(statementList)), program_(program) - { - type_ = AstNodeType::ETS_SCRIPT; +void ETSModule::Dump(ir::SrcDumper *dumper) const +{ + if (flag_ == ModuleFlag::NAMESPACE) { + if (IsExported()) { + dumper->Add("export "); + } + + if (IsDeclare()) { + dumper->Add("declare "); + } + + dumper->Add("namespace "); + ident_->Dump(dumper); + dumper->Add(" {"); + dumper->IncrIndent(); } - parser::Program *Program() - { - return program_; + if (!Statements().empty()) { + dumper->Endl(); + for (auto elem : Statements()) { + elem->Dump(dumper); + if (elem == Statements().back()) { + dumper->DecrIndent(); + } + dumper->Endl(); + } } - - const parser::Program *Program() const - { - return program_; + if (flag_ == ModuleFlag::NAMESPACE) { + dumper->Add("}"); } +} -private: - parser::Program *program_; -}; } // namespace ark::es2panda::ir - -#endif diff --git a/ets2panda/ir/ets/etsModule.h b/ets2panda/ir/ets/etsModule.h new file mode 100644 index 0000000000..3fdd81038d --- /dev/null +++ b/ets2panda/ir/ets/etsModule.h @@ -0,0 +1,111 @@ +/* + * 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_IR_ETS_MODULE_H +#define ES2PANDA_IR_ETS_MODULE_H + +#include "ir/statements/blockStatement.h" +#include "ir/annotationAllowed.h" +#include "ir/expressions/identifier.h" +#include "ir/srcDump.h" + +namespace ark::es2panda::parser { +class Program; +} // namespace ark::es2panda::parser + +namespace ark::es2panda::ir { + +using ENUMBITOPS_OPERATORS; + +enum class ModuleFlag : uint32_t { + NONE = 0, + ETSSCRIPT = 1U << 0U, + NAMESPACE = 1U << 1U, + NAMESPACE_CHAIN_LAST_NODE = 1U << 2U +}; +} // namespace ark::es2panda::ir + +template <> +struct enumbitops::IsAllowedType : std::true_type { +}; + +namespace ark::es2panda::ir { + +class ETSModule : public AnnotationAllowed { +public: + explicit ETSModule(ArenaAllocator *allocator, ArenaVector &&statementList, Identifier *ident, + ModuleFlag flag, parser::Program *program) + : AnnotationAllowed(allocator, std::move(statementList)), + ident_(ident), + flag_(flag), + program_(program) + { + type_ = AstNodeType::ETS_MODULE; + } + + ir::Identifier *Ident() + { + return ident_; + } + + const ir::Identifier *Ident() const + { + return ident_; + } + + parser::Program *Program() + { + return program_; + } + + [[nodiscard]] bool IsETSScript() const noexcept + { + return (flag_ & ModuleFlag::ETSSCRIPT) != 0; + } + + [[nodiscard]] bool IsNamespace() const noexcept + { + return (flag_ & ModuleFlag::NAMESPACE) != 0; + } + + [[nodiscard]] bool IsNamespaceChainLastNode() const noexcept + { + return (flag_ & ModuleFlag::NAMESPACE_CHAIN_LAST_NODE) != 0; + } + + void SetNamespaceChainLastNode() noexcept + { + ASSERT(IsNamespace()); + flag_ |= ModuleFlag::NAMESPACE_CHAIN_LAST_NODE; + } + + const parser::Program *Program() const + { + return program_; + } + void Dump(ir::SrcDumper *dumper) const override; + void Accept(ASTVisitorT *v) override + { + v->Accept(this); + } + +private: + Identifier *ident_; + ModuleFlag flag_; + parser::Program *program_; +}; +} // namespace ark::es2panda::ir + +#endif diff --git a/ets2panda/ir/ts/tsQualifiedName.cpp b/ets2panda/ir/ts/tsQualifiedName.cpp index ed6bf8ca86..89ae9979a8 100644 --- a/ets2panda/ir/ts/tsQualifiedName.cpp +++ b/ets2panda/ir/ts/tsQualifiedName.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 @@ -58,7 +58,9 @@ void TSQualifiedName::Dump(ir::AstDumper *dumper) const void TSQualifiedName::Dump(ir::SrcDumper *dumper) const { - dumper->Add("TSQualifiedName"); + left_->Dump(dumper); + dumper->Add("."); + right_->Dump(dumper); } void TSQualifiedName::Compile([[maybe_unused]] compiler::PandaGen *pg) const diff --git a/ets2panda/ir/visitor/IterateAstVisitor.h b/ets2panda/ir/visitor/IterateAstVisitor.h index be8018860d..c8b280a325 100644 --- a/ets2panda/ir/visitor/IterateAstVisitor.h +++ b/ets2panda/ir/visitor/IterateAstVisitor.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 @@ -35,7 +35,6 @@ #include "ir/ets/etsReExportDeclaration.h" #include "ir/statements/variableDeclaration.h" #include "ir/statements/variableDeclarator.h" -#include "ir/statements/namespaceDeclaration.h" namespace ark::es2panda::ir::visitor { diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index a10fb769d3..22e831843a 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -34,7 +34,6 @@ #include "ir/base/scriptFunction.h" #include "ir/base/methodDefinition.h" #include "ir/base/spreadElement.h" -#include "ir/statements/namespaceDeclaration.h" #include "ir/expressions/identifier.h" #include "ir/expressions/functionExpression.h" #include "ir/expressions/dummyNode.h" @@ -49,7 +48,7 @@ #include "ir/ets/etsWildcardType.h" #include "ir/ets/etsTuple.h" #include "ir/ets/etsFunctionType.h" -#include "ir/ets/etsScript.h" +#include "ir/ets/etsModule.h" #include "ir/ets/etsTypeReference.h" #include "ir/ets/etsTypeReferencePart.h" #include "ir/ets/etsNullishTypes.h" @@ -81,12 +80,14 @@ using namespace std::literals::string_literals; ETSParser::ETSParser(Program *program, const util::Options &options, ParserStatus status) : TypedParser(program, &options, status), globalProgram_(GetProgram()) { + namespaceNestedRank_ = 0; importPathManager_ = std::make_unique(Allocator(), options); } ETSParser::ETSParser(Program *program, std::nullptr_t) : TypedParser(program, nullptr, ParserStatus::NO_OPTS), globalProgram_(GetProgram()) { + namespaceNestedRank_ = 0; } bool ETSParser::IsETSParser() const noexcept @@ -126,7 +127,7 @@ void ETSParser::ParseProgram(ScriptKind kind) GetProgram()->SetAst(script); } -ir::ETSScript *ETSParser::ParseETSGlobalScript(lexer::SourcePosition startLoc, ArenaVector &statements) +ir::ETSModule *ETSParser::ParseETSGlobalScript(lexer::SourcePosition startLoc, ArenaVector &statements) { ETSNolintParser etsnolintParser(this); etsnolintParser.CollectETSNolints(); @@ -139,9 +140,11 @@ ir::ETSScript *ETSParser::ParseETSGlobalScript(lexer::SourcePosition startLoc, A etsnolintParser.ApplyETSNolintsToStatements(statements); - auto *etsScript = AllocNode(Allocator(), std::move(statements), GetProgram()); - etsScript->SetRange({startLoc, Lexer()->GetToken().End()}); - return etsScript; + auto ident = AllocNode(compiler::Signatures::ETS_GLOBAL, Allocator()); + auto *etsModule = + AllocNode(Allocator(), std::move(statements), ident, ir::ModuleFlag::ETSSCRIPT, GetProgram()); + etsModule->SetRange({startLoc, Lexer()->GetToken().End()}); + return etsModule; } void ETSParser::AddExternalSource(const std::vector &programs) @@ -449,10 +452,6 @@ ir::AstNode *ETSParser::ParseInnerTypeDeclaration(ir::ModifierFlags memberModifi ir::AstNode *ETSParser::ParseInnerConstructorDeclaration(ir::ModifierFlags memberModifiers, const lexer::SourcePosition &startLoc) { - if ((GetContext().Status() & ParserStatus::IN_NAMESPACE) != 0) { - LogSyntaxError({"Namespaces should not have a constructor"}); - } - if ((memberModifiers & (~(ir::ModifierFlags::ACCESS | ir::ModifierFlags::DECLARE | ir::ModifierFlags::NATIVE))) != 0) { LogSyntaxError( @@ -602,15 +601,6 @@ ir::Statement *ETSParser::ParseTypeDeclaration(bool allowStatic) case lexer::TokenType::KEYW_INTERFACE: { return ParseInterfaceDeclaration(false); } - case lexer::TokenType::KEYW_NAMESPACE: { - if (!InAmbientContext()) { - LogSyntaxError("Namespaces are declare only"); - } - GetContext().Status() |= ParserStatus::IN_NAMESPACE; - auto *ns = ParseNamespaceDeclaration(ir::ModifierFlags::DECLARE | ir::ModifierFlags::EXPORT); - GetContext().Status() &= ~ParserStatus::IN_NAMESPACE; - return ns; - } case lexer::TokenType::KEYW_CLASS: { return ParseClassDeclaration(modifiers); } @@ -977,6 +967,9 @@ void ETSParser::ReportIfVarDeclaration(VariableParsingFlags flags) ir::Statement *ETSParser::ParseExport(lexer::SourcePosition startLoc, ir::ModifierFlags modifiers) { + if (!InAmbientContext() && (GetContext().Status() & ParserStatus::IN_NAMESPACE) != 0) { + LogSyntaxError("Export declarations are not permitted in a namespace."); + } ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY || Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE || Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT); diff --git a/ets2panda/parser/ETSparser.h b/ets2panda/parser/ETSparser.h index bc179b3237..75b48bafb7 100644 --- a/ets2panda/parser/ETSparser.h +++ b/ets2panda/parser/ETSparser.h @@ -213,6 +213,21 @@ public: void ApplyAnnotationsToNode(ir::AstNode *node, ArenaVector &&annotations, lexer::SourcePosition pos); + uint32_t GetNamespaceNestedRank() + { + return namespaceNestedRank_; + } + + void IncrementNamespaceNestedRank() + { + namespaceNestedRank_++; + } + + void DecrementNamespaceNestedRank() + { + namespaceNestedRank_--; + } + private: NodeFormatType GetFormatPlaceholderType(); @@ -273,7 +288,7 @@ private: ir::ImportKinds importKind); parser::Program *ParseSource(const SourceFile &sourceFile); void AddExternalSource(const std::vector &programs); - ir::ETSScript *ParseETSGlobalScript(lexer::SourcePosition startLoc, ArenaVector &statements); + ir::ETSModule *ParseETSGlobalScript(lexer::SourcePosition startLoc, ArenaVector &statements); ir::AstNode *ParseImportDefaultSpecifier(ArenaVector *specifiers) override; void *ApplyAnnotationsToClassElement(ir::AstNode *property, ArenaVector &&annotations, @@ -449,8 +464,9 @@ private: ir::ClassDefinition *ParseClassDefinition(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags = ir::ModifierFlags::NONE) override; bool CheckInNamespaceContextIsExported(); - ir::NamespaceDeclaration *ParseNamespaceDeclaration(ir::ModifierFlags flags); - ir::NamespaceDefinition *ParseNamespaceDefinition(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags); + ir::ETSModule *ParseNamespaceStatement(ir::ModifierFlags memberModifiers); + ir::ETSModule *ParseNamespace(ir::ModifierFlags flags); + ir::ETSModule *ParseNamespaceImp(ir::ModifierFlags flags); using NamespaceBody = std::tuple, lexer::SourceRange>; NamespaceBody ParseNamespaceBody(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags); // NOLINTNEXTLINE(google-default-arguments) @@ -490,6 +506,7 @@ private: ir::ModifierFlags ParseTypeVarianceModifier(TypeAnnotationParsingOptions *const options); + bool IsExportedDeclaration(ir::ModifierFlags memberModifiers); ir::Statement *ParseTopLevelDeclStatement(StatementParsingFlags flags); ir::Statement *ParseTopLevelStatement(); @@ -501,6 +518,7 @@ private: friend class InnerSourceParser; private: + uint32_t namespaceNestedRank_; std::optional GetPostPrimaryExpression(ir::Expression *returnExpression, lexer::SourcePosition startLoc, bool ignoreCallExpression, [[maybe_unused]] bool *isChainExpression); diff --git a/ets2panda/parser/ETSparserAnnotations.cpp b/ets2panda/parser/ETSparserAnnotations.cpp index 864b7b1803..edd9ce9716 100644 --- a/ets2panda/parser/ETSparserAnnotations.cpp +++ b/ets2panda/parser/ETSparserAnnotations.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 @@ -253,6 +253,23 @@ ArenaVector ETSParser::ParseAnnotations(bool isTopLevelSt return annotations; } +static bool ApplyAnnotationsToNamespace(ir::ETSModule *ns, ArenaVector &annotations) +{ + if (ns->IsNamespaceChainLastNode()) { + ns->SetAnnotations(std::move(annotations)); + return true; + } + + for (auto *node : ns->Statements()) { + if (node->IsETSModule()) { + if (ApplyAnnotationsToNamespace(node->AsETSModule(), annotations)) { + return true; + } + } + } + return false; +} + void ETSParser::ApplyAnnotationsToNode(ir::AstNode *node, ArenaVector &&annotations, lexer::SourcePosition pos) { @@ -294,6 +311,9 @@ void ETSParser::ApplyAnnotationsToNode(ir::AstNode *node, ArenaVectorAsArrowFunctionExpression()->SetAnnotations(std::move(annotations)); break; + case ir::AstNodeType::ETS_MODULE: + ApplyAnnotationsToNamespace(node->AsETSModule(), annotations); + break; default: LogSyntaxError("Annotations are not allowed on this type of declaration.", pos); } diff --git a/ets2panda/parser/ETSparserClasses.cpp b/ets2panda/parser/ETSparserClasses.cpp index 33de6437fa..773bd730ab 100644 --- a/ets2panda/parser/ETSparserClasses.cpp +++ b/ets2panda/parser/ETSparserClasses.cpp @@ -49,7 +49,6 @@ #include "ir/statements/blockStatement.h" #include "ir/statements/ifStatement.h" #include "ir/statements/labelledStatement.h" -#include "ir/statements/namespaceDeclaration.h" #include "ir/statements/switchStatement.h" #include "ir/statements/throwStatement.h" #include "ir/statements/tryStatement.h" @@ -69,7 +68,7 @@ #include "ir/ets/etsFunctionType.h" #include "ir/ets/etsNewClassInstanceExpression.h" #include "ir/ets/etsNewMultiDimArrayInstanceExpression.h" -#include "ir/ets/etsScript.h" +#include "ir/ets/etsModule.h" #include "ir/ets/etsTypeReference.h" #include "ir/ets/etsTypeReferencePart.h" #include "ir/ets/etsNullishTypes.h" @@ -550,7 +549,7 @@ ir::AstNode *ETSParser::ParseClassElement(const ArenaVector &prop result = ParseInnerConstructorDeclaration(memberModifiers, startLoc); break; case lexer::TokenType::KEYW_NAMESPACE: - result = ParseNamespaceDeclaration(memberModifiers); + result = ParseNamespace(memberModifiers); break; case lexer::TokenType::KEYW_PUBLIC: case lexer::TokenType::KEYW_PRIVATE: diff --git a/ets2panda/parser/ETSparserEnums.cpp b/ets2panda/parser/ETSparserEnums.cpp index 9e268017c1..caaceb8ea2 100644 --- a/ets2panda/parser/ETSparserEnums.cpp +++ b/ets2panda/parser/ETSparserEnums.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 @@ -86,7 +86,7 @@ #include "ir/ets/etsFunctionType.h" #include "ir/ets/etsNewClassInstanceExpression.h" #include "ir/ets/etsNewMultiDimArrayInstanceExpression.h" -#include "ir/ets/etsScript.h" +#include "ir/ets/etsModule.h" #include "ir/ets/etsTypeReference.h" #include "ir/ets/etsTypeReferencePart.h" #include "ir/ets/etsNullishTypes.h" diff --git a/ets2panda/parser/ETSparserNamespaces.cpp b/ets2panda/parser/ETSparserNamespaces.cpp index a0a05b8b82..abca216e97 100644 --- a/ets2panda/parser/ETSparserNamespaces.cpp +++ b/ets2panda/parser/ETSparserNamespaces.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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 @@ -14,107 +14,99 @@ */ #include "ETSparser.h" -#include "ETSNolintParser.h" -#include - -#include "macros.h" -#include "parser/parserFlags.h" -#include "parser/parserStatusContext.h" -#include "util/helpers.h" -#include "util/language.h" -#include "utils/arena_containers.h" -#include "varbinder/varbinder.h" -#include "varbinder/ETSBinder.h" #include "lexer/lexer.h" -#include "lexer/ETSLexer.h" #include "ir/astNode.h" - -#include "ir/statements/namespaceDeclaration.h" +#include "ir/ets/etsModule.h" +#include "utils/arena_containers.h" namespace ark::es2panda::parser { -class FunctionContext; using namespace std::literals::string_literals; -ir::NamespaceDeclaration *ETSParser::ParseNamespaceDeclaration(ir::ModifierFlags flags) +ir::ETSModule *ETSParser::ParseNamespaceStatement(ir::ModifierFlags memberModifiers) { - if ((GetContext().Status() & ParserStatus::IN_NAMESPACE) == 0) { - LogSyntaxError("Namespace not enabled in here."); + auto modifiers = ir::ModifierFlags::NONE; + if (((memberModifiers & ir::ModifierFlags::EXPORT) != 0)) { + modifiers |= ir::ModifierFlags::EXPORT; } - - const lexer::SourcePosition startLoc = Lexer()->GetToken().Start(); - auto modifiers = ir::ClassDefinitionModifiers::NONE; - if (IsExternal()) { - modifiers |= ir::ClassDefinitionModifiers::FROM_EXTERNAL; + if ((memberModifiers & ir::ModifierFlags::DECLARE) != 0) { + modifiers |= ir::ModifierFlags::DECLARE; + GetContext().Status() |= ParserStatus::IN_AMBIENT_CONTEXT; } + GetContext().Status() |= ParserStatus::IN_NAMESPACE; + IncrementNamespaceNestedRank(); - ir::NamespaceDefinition *namespaceDefinition = ParseNamespaceDefinition(modifiers, flags); + ir::ETSModule *result = ParseNamespace(modifiers); - auto *namespaceDecl = AllocNode(namespaceDefinition); - - namespaceDecl->SetRange({startLoc, Lexer()->GetToken().End()}); - return namespaceDecl; + DecrementNamespaceNestedRank(); + if (GetNamespaceNestedRank() == 0) { + GetContext().Status() &= ~ParserStatus::IN_NAMESPACE; + } + if ((memberModifiers & ir::ModifierFlags::DECLARE) != 0) { + GetContext().Status() &= ~ParserStatus::IN_AMBIENT_CONTEXT; + } + return result; } -ir::NamespaceDefinition *ETSParser::ParseNamespaceDefinition(ir::ClassDefinitionModifiers modifiers, - ir::ModifierFlags flags) +ir::ETSModule *ETSParser::ParseNamespace(ir::ModifierFlags flags) { - Lexer()->NextToken(); - flags |= ir::ModifierFlags::DECLARE; - ir::Identifier *identNode = ParseClassIdent(modifiers); - - ArenaVector properties(Allocator()->Adapter()); - ir::MethodDefinition *ctor = nullptr; - lexer::SourceRange bodyRange; - - std::tie(ctor, properties, bodyRange) = ParseNamespaceBody(modifiers, flags); - - auto def = - AllocNode(identNode, std::move(properties), ctor, flags, GetContext().GetLanguage()); - def->SetRange(bodyRange); - return def; + if ((GetContext().Status() & ParserStatus::IN_NAMESPACE) == 0) { + LogSyntaxError("Namespace is allowed only at the top level or inside a namespace."); + } + auto start = Lexer()->GetToken().Start(); + ir::ETSModule *ns = ParseNamespaceImp(flags); + ns->SetRange({start, Lexer()->GetToken().Start()}); + return ns; } -ETSParser::NamespaceBody ETSParser::ParseNamespaceBody(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags) +ir::ETSModule *ETSParser::ParseNamespaceImp(ir::ModifierFlags flags) { - auto savedCtx = SavedStatusContext(&GetContext()); - - lexer::SourcePosition startLoc = Lexer()->GetToken().Start(); - Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT); - - ir::MethodDefinition *ctor = nullptr; - ArenaVector properties(Allocator()->Adapter()); - - SavedClassPrivateContext classContext(this); - - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT && - Lexer()->Lookahead() == static_cast(ARRAY_FORMAT_NODE)) { - properties = std::move(ParseAstNodesArrayFormatPlaceholder()); - if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { - LogSyntaxError("Expected a '}'"); - UNREACHABLE(); + Lexer()->NextToken(); + auto *result = AllocNode(Allocator(), ArenaVector(Allocator()->Adapter()), + ExpectIdentifier(), ir::ModuleFlag::NAMESPACE, globalProgram_); + ir::ETSModule *parent = result; + ir::ETSModule *child = nullptr; + while (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) { + Lexer()->NextToken(); + auto start = Lexer()->GetToken().Start(); + child = AllocNode(Allocator(), ArenaVector(Allocator()->Adapter()), + ExpectIdentifier(), ir::ModuleFlag::NAMESPACE, globalProgram_); + child->SetParent(parent); + child->SetRange({start, Lexer()->GetToken().Start()}); + child->AddModifier(ir::ModifierFlags::EXPORT); + if ((flags & ir::ModifierFlags::DECLARE) != 0) { + child->AddModifier(ir::ModifierFlags::DECLARE); } - } else { - while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { - Lexer()->NextToken(); - continue; - } - - ir::AstNode *property = ParseClassElement(properties, modifiers, flags); - - if (CheckClassElement(property, ctor, properties)) { - continue; - } - - properties.push_back(property); + parent->Statements().emplace_back(child); + parent = child; + } + ExpectToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE); + ArenaVector statements(Allocator()->Adapter()); + while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { + if (Lexer()->GetToken().Type() == lexer::TokenType::EOS) { + LogSyntaxError("Unexpected token, expected '}'"); + break; + } + if (Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_SEMI_COLON)) { + continue; } + auto st = ParseTopLevelStatement(); + if (st == nullptr) { + LogSyntaxError("Failed to parse statement."); + break; + } + statements.emplace_back(st); } - - lexer::SourcePosition endLoc = Lexer()->GetToken().End(); Lexer()->NextToken(); - - return {ctor, std::move(properties), lexer::SourceRange {startLoc, endLoc}}; + if (child != nullptr) { + child->SetNamespaceChainLastNode(); + child->SetStatements(std::move(statements)); + } else { + result->SetNamespaceChainLastNode(); + result->SetStatements(std::move(statements)); + } + result->AddModifier(flags); + return result; } } // namespace ark::es2panda::parser diff --git a/ets2panda/parser/ETSparserStatements.cpp b/ets2panda/parser/ETSparserStatements.cpp index c92d9515ed..7792d66a18 100644 --- a/ets2panda/parser/ETSparserStatements.cpp +++ b/ets2panda/parser/ETSparserStatements.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 @@ -89,7 +89,7 @@ #include "ir/ets/etsFunctionType.h" #include "ir/ets/etsNewClassInstanceExpression.h" #include "ir/ets/etsNewMultiDimArrayInstanceExpression.h" -#include "ir/ets/etsScript.h" +#include "ir/ets/etsModule.h" #include "ir/ets/etsTypeReference.h" #include "ir/ets/etsTypeReferencePart.h" #include "ir/ets/etsNullishTypes.h" @@ -148,6 +148,9 @@ static ir::Statement *ValidateExportableStatement(ETSParser *parser, ir::Stateme lexer::SourcePosition pos) { if (stmt != nullptr) { + if (stmt->IsETSModule()) { + return stmt; + } if ((memberModifiers & ir::ModifierFlags::EXPORT_TYPE) != 0U && !(stmt->IsClassDeclaration() || stmt->IsTSInterfaceDeclaration() || stmt->IsTSTypeAliasDeclaration())) { parser->LogSyntaxError("Can only type export class or interface!", stmt->Start()); @@ -167,13 +170,17 @@ static ir::Statement *ValidateExportableStatement(ETSParser *parser, ir::Stateme return stmt; } +bool ETSParser::IsExportedDeclaration(ir::ModifierFlags memberModifiers) +{ + return (memberModifiers & ir::ModifierFlags::EXPORTED) != 0U && + (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY || + Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE); +} ir::Statement *ETSParser::ParseTopLevelDeclStatement(StatementParsingFlags flags) { auto [memberModifiers, startLoc] = ParseMemberModifiers(); - if ((memberModifiers & (ir::ModifierFlags::EXPORTED)) != 0U && - (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY || - Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE)) { + if (IsExportedDeclaration(memberModifiers)) { return ParseExport(startLoc, memberModifiers); } @@ -191,7 +198,10 @@ ir::Statement *ETSParser::ParseTopLevelDeclStatement(StatementParsingFlags flags case lexer::TokenType::KEYW_LET: result = ParseStatement(flags); break; - case lexer::TokenType::KEYW_NAMESPACE: + case lexer::TokenType::KEYW_NAMESPACE: { + result = ParseNamespaceStatement(memberModifiers); + break; + } case lexer::TokenType::KEYW_STATIC: case lexer::TokenType::KEYW_ABSTRACT: case lexer::TokenType::KEYW_FINAL: diff --git a/ets2panda/parser/ETSparserTypes.cpp b/ets2panda/parser/ETSparserTypes.cpp index d3b481de97..b1a6d47c8b 100644 --- a/ets2panda/parser/ETSparserTypes.cpp +++ b/ets2panda/parser/ETSparserTypes.cpp @@ -47,7 +47,7 @@ #include "ir/ets/etsWildcardType.h" #include "ir/ets/etsTuple.h" #include "ir/ets/etsFunctionType.h" -#include "ir/ets/etsScript.h" +#include "ir/ets/etsModule.h" #include "ir/ets/etsStringLiteralType.h" #include "ir/ets/etsTypeReference.h" #include "ir/ets/etsTypeReferencePart.h" diff --git a/ets2panda/public/CMakeLists.txt b/ets2panda/public/CMakeLists.txt index a231d4efb0..dfcf3e63ed 100644 --- a/ets2panda/public/CMakeLists.txt +++ b/ets2panda/public/CMakeLists.txt @@ -153,7 +153,7 @@ set (HEADERS_TO_BE_PARSED ${ES2PANDA_ROOT}/checker/types/type.h ${ES2PANDA_ROOT}/checker/types/ts/booleanLiteralType.h ${ES2PANDA_ROOT}/checker/types/ts/anyType.h - ${ES2PANDA_ROOT}/ir/ets/etsScript.h + ${ES2PANDA_ROOT}/ir/ets/etsModule.h ${ES2PANDA_ROOT}/ir/ts/tsInferType.h ${ES2PANDA_ROOT}/ir/ts/tsMappedType.h ${ES2PANDA_ROOT}/ir/statements/debuggerStatement.h @@ -393,7 +393,7 @@ set (ES2PANDA_API_GENERATED ${LIBGEN_DIR}/gen/headers/checker/types/ts/voidType.yaml ${LIBGEN_DIR}/gen/headers/checker/types/ets/doubleType.yaml ${LIBGEN_DIR}/gen/headers/ir/statements/expressionStatement.yaml - ${LIBGEN_DIR}/gen/headers/ir/ets/etsScript.yaml + ${LIBGEN_DIR}/gen/headers/ir/ets/etsModule.yaml ${LIBGEN_DIR}/gen/headers/ir/base/metaProperty.yaml ${LIBGEN_DIR}/gen/headers/ir/ts/tsArrayType.yaml ${LIBGEN_DIR}/gen/headers/ir/base/tsSignatureDeclaration.yaml diff --git a/ets2panda/public/headers_parser/supported_types.py b/ets2panda/public/headers_parser/supported_types.py index 299a3fd824..904abd7b9f 100644 --- a/ets2panda/public/headers_parser/supported_types.py +++ b/ets2panda/public/headers_parser/supported_types.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # coding=utf-8 # -# Copyright (c) 2024 Huawei Device Co., Ltd. +# 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 @@ -95,7 +95,7 @@ ast_nodes_supported = [ "ETSImportDeclaration", "ETSParameterExpression", "ETSTuple", - "ETSScript", + "ETSModule", "SuperExpression", "ETSStructDeclaration", "SwitchCaseStatement", diff --git a/ets2panda/test/ast/compiler/ets/ambient_namesapce01.sts b/ets2panda/test/ast/compiler/ets/ambient_namesapce01.sts new file mode 100644 index 0000000000..461469160b --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/ambient_namesapce01.sts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +declare namespace MySpace{ + function foo():void {} + function bar() +} + +/* @@? 17:25 Error TypeError: Native, Abstract and Declare methods cannot have body. */ +/* @@? 18:14 Error TypeError: Native and Declare methods should have explicit return type. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/ambient_namesapce02.sts b/ets2panda/test/ast/compiler/ets/ambient_namesapce02.sts new file mode 100644 index 0000000000..0f76a8585d --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/ambient_namesapce02.sts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +declare namespace MySpace{ + class A{ + a:int = 1 + } +} + +/* @@? 19:5 Error SyntaxError: Initializers are not allowed in ambient contexts. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/ambient_namesapce03.sts b/ets2panda/test/ast/compiler/ets/ambient_namesapce03.sts new file mode 100644 index 0000000000..3210127db6 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/ambient_namesapce03.sts @@ -0,0 +1,24 @@ +/* + * 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. + */ + +declare namespace MySpace{ + class A{ + foo():void {} + bar(){} + } +} + +/* @@? 18:20 Error TypeError: Native, Abstract and Declare methods cannot have body. */ +/* @@? 19:12 Error TypeError: Native and Declare methods should have explicit return type. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/ambient_namesapce04.sts b/ets2panda/test/ast/compiler/ets/ambient_namesapce04.sts new file mode 100644 index 0000000000..798c8ebdfd --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/ambient_namesapce04.sts @@ -0,0 +1,24 @@ +/* + * 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. + */ + +declare namespace MySpace{ + interface A{ + foo():void {} + bar(){} + } +} + +/* @@? 18:20 Error TypeError: Native, Abstract and Declare methods cannot have body. */ +/* @@? 19:12 Error TypeError: Native and Declare methods should have explicit return type. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/ambient_namesapce05.sts b/ets2panda/test/ast/compiler/ets/ambient_namesapce05.sts new file mode 100644 index 0000000000..b22fa8484a --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/ambient_namesapce05.sts @@ -0,0 +1,25 @@ +/* + * 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. + */ + +declare namespace MySpace{ + interface A{ + a:int = 1 + } +} + +/* @@? 18:15 Error SyntaxError: Interface member initialization is prohibited */ +/* @@? 18:17 Error SyntaxError: Unexpected token, expected: ','. */ +/* @@? 18:17 Error SyntaxError: Unexpected token, expected 'private' or identifier */ +/* @@? 19:5 Error SyntaxError: Identifier expected */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/ambient_namesapce06.sts b/ets2panda/test/ast/compiler/ets/ambient_namesapce06.sts new file mode 100644 index 0000000000..fee504838b --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/ambient_namesapce06.sts @@ -0,0 +1,27 @@ +/* + * 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. + */ + +declare namespace MySpace{ + export @interface ClassAuthor { + authorName: string = "Jim" + } +} + +@interface MySpace.ClassAuthor { + authorName: string = "Jima" +} + +/* @@? 23:26 Error TypeError: The initial value does not match the expected value. */ +/* @@? 23:5 Error TypeError: Initializer for field 'authorName' does not match the expected definition in the ambient annotation 'ClassAuthor'. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/ambient_namesapce07.sts b/ets2panda/test/ast/compiler/ets/ambient_namesapce07.sts new file mode 100644 index 0000000000..02d30a782d --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/ambient_namesapce07.sts @@ -0,0 +1,23 @@ +/* + * 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. + */ + +declare namespace A.B.C{ + + class A{ + a:int = 1 + } +} + +/* @@? 20:5 Error SyntaxError: Initializers are not allowed in ambient contexts. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_conflict_for_namespace01.sts b/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_conflict_for_namespace01.sts new file mode 100644 index 0000000000..5253e490db --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_conflict_for_namespace01.sts @@ -0,0 +1,28 @@ +/* + * 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. + */ + +@interface Anno1{} +@interface Anno2{} + +@Anno1 +namespace A.B{} // annotations to B + +namespace A{ + @Anno2 + namespace B{} +} + +/* @@? 24:5 Error SyntaxError: Unable to merge namespaces 'B', because their modifiers are different. */ +/* @@? 24:5 Error SyntaxError: Annotation conflict! Multiple namespace declarations for 'B' cannot each have annotations. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_conflict_for_namespace02.sts b/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_conflict_for_namespace02.sts new file mode 100644 index 0000000000..c5926213cf --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_conflict_for_namespace02.sts @@ -0,0 +1,28 @@ +/* + * 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. + */ + +@interface Anno1{} +@interface Anno2{} + +namespace A{ + @Anno2 + namespace B{} +} + +@Anno1 +namespace A.B{} + +/* @@? 25:13 Error SyntaxError: Unable to merge namespaces 'B', because their modifiers are different. */ +/* @@? 25:13 Error SyntaxError: Annotation conflict! Multiple namespace declarations for 'B' cannot each have annotations. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_duplicate_for_namespace01.sts b/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_duplicate_for_namespace01.sts new file mode 100644 index 0000000000..a8328ababd --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_duplicate_for_namespace01.sts @@ -0,0 +1,34 @@ +/* + * 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. + */ + +@interface Anno1{} +@interface Anno2{} +@interface Anno3{} + +@Anno1 +@Anno1 +namespace A.B{} + +@Anno2 +@Anno2 +namespace A{ + @Anno3 + @Anno3 + namespace C{} +} + +/* @@? 25:2 Error TypeError: Duplicate annotations are not allowed. The annotation 'Anno2' has already been applied to this element. */ +/* @@? 21:2 Error TypeError: Duplicate annotations are not allowed. The annotation 'Anno1' has already been applied to this element. */ +/* @@? 28:6 Error TypeError: Duplicate annotations are not allowed. The annotation 'Anno3' has already been applied to this element. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_duplicate_for_namespace02.sts b/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_duplicate_for_namespace02.sts new file mode 100644 index 0000000000..e3997ab452 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_duplicate_for_namespace02.sts @@ -0,0 +1,34 @@ +/* + * 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. + */ + +@interface Anno1{} +@interface Anno2{} +@interface Anno3{} + +@Anno2 +@Anno2 +namespace A{ + @Anno3 + @Anno3 + namespace C{} +} + +@Anno1 +@Anno1 +namespace A.B{} + +/* @@? 21:2 Error TypeError: Duplicate annotations are not allowed. The annotation 'Anno2' has already been applied to this element. */ +/* @@? 24:6 Error TypeError: Duplicate annotations are not allowed. The annotation 'Anno3' has already been applied to this element. */ +/* @@? 29:2 Error TypeError: Duplicate annotations are not allowed. The annotation 'Anno1' has already been applied to this element. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/namespace_export_invalid01.sts b/ets2panda/test/ast/compiler/ets/namespace_export_invalid01.sts new file mode 100644 index 0000000000..4cc7db74ab --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_export_invalid01.sts @@ -0,0 +1,23 @@ +/* + * 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. + */ +namespace NS { + function bar(): void {} + export { baz } +} + +NS.baz(); + + +/* @@? 17:12 Error SyntaxError: Export declarations are not permitted in a namespace. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/namespace_export_invalid02.sts b/ets2panda/test/ast/compiler/ets/namespace_export_invalid02.sts new file mode 100644 index 0000000000..f12c05eea5 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_export_invalid02.sts @@ -0,0 +1,23 @@ +/* + * 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. + */ +namespace X { + namespace Y { + + } + export {Y} +} + + +/* @@? 19:12 Error SyntaxError: Export declarations are not permitted in a namespace. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace.sts new file mode 100644 index 0000000000..40787912d5 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace.sts @@ -0,0 +1,25 @@ +/* + * 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 {ns as ns1} from "./namespace_ambient_export01" +import {ns as ns2} from "./namespace_ambient_export02" +import {ns as ns3} from "./namespace_ambient_export03" +import {ns as ns4} from "./namespace_ambient_export04" + +ns1.bar() +new ns2.C +new ns3.C +let a:ns4.A = 1 + diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation.sts new file mode 100644 index 0000000000..81a8bac256 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation.sts @@ -0,0 +1,68 @@ +/* + * 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. + */ + +namespace MySpace { + let privateVariable = 123; + + function foo(){} + + interface myInterface{} + + class innerClass implements myInterface{} //ok visible + + enum Color{RED, BLUE, GREEN} + + @interface Anno{ + color :Color + } + + console.log(privateVariable) //ok visible + new innerClass() //ok visible + + @Anno(Color.RED) //ok visible + class C{ + static a:int = 1 + } + + foo() //ok visible +} + +class A implements MySpace.myInterface{} // CTE + +new MySpace.innerClass() // CTE + +@MySpace.Anno(MySpace.Color.RED) // CTE +class C{} + +MySpace.privateVariable = 456; // CTE + +MySpace.foo() // CTE + +new MySpace.C() // CTE + +let a = new Array() // CTE + +MySpace.C.a // CTE + +/* @@? 55:27 Error TypeError: 'C' is not exported in 'MySpace' */ +/* @@? 44:13 Error TypeError: 'innerClass' is not exported in 'MySpace' */ +/* @@? 49:9 Error TypeError: 'privateVariable' is not exported in 'MySpace' */ +/* @@? 51:9 Error TypeError: 'foo' is not exported in 'MySpace' */ +/* @@? 53:13 Error TypeError: 'C' is not exported in 'MySpace' */ +/* @@? 55:27 Error TypeError: 'C' is not exported in 'MySpace' */ +/* @@? 57:9 Error TypeError: 'C' is not exported in 'MySpace' */ +/* @@? 42:28 Error TypeError: 'myInterface' is not exported in 'MySpace' */ +/* @@? 46:10 Error TypeError: 'Anno' is not exported in 'MySpace' */ +/* @@? 46:23 Error TypeError: 'Color' is not exported in 'MySpace' */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_circular_dependencies.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_circular_dependencies.sts new file mode 100644 index 0000000000..159cb8998c --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_circular_dependencies.sts @@ -0,0 +1,25 @@ +/* + * 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. + */ +// Example of circular dependencies in namespaces + +namespace NS1 { + export let value = NS2.constant; // Error: Circular dependency +} + +namespace NS2 { + export let constant = NS1.value; // Error: Circular dependency +} + +/* @@? 18:24 Error TypeError: Circular dependency detected for identifier: value */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_conflicts.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_conflicts.sts new file mode 100644 index 0000000000..2d4ff9dfec --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_conflicts.sts @@ -0,0 +1,24 @@ +/* + * 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. + */ + +namespace ConflictedSpace { + export let InnerSpace = 123; + + export namespace InnerSpace { + export let value = 456; + } +} + +/* @@? 19:22 Error SyntaxError: Variable 'InnerSpace' has already been declared. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_exports.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_exports.sts new file mode 100644 index 0000000000..2f0e189c28 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_exports.sts @@ -0,0 +1,23 @@ +/* + * 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. + */ +// Example of duplicate member declarations within a namespace + +namespace DuplicateSpace { + export let shared = 123; + export let shared = 456; // Error: Duplicate member 'shared' +} + + +/* @@? 19:16 Error SyntaxError: Variable 'shared' has already been declared. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_import_conflicts.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_import_conflicts.sts new file mode 100644 index 0000000000..b2af5a58fe --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_import_conflicts.sts @@ -0,0 +1,29 @@ +/* + * 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. + */ +// Example of accessing non-exported members in merged namespaces + +import { Space2 as Space1 } from "./src02"; + +if (Space1.variable == Space1.constant) { // CTE + Space1.variable = 4321; // CTE +} + +Space1.foo(); // CTE +Space1.foo(1234); //ok + +/* @@? 19:31 Error TypeError: Property 'constant' does not exist on type 'Space2' */ +/* @@? 20:23 Error TypeError: Type 'int' cannot be assigned to type 'String' */ +/* @@? 23:1 Error TypeError: Expected 1 arguments, got 0. */ +/* @@? 23:1 Error TypeError: No matching call signature */ diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_merge_conflicts.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_merge_conflicts.sts new file mode 100644 index 0000000000..dc0d907057 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_merge_conflicts.sts @@ -0,0 +1,21 @@ +/* + * 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. + */ +package P + +export namespace MergeSpace { + export function foo() { return 42; } // Error: Conflicting 'foo()' definitions +} + +/* @@? 19:2 Error TypeError: Function foo is already declared. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_nested_scopes.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_nested_scopes.sts new file mode 100644 index 0000000000..b06cd45c07 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_nested_scopes.sts @@ -0,0 +1,64 @@ +/* + * 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. + */ + +// Example of accessing non-exported members in nested namespaces +namespace OuterSpace { + namespace InnerSpace { + let privateVariable = 123; + + function foo(){} + + interface myInterface{} + + class innerClass implements myInterface{} //ok visible + + enum Color{RED, BLUE, GREEN} + + @interface Anno{ + color :Color + } + + console.log(privateVariable) //ok visible + new innerClass() //ok visible + + @Anno(Color.RED) //ok visible + class C{} + } + + let value = InnerSpace.privateVariable; +} + +class A implements OuterSpace.InnerSpace.myInterface{} // CTE + +new OuterSpace.InnerSpace.innerClass() // CTE + +@OuterSpace.InnerSpace.Anno(OuterSpace.InnerSpace.Color.RED) // CTE +class C{} + +OuterSpace.InnerSpace.privateVariable = 456; // CTE + + +/* @@? 45:16 Error TypeError: 'InnerSpace' is not exported in 'OuterSpace' */ +/* @@? 45:27 Error TypeError: 'innerClass' is not exported in 'InnerSpace' */ +/* @@? 40:27 Error TypeError: 'privateVariable' is not exported in 'InnerSpace' */ +/* @@? 40:27 Error TypeError: 'privateVariable' is not exported in 'InnerSpace' */ +/* @@? 50:12 Error TypeError: 'InnerSpace' is not exported in 'OuterSpace' */ +/* @@? 50:23 Error TypeError: 'privateVariable' is not exported in 'InnerSpace' */ +/* @@? 43:31 Error TypeError: 'InnerSpace' is not exported in 'OuterSpace' */ +/* @@? 43:42 Error TypeError: 'myInterface' is not exported in 'InnerSpace' */ +/* @@? 47:13 Error TypeError: 'InnerSpace' is not exported in 'OuterSpace' */ +/* @@? 47:24 Error TypeError: 'Anno' is not exported in 'InnerSpace' */ +/* @@? 47:40 Error TypeError: 'InnerSpace' is not exported in 'OuterSpace' */ +/* @@? 47:51 Error TypeError: 'Color' is not exported in 'InnerSpace' */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_non_exported_merge.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_non_exported_merge.sts new file mode 100644 index 0000000000..fe1f2e156e --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_non_exported_merge.sts @@ -0,0 +1,29 @@ +/* + * 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. + */ +// Example of accessing non-exported members in merged namespaces + +namespace A { + export namespace B { + export function foo() { return 123; } + } +} + +namespace A.B { + function bar() { return 456; } // Error: 'bar()' is not exported +} + +A.B.bar(); // Error: 'bar()' cannot be accessed + +/* @@? 27:5 Error TypeError: 'bar' is not exported in 'B' */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_scope_resolution.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_scope_resolution.sts new file mode 100644 index 0000000000..8d27d9affd --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_scope_resolution.sts @@ -0,0 +1,25 @@ +/* + * 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. + */ + +// Example of incorrect use of qualified names in namespaces + +namespace A.B { + export function foo() { return "A.B.foo"; } +} + +A.foo(); // Error: 'A' does not contain a member named 'foo' + + +/* @@? 22:3 Error TypeError: Property 'foo' does not exist on type 'A' */ diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_undefined_scopes.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_undefined_scopes.sts new file mode 100644 index 0000000000..925572634c --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_undefined_scopes.sts @@ -0,0 +1,27 @@ +/* + * 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. + */ + +// Example of accessing an undefined nested namespace + +namespace ParentSpace { + export let value = 42; +} + +let result = ParentSpace.ChildSpace.value; // Error: 'ChildSpace' is not defined + +/* @@? 22:26 Error TypeError: Property 'ChildSpace' does not exist on type 'ParentSpace' */ +/* @@? 22:14 Error TypeError: Property 'value' does not exist on type '*TYPE_ERROR*' */ +/* @@? 22:26 Error TypeError: Property 'ChildSpace' does not exist on type 'ParentSpace' */ +/* @@? 22:14 Error TypeError: Property 'value' does not exist on type '*TYPE_ERROR*' */ diff --git a/ets2panda/ir/ets/etsScript.cpp b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_ambient_export01.sts similarity index 80% rename from ets2panda/ir/ets/etsScript.cpp rename to ets2panda/test/ast/compiler/ets/namespace_tests/namespace_ambient_export01.sts index b81af336d6..ecfe7f45a9 100644 --- a/ets2panda/ir/ets/etsScript.cpp +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_ambient_export01.sts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2023 Huawei Device Co., Ltd. + * 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 @@ -13,8 +13,11 @@ * limitations under the License. */ -#include "etsScript.h" +declare namespace ns { + function bar(): void + export { bar } +} -namespace ark::es2panda::ir { +export {ns} +ns.bar(); -} // namespace ark::es2panda::ir diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_ambient_export02.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_ambient_export02.sts new file mode 100644 index 0000000000..b9f863d886 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_ambient_export02.sts @@ -0,0 +1,18 @@ +/* + * 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. + */ +export {ns} +declare namespace ns { + export class C {} +} diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_ambient_export03.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_ambient_export03.sts new file mode 100644 index 0000000000..6340ec3eb3 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_ambient_export03.sts @@ -0,0 +1,21 @@ +/* + * 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. + */ + +declare namespace ns { + export class C { + constructor() + } +} +export {ns} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_ambient_export04.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_ambient_export04.sts new file mode 100644 index 0000000000..8420bd437a --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_ambient_export04.sts @@ -0,0 +1,19 @@ +/* + * 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. + */ + +declare namespace ns { + export type A = Int +} +export {ns} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type01.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type01.sts new file mode 100644 index 0000000000..f9e8c1e2fd --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type01.sts @@ -0,0 +1,22 @@ +/* + * 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. + */ +namespace MySpace { + let a:string = "1" +} + +let a = new MySpace() + +/* @@? 19:13 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ +/* @@? 19:13 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type02.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type02.sts new file mode 100644 index 0000000000..5379bb1813 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type02.sts @@ -0,0 +1,27 @@ +/* + * 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. + */ +namespace MySpace { + let a:string = "1" +} + +class A extends MySpace{} +class B implements MySpace{} +type C = MySpace + +/* @@? 19:17 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ +/* @@? 19:17 Error TypeError: The super type of 'A' class is not extensible. */ +/* @@? 20:20 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ +/* @@? 20:20 Error TypeError: Interface expected here. */ +/* @@? 21:10 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type03.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type03.sts new file mode 100644 index 0000000000..7eef24f6e8 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type03.sts @@ -0,0 +1,24 @@ +/* + * 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. + */ +namespace MySpace { + let a:string = "1" +} + +function foo(a:T){} + +let array:Array = new Array() + +/* @@? 21:17 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ +/* @@? 21:38 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type04.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type04.sts new file mode 100644 index 0000000000..011e1de60c --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type04.sts @@ -0,0 +1,24 @@ +/* + * 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. + */ +namespace MySpace { + let a:string = "1" +} + +function foo(a:T){} + +foo(new MySpace()) + +/* @@? 21:5 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ +/* @@? 21:18 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type05.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type05.sts new file mode 100644 index 0000000000..e8bb77d613 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type05.sts @@ -0,0 +1,25 @@ +/* + * 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. + */ +namespace MySpace { + let a:string = "1" +} + +class A{ + a:T +} + +new A() + +/* @@? 23:7 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type06.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type06.sts new file mode 100644 index 0000000000..0d5cfb283e --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type06.sts @@ -0,0 +1,26 @@ +/* + * 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. + */ +namespace MySpace { + let a:string = "1" +} + +function foo1(a:MySpace){} +function foo2(): MySpace {} + +foo1(new MySpace()) + +/* @@? 20:18 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ +/* @@? 19:17 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ +/* @@? 22:10 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type07.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type07.sts new file mode 100644 index 0000000000..514d932358 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type07.sts @@ -0,0 +1,29 @@ +/* + * 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. + */ +namespace MySpace { + let a:string = "1" +} + +class A{ + a:MySpace +} + +let tuple:[int, string, MySpace] = [1, "1", new MySpace()] +let union:int|string|MySpace = 1 + +/* @@? 23:25 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ +/* @@? 24:22 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ +/* @@? 23:49 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ +/* @@? 20:7 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type08.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type08.sts new file mode 100644 index 0000000000..1f1051e722 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type08.sts @@ -0,0 +1,23 @@ +/* + * 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. + */ +namespace MySpace { + let a:string = "1" +} + +let foo1:(a:MySpace)=>int +let foo2:()=>MySpace + +/* @@? 19:13 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ +/* @@? 20:14 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type09.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type09.sts new file mode 100644 index 0000000000..478994c51b --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type09.sts @@ -0,0 +1,24 @@ +/* + * 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. + */ +namespace MySpace { + let a:string = "1" +} + +let a = 1 as MySpace + +/* @@? 19:14 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ +/* @@? 19:9 Error TypeError: Cannot cast type 'int' to '*TYPE_ERROR*' */ +/* @@? 19:14 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ +/* @@? 19:9 Error TypeError: Cannot cast type 'int' to '*TYPE_ERROR*' */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type10.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type10.sts new file mode 100644 index 0000000000..ffccb2a9a7 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type10.sts @@ -0,0 +1,24 @@ +/* + * 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. + */ +namespace MySpace { + let a:string = "1" +} + +let a = 1 instanceof MySpace + +/* @@? 19:22 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ +/* @@? 19:9 Error TypeError: Bad operand type, the types of the operands must be same type. */ +/* @@? 19:22 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ +/* @@? 19:9 Error TypeError: Bad operand type, the types of the operands must be same type. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type11.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type11.sts new file mode 100644 index 0000000000..208a6dc12f --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type11.sts @@ -0,0 +1,22 @@ +/* + * 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. + */ +namespace MySpace { + let a:string = "1" +} + +let a = MySpace + +/* @@? 19:9 Error TypeError: Unresolved reference MySpace */ +/* @@? 19:9 Error TypeError: Unresolved reference MySpace */ diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type12.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type12.sts new file mode 100644 index 0000000000..4e86c7e41a --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type12.sts @@ -0,0 +1,23 @@ +/* +/* + * 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. + */ +namespace MySpace{ + let a: MySpace +} + +function foo(a: MySpace) {} + +/* @@? 20:17 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ +/* @@? 17:12 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_bad_merged01.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_bad_merged01.sts new file mode 100644 index 0000000000..9cf36e53cd --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_bad_merged01.sts @@ -0,0 +1,26 @@ +/* +/* + * 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. + */ +export namespace A {} +namespace A {} // CTE + +namespace B.C.D {} // C and D are exported +namespace B { + namespace C {} // CTE +} + +/* @@? 17:1 Error SyntaxError: Unable to merge namespaces 'A', because their modifiers are different. */ +/* @@? 21:3 Error SyntaxError: Unable to merge namespaces 'C', because their modifiers are different. */ + diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_bad_merged02.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_bad_merged02.sts new file mode 100644 index 0000000000..b91d8642f3 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_bad_merged02.sts @@ -0,0 +1,33 @@ +/* +/* + * 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. + */ +namespace X { + namespace Y {} +} +namespace X { + export namespace Y {} // CTE +} + +namespace P { + export namespace Q {} + namespace R {} +} +namespace P { + export namespace Q {} // OK + namespace R {} // OK +} + +/* @@? 20:10 Error SyntaxError: Unable to merge namespaces 'Y', because their modifiers are different. */ + diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_merge_conflicts.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_merge_conflicts.sts new file mode 100644 index 0000000000..d8e4709793 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_merge_conflicts.sts @@ -0,0 +1,36 @@ +/* + * 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. + */ +// single file +namespace A { + function foo() { } + function bar() { } + + export namespace C { + function too() { } + } +} + +namespace B { } + +namespace A { + function goo() { bar(); } + function foo() { } // CTE +} + +namespace A.C { + function moo() { too(); } +} + +/* @@? 29:5 Error TypeError: Function foo is already declared. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/src01.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/src01.sts new file mode 100644 index 0000000000..420f08c400 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/src01.sts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +package P + +export namespace MergeSpace { + export function foo() { return "string"; } +} + +/* @@? 18:30 Error TypeError: Function foo is already declared. */ diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/src02.sts b/ets2panda/test/ast/compiler/ets/namespace_tests/src02.sts new file mode 100644 index 0000000000..a7b9ecb8ae --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/src02.sts @@ -0,0 +1,25 @@ +/* + * 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. + */ + +namespace Space1 { + export function foo() { } + export let variable = 1234; + export const constant = 1234; +} + +export namespace Space2 { + export function foo(p: number) { } + export let variable = "1234"; +} diff --git a/ets2panda/test/ast/parser/ets/declare_namespace_5.sts b/ets2panda/test/ast/parser/ets/declare_namespace_5.sts index a9c9ac05e4..457865980f 100644 --- a/ets2panda/test/ast/parser/ets/declare_namespace_5.sts +++ b/ets2panda/test/ast/parser/ets/declare_namespace_5.sts @@ -16,8 +16,8 @@ class A { /* @@ label */namespace ns { dfdfsfdf - /* @@ label1 */} - /* @@ label2 */namespace hehe { + } + /* @@ label1 */namespace hehe { } time: number = foo(); @@ -33,10 +33,10 @@ class A { } class B { - /* @@ label3 */namespace ns { + /* @@ label2 */namespace ns { }ddddddd - /* @@ label4 */time: number = foo(); + /* @@ label3 */time: number = foo(); private uri: string; private routerssdsds() { @@ -48,8 +48,8 @@ class B { } } -/* @@@ label Error SyntaxError: Namespace not enabled in here. */ -/* @@@ label1 Error SyntaxError: Field type annotation expected */ -/* @@@ label2 Error SyntaxError: Namespace not enabled in here. */ -/* @@@ label3 Error SyntaxError: Namespace not enabled in here. */ -/* @@@ label4 Error SyntaxError: Field type annotation expected */ +/* @@@ label Error SyntaxError: Namespace is allowed only at the top level or inside a namespace. */ +/* @@@ label1 Error SyntaxError: Namespace is allowed only at the top level or inside a namespace. */ +/* @@@ label2 Error SyntaxError: Namespace is allowed only at the top level or inside a namespace. */ +/* @@@ label3 Error SyntaxError: Field type annotation expected */ + diff --git a/ets2panda/test/ast/parser/ets/namespace_badtoken01.sts b/ets2panda/test/ast/parser/ets/namespace_badtoken01.sts new file mode 100644 index 0000000000..fb426890b2 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/namespace_badtoken01.sts @@ -0,0 +1,23 @@ +/* + * 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. + */ + +namespace MySpace{ + ... +} + +/* @@? 17:5 Error SyntaxError: Unexpected token '...'. */ +/* @@? 17:5 Error SyntaxError: Failed to parse statement. */ +/* @@? 18:1 Error SyntaxError: Unexpected token '}'. */ + diff --git a/ets2panda/test/ast/parser/ets/namespace_badtoken02.sts b/ets2panda/test/ast/parser/ets/namespace_badtoken02.sts new file mode 100644 index 0000000000..3db41b97a2 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/namespace_badtoken02.sts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +namespace MySpace{ + +/* @@? 18:67 Error SyntaxError: Unexpected token, expected '}' */ \ No newline at end of file diff --git a/ets2panda/test/ast/parser/ets/namespace_badtoken03.sts b/ets2panda/test/ast/parser/ets/namespace_badtoken03.sts new file mode 100644 index 0000000000..372909c895 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/namespace_badtoken03.sts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +namespace MySpace{ +}} +/* @@? 17:2 Error SyntaxError: Unexpected token '}'. */ \ No newline at end of file diff --git a/ets2panda/test/ast/parser/ets/namespace_badtoken04.sts b/ets2panda/test/ast/parser/ets/namespace_badtoken04.sts new file mode 100644 index 0000000000..7b075bd2e4 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/namespace_badtoken04.sts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +declare namespace MySpace{ + foo():void +} +/* @@? 17:10 Error SyntaxError: Unexpected token ':'. */ +/* @@? 17:10 Error SyntaxError: Unexpected token ':'. */ +/* @@? 17:10 Error SyntaxError: Failed to parse statement. */ +/* @@? 18:1 Error SyntaxError: Unexpected token '}'. */ \ No newline at end of file diff --git a/ets2panda/test/runtime/ets/annotation_tests/annotationForNamespace.sts b/ets2panda/test/runtime/ets/annotation_tests/annotationForNamespace.sts new file mode 100644 index 0000000000..7138c24758 --- /dev/null +++ b/ets2panda/test/runtime/ets/annotation_tests/annotationForNamespace.sts @@ -0,0 +1,29 @@ +/* + * 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. +*/ + +@interface Anno1{} +@interface Anno2{} +@interface Anno3{} + +@Anno1 +namespace A.B{} // annotations to B + +@Anno2 +namespace A{ + @Anno3 + namespace C{} +} + +function main(){} \ No newline at end of file diff --git a/ets2panda/test/runtime/ets/namespace_tests/namespace_basic.sts b/ets2panda/test/runtime/ets/namespace_tests/namespace_basic.sts new file mode 100644 index 0000000000..92b0aefcf7 --- /dev/null +++ b/ets2panda/test/runtime/ets/namespace_tests/namespace_basic.sts @@ -0,0 +1,43 @@ +/* + * 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. + */ + +namespace BasicNamespace { + // Exported members + export function greet() { + return "Hello, BasicNamespace!"; + } + + export let counter = 0; + export const maxCounter = 100; + + export function incrementCounter() { + if (counter < maxCounter) { + counter++; + } + } +} + +function main() { + // Reset counter to ensure clean state for each execution + BasicNamespace.counter = 0; + + // Test access to namespace members + assert BasicNamespace.greet() == "Hello, BasicNamespace!": "Namespace function failed"; + assert BasicNamespace.counter == 0: "Initial counter value is incorrect"; + + // Test function usage and variable updates + BasicNamespace.incrementCounter(); + assert BasicNamespace.counter == 1: "Counter increment failed"; +} diff --git a/ets2panda/test/runtime/ets/namespace_tests/namespace_deeplt_nested.sts b/ets2panda/test/runtime/ets/namespace_tests/namespace_deeplt_nested.sts new file mode 100644 index 0000000000..cbc2931367 --- /dev/null +++ b/ets2panda/test/runtime/ets/namespace_tests/namespace_deeplt_nested.sts @@ -0,0 +1,35 @@ +/* + * 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. + */ + +namespace EdgeCasesNamespace { + export namespace Deeply.Nested.Namespace { + export function deepFunction() { + return "Deeply Nested Function"; + } + } + + export function recursiveFunction(n: number): number { + if (n == 0) return 0; + return n + recursiveFunction(n - 1); + } +} + +function main() { + // Test access to deeply nested namespace function + assert EdgeCasesNamespace.Deeply.Nested.Namespace.deepFunction() == "Deeply Nested Function": "Deeply nested function failed"; + + // Test recursive function + assert EdgeCasesNamespace.recursiveFunction(5) == 15: "Recursive function failed"; +} diff --git a/ets2panda/test/runtime/ets/namespace_tests/namespace_execution_statements_test01.sts b/ets2panda/test/runtime/ets/namespace_tests/namespace_execution_statements_test01.sts new file mode 100644 index 0000000000..6d4ea4f7d4 --- /dev/null +++ b/ets2panda/test/runtime/ets/namespace_tests/namespace_execution_statements_test01.sts @@ -0,0 +1,85 @@ +/* + * 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. + */ + +namespace ComprehensiveNamespace { + // 1. Variable assignment + export let counter = 0; + export let message = "Initial message"; + + // 2. Assignment expression + counter = counter + 5; + + // 3. Function declaration and call + export function incrementCounter() { + counter++; + } + + export function resetMessage() { + message = "Message reset inside namespace"; + } + + // 4. Conditional statement + export function checkCounter() { + if (counter > 5) { + message = "Counter is greater than 5"; + } else { + message = "Counter is less than or equal to 5"; + } + } + + // 5. Loop statement + export function loopTest() { + let sum = 0; + for (let i = 1; i <= 5; i++) { + sum += i; + } + return sum; + } + + // Utility function to reset the state of the namespace + export function resetState() { + counter = 0; + message = "Initial message"; + counter = counter + 5; // Reapply the assignment expression + } +} + +function main() { + // Reset namespace state before running tests + ComprehensiveNamespace.resetState(); + + // 1. Test variable assignment + assert ComprehensiveNamespace.counter == 5: "Counter should be 5 after assignment"; + + // 2. Test assignment expression + assert ComprehensiveNamespace.message == "Initial message": "Message should be the initial value"; + + // 3. Test function call + ComprehensiveNamespace.incrementCounter(); + assert ComprehensiveNamespace.counter == 6: "Counter should be 6 after increment"; + + ComprehensiveNamespace.resetMessage(); + assert ComprehensiveNamespace.message == "Message reset inside namespace": "Message should be reset after function call"; + + // 4. Test conditional statement + ComprehensiveNamespace.checkCounter(); + assert ComprehensiveNamespace.message == "Counter is greater than 5": "Condition failed for counter > 5"; + + // 5. Test loop statement + let loopResult = ComprehensiveNamespace.loopTest(); + assert loopResult == 15: "Loop test failed, sum should be 15"; +} + + diff --git a/ets2panda/test/runtime/ets/namespace_tests/namespace_execution_statements_test02.sts b/ets2panda/test/runtime/ets/namespace_tests/namespace_execution_statements_test02.sts new file mode 100644 index 0000000000..47a985ad9c --- /dev/null +++ b/ets2panda/test/runtime/ets/namespace_tests/namespace_execution_statements_test02.sts @@ -0,0 +1,100 @@ +/* + * 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. + */ + +namespace MySpace { + // 1. Variable definition and assignment + export let count = 123; + export let message = "Initial message"; + + // 2. Function definition + export function resetMessage() { + message = "Message has been reset"; + } + + // 3. Interface definition + export interface IShape { + area(): number; + } + + // 4. Class definition implementing the interface + export class Rectangle implements IShape { + width: number; + height: number; + + constructor(width: number, height: number) { + this.width = width; + this.height = height; + } + + area(): number { + return this.width * this.height; + } + } + + // 5. Enum definition + export enum Color { + RED, + GREEN, + BLUE + } + + // 6. Annotations definition + export @interface Anno { + color: Color + } + + // Reset function to initialize the variables to their default values + export function resetState() { + count = 123; + message = "Initial message"; + } + + // Update values (for testing) + count = 456; + resetMessage(); + let shape: IShape = new Rectangle(5, 10); + + @Anno(Color.RED) + class ColoredRectangle {} + +} + +// Assertions outside the namespace +MySpace.resetState(); // Reset the state before running assertions +MySpace.count = 456; +assert MySpace.count == 456: "Count should be updated to 456 outside namespace"; + +MySpace.resetMessage(); +assert MySpace.message == "Message has been reset": "Message should be reset outside namespace"; + +let rectangleShape: MySpace.IShape = new MySpace.Rectangle(5, 10); +assert rectangleShape.area() == 50: "Area of rectangleShape should be 50 outside namespace"; + +// Test code starts here +function main() { + // Reset state before running tests to ensure no previous state affects the tests + MySpace.resetState(); + + // 1. Test variable assignment + assert MySpace.count == 123: "Count should be updated to 456"; + + // 2. Test function call + MySpace.resetMessage(); + assert MySpace.message == "Message has been reset": "Message should be reset after function call"; + + // 3. Test class instantiation and interface implementation + let rectangle = new MySpace.Rectangle(5, 10); + assert rectangle.area() == 50: "Area of rectangle should be 50"; +} diff --git a/ets2panda/test/runtime/ets/namespace_tests/namespace_merge_test.sts b/ets2panda/test/runtime/ets/namespace_tests/namespace_merge_test.sts new file mode 100644 index 0000000000..1e3d48c37d --- /dev/null +++ b/ets2panda/test/runtime/ets/namespace_tests/namespace_merge_test.sts @@ -0,0 +1,37 @@ +/* + * 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. + */ +namespace A{ + export let a = 1 + export function foo1():string {return "foo1"} +} + +namespace A{ + export let b = 2 + export function foo2():string {return "foo2"} +} + +namespace A{ + export let c = 3 + export function foo3():string {return "foo3"} +} + +function main(){ + assert A.a == 1 + assert A.b == 2 + assert A.c == 3 + assert A.foo1() == "foo1" + assert A.foo2() == "foo2" + assert A.foo3() == "foo3" +} \ No newline at end of file diff --git a/ets2panda/test/runtime/ets/namespace_tests/namespace_merged.sts b/ets2panda/test/runtime/ets/namespace_tests/namespace_merged.sts new file mode 100644 index 0000000000..0d95942ad1 --- /dev/null +++ b/ets2panda/test/runtime/ets/namespace_tests/namespace_merged.sts @@ -0,0 +1,32 @@ +/* + * 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. + */ + +namespace MergedNamespace { + export function functionOne() { + return "Function One"; + } +} + +namespace MergedNamespace { + export function functionTwo() { + return "Function Two"; + } +} + +function main() { + // Test merged namespace access + assert MergedNamespace.functionOne() == "Function One": "Function one failed"; + assert MergedNamespace.functionTwo() == "Function Two": "Function two failed"; +} diff --git a/ets2panda/ir/statements/namespaceDeclaration.h b/ets2panda/test/runtime/ets/namespace_tests/namespace_nested.sts similarity index 30% rename from ets2panda/ir/statements/namespaceDeclaration.h rename to ets2panda/test/runtime/ets/namespace_tests/namespace_nested.sts index 29b4b5bdc0..62b3ed3e14 100644 --- a/ets2panda/ir/statements/namespaceDeclaration.h +++ b/ets2panda/test/runtime/ets/namespace_tests/namespace_nested.sts @@ -1,4 +1,4 @@ -/** +/* * 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. @@ -13,54 +13,39 @@ * limitations under the License. */ -#ifndef ES2PANDA_IR_STATEMENT_DECLARE_NAMESPACE_DECLARATION_H -#define ES2PANDA_IR_STATEMENT_DECLARE_NAMESPACE_DECLARATION_H - -#include "ir/statement.h" -#include "ir/visitor/AstVisitor.h" -#include "ir/base/namespaceDefinition.h" - -namespace ark::es2panda::ir { -class NamespaceDeclaration : public Statement { -public: - NamespaceDeclaration() = delete; - ~NamespaceDeclaration() override = default; +namespace OuterNamespace { + export function outerFunction() { + return "Outer function"; + } - NO_COPY_SEMANTIC(NamespaceDeclaration); - NO_MOVE_SEMANTIC(NamespaceDeclaration); + export namespace InnerNamespace { + export function innerFunction() { + return "Inner function"; + } - explicit NamespaceDeclaration(NamespaceDefinition *def) : Statement(AstNodeType::NAMESPACE_DECLARATION), def_(def) - { - } + export let sharedValue = 50; - NamespaceDefinition *Definition() - { - return def_; + // Utility function to reset the state of InnerNamespace + export function resetState() { + sharedValue = 50; // Reset sharedValue to its initial state + } } - const NamespaceDefinition *Definition() const - { - return def_; + // Utility function to reset the state of OuterNamespace + export function resetOuterState() { + InnerNamespace.resetState(); } +} - void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) override; - void Iterate(const NodeTraverser &cb) const override; - void Dump(ir::AstDumper *dumper) const override; - void Dump(ir::SrcDumper *dumper) const override; - void Compile(compiler::PandaGen *pg) const override; - void Compile(compiler::ETSGen *etsg) const override; - - checker::Type *Check(checker::TSChecker *checker) override; - checker::VerifiedType Check(checker::ETSChecker *checker) override; - - void Accept(ASTVisitorT *v) override - { - v->Accept(this); - } +function main() { + // Reset OuterNamespace and InnerNamespace state before running tests + OuterNamespace.resetOuterState(); -private: - NamespaceDefinition *def_; -}; -} // namespace ark::es2panda::ir + // Test access to outer and inner namespace members + assert OuterNamespace.outerFunction() == "Outer function": "Outer function failed"; + assert OuterNamespace.InnerNamespace.innerFunction() == "Inner function": "Inner function failed"; -#endif + // Test modification of shared value in inner namespace + OuterNamespace.InnerNamespace.sharedValue = OuterNamespace.InnerNamespace.sharedValue + 25; + assert OuterNamespace.InnerNamespace.sharedValue == 75: "Shared value update failed"; +} \ No newline at end of file diff --git a/ets2panda/test/runtime/ets/namespace_tests/namespace_qualified.sts b/ets2panda/test/runtime/ets/namespace_tests/namespace_qualified.sts new file mode 100644 index 0000000000..de62eec20e --- /dev/null +++ b/ets2panda/test/runtime/ets/namespace_tests/namespace_qualified.sts @@ -0,0 +1,49 @@ +/* + * 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. + */ + +namespace QualifiedNamespace { + export namespace LevelOne { + export namespace LevelTwo { + export function qualifiedFunction() { + return "Qualified Function"; + } + + export let qualifiedValue = 100; + + // Utility function to reset the state of LevelTwo + export function resetState() { + qualifiedValue = 100; // Reset qualifiedValue to its initial state + } + } + } + + // Utility function to reset the state of LevelOne and LevelTwo + export function resetQualifiedState() { + LevelOne.LevelTwo.resetState(); + } +} + +function main() { + // Reset QualifiedNamespace state before running tests + QualifiedNamespace.resetQualifiedState(); + + // Test access to deeply qualified namespace members + assert QualifiedNamespace.LevelOne.LevelTwo.qualifiedFunction() == "Qualified Function": "Qualified function access failed"; + assert QualifiedNamespace.LevelOne.LevelTwo.qualifiedValue == 100: "Qualified value access failed"; + + // Test modification of qualified value + QualifiedNamespace.LevelOne.LevelTwo.qualifiedValue = QualifiedNamespace.LevelOne.LevelTwo.qualifiedValue + 50; + assert QualifiedNamespace.LevelOne.LevelTwo.qualifiedValue == 150: "Qualified value update failed"; +} \ No newline at end of file diff --git a/ets2panda/ir/statements/namespaceDeclaration.cpp b/ets2panda/test/runtime/ets/namespace_tests/namespace_with_annotations.sts similarity index 33% rename from ets2panda/ir/statements/namespaceDeclaration.cpp rename to ets2panda/test/runtime/ets/namespace_tests/namespace_with_annotations.sts index 258e3cad8f..7508176906 100644 --- a/ets2panda/ir/statements/namespaceDeclaration.cpp +++ b/ets2panda/test/runtime/ets/namespace_tests/namespace_with_annotations.sts @@ -1,4 +1,4 @@ -/** +/* * 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. @@ -13,46 +13,59 @@ * limitations under the License. */ -#include "namespaceDeclaration.h" +enum Color{RED, BLUE, GREEN} -#include "checker/TSchecker.h" -#include "compiler/core/ETSGen.h" -#include "compiler/core/pandagen.h" -#include "ir/astDump.h" -#include "ir/srcDump.h" - -namespace ark::es2panda::ir { -void NamespaceDeclaration::TransformChildren([[maybe_unused]] const NodeTransformer &cb, - [[maybe_unused]] std::string_view const transformationName) -{ +@interface Anno{} +@interface ClassAuthor { + authorName: string = "Jim" + authorAge: number = -35 + testBool: boolean = false + favorColor: Color = Color.BLUE + color: Color[] = [Color.RED, Color.BLUE] + reviewers: string[] = ["Bob", "Jim", "Tom"] + reviewersAge: number[] = [18, 21, 32] + testBools: boolean[] = [false, true, false] + mutiArray: number[][] = [ + [1, 2, 3], + [4, +5, 6], + [7, 8, -9] + ] } -void NamespaceDeclaration::Iterate([[maybe_unused]] const NodeTraverser &cb) const {} +@Anno +@ClassAuthor +namespace A{ + @Anno + @ClassAuthor + let a = 1 -void NamespaceDeclaration::Dump(ir::AstDumper *dumper) const -{ - dumper->Add({{"type", "NamespaceDeclaration"}, {"definition", def_}}); -} + @Anno + @ClassAuthor + function foo(@Anno a:int){} -void NamespaceDeclaration::Dump([[maybe_unused]] ir::SrcDumper *dumper) const {} + @Anno + @ClassAuthor + interface MyInterface{ + @Anno + @ClassAuthor + value:string -void NamespaceDeclaration::Compile(compiler::PandaGen *pg) const -{ - pg->GetAstCompiler()->Compile(this); -} + @Anno + @ClassAuthor + bar(){} + } -void NamespaceDeclaration::Compile(compiler::ETSGen *etsg) const -{ - etsg->GetAstCompiler()->Compile(this); -} + @Anno + @ClassAuthor + class A{ + @Anno + @ClassAuthor + b:number = 1 -checker::Type *NamespaceDeclaration::Check(checker::TSChecker *checker) -{ - return checker->GetAnalyzer()->Check(this); + @Anno + @ClassAuthor + foo(){} + } } -checker::VerifiedType NamespaceDeclaration::Check(checker::ETSChecker *checker) -{ - return {this, checker->GetAnalyzer()->Check(this)}; -} -} // namespace ark::es2panda::ir +function main(){} \ No newline at end of file diff --git a/ets2panda/test/runtime/ets/namespace_tests/nested_namespace_plus_equal.sts b/ets2panda/test/runtime/ets/namespace_tests/nested_namespace_plus_equal.sts new file mode 100644 index 0000000000..c30bab3e3f --- /dev/null +++ b/ets2panda/test/runtime/ets/namespace_tests/nested_namespace_plus_equal.sts @@ -0,0 +1,24 @@ +/* + * 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. + */ + +namespace OuterNamespace { + export let outerValue = 50; + export namespace InnerNamespace { + export let innerValue = 50; + } + +} +OuterNamespace.outerValue += 1 +OuterNamespace.InnerNamespace.innerValue += 1 diff --git a/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt b/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt index 3deab8b181..da5abbe910 100644 --- a/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt +++ b/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt @@ -60,3 +60,6 @@ lambdaWithLocalClassAccess.sts #Issue 21065 implementsClassPropertyUnionType1.sts implementsClassPropertyUnionType2.sts + +#Issue 21188 +namespace_tests/nested_namespace_plus_equal.sts diff --git a/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt b/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt index e4b81b40d4..4c237de7d8 100644 --- a/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt +++ b/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt @@ -249,3 +249,19 @@ runtime/ets/interfacePropertyFunctionType.sts #Issue 21065 runtime/ets/implementsClassPropertyUnionType1.sts runtime/ets/implementsClassPropertyUnionType2.sts + +#New failures at #FailKind.SRC_DUMPER_FAI +ast/compiler/ets/ambient_namesapce01.sts +ast/compiler/ets/ambient_namesapce03.sts +ast/compiler/ets/ambient_namesapce04.sts +ast/compiler/ets/ambient_namesapce06.sts +ast/compiler/ets/namespace_tests/namespace_access_violation.sts +ast/compiler/ets/namespace_tests/namespace_access_violation_import_conflicts.sts +ast/compiler/ets/namespace_tests/namespace_access_violation_nested_scopes.sts +runtime/ets/namespace_tests/namespace_execution_statements_test02.sts +ast/compiler/ets/namespace_tests/namespace_access_violation_merge_conflicts.sts +ast/compiler/ets/namespace_tests/src01.sts +ast/compiler/ets/namespace_tests/namespace.sts +ast/compiler/ets/namespace_tests/namespace_ambient_export01.sts +ast/compiler/ets/namespace_tests/namespace_ambient_export02.sts +ast/compiler/ets/namespace_tests/namespace_ambient_export03.sts diff --git a/ets2panda/test/unit/extern_flag_test.cpp b/ets2panda/test/unit/extern_flag_test.cpp index 83bfa6f700..5594a35113 100644 --- a/ets2panda/test/unit/extern_flag_test.cpp +++ b/ets2panda/test/unit/extern_flag_test.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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 @@ -16,7 +16,6 @@ #include #include "assembler/assembly-program.h" -#include "es2panda.h" #include "generated/signatures.h" #include "libpandabase/mem/mem.h" #include "macros.h" @@ -51,14 +50,21 @@ public: ASSERT_NE(program_.get(), nullptr); } - void CheckExternalFlag(std::string_view functionName) + void CheckRecordExternalFlag(std::string_view recordName) + { + pandasm::Record *record = GetRecord(recordName, program_); + ASSERT_TRUE(record != nullptr) << "Record '" << recordName << "' not found"; + ASSERT_TRUE(HasExternalFlag(record)) << "Record '" << record->name << "' doesn't have External flag"; + } + + void CheckFunctionExternalFlag(std::string_view functionName) { pandasm::Function *fn = GetFunction(functionName); ASSERT_TRUE(fn != nullptr) << "Function '" << functionName << "' not found"; ASSERT_TRUE(HasExternalFlag(fn)) << "Function '" << fn->name << "' doesn't have External flag"; } - void CheckNoExternalFlag(std::string_view functionName) + void CheckFunctionNoExternalFlag(std::string_view functionName) { pandasm::Function *fn = GetFunction(functionName); ASSERT_TRUE(fn != nullptr) << "Function '" << functionName << "' not found"; @@ -71,6 +77,11 @@ private: return (fn->metadata->GetAttribute("external")); } + bool HasExternalFlag(pandasm::Record *record) + { + return (record->metadata->GetAttribute("external")); + } + NO_COPY_SEMANTIC(DeclareTest); NO_MOVE_SEMANTIC(DeclareTest); @@ -102,6 +113,15 @@ private: return &it->second; } + pandasm::Record *GetRecord(std::string_view recordName, const std::unique_ptr &program) + { + auto it = program->recordTable.find(recordName.data()); + if (it == program->recordTable.end()) { + return nullptr; + } + return &it->second; + } + private: std::unique_ptr program_ {}; }; @@ -112,7 +132,7 @@ TEST_F(DeclareTest, function_without_overloads_0) SetCurrentProgram(R"( declare function foo(tmp: double): string )"); - CheckExternalFlag("ETSGLOBAL.foo:f64;std.core.String;"); + CheckFunctionExternalFlag("ETSGLOBAL.foo:f64;std.core.String;"); } TEST_F(DeclareTest, function_with_overloads_0) @@ -120,8 +140,8 @@ TEST_F(DeclareTest, function_with_overloads_0) SetCurrentProgram(R"( declare function foo(tmp?: double): string )"); - CheckExternalFlag("ETSGLOBAL.foo:std.core.Object;std.core.String;"); - CheckExternalFlag("ETSGLOBAL.foo:std.core.String;"); + CheckFunctionExternalFlag("ETSGLOBAL.foo:std.core.Object;std.core.String;"); + CheckFunctionExternalFlag("ETSGLOBAL.foo:std.core.String;"); } // === Method of class === @@ -132,8 +152,8 @@ TEST_F(DeclareTest, noImplclass_def_with_overload_0) public foo(arg?: int): string } )"); - CheckExternalFlag("my_class.foo:std.core.Object;std.core.String;"); - CheckExternalFlag("my_class.foo:std.core.String;"); + CheckFunctionExternalFlag("my_class.foo:std.core.Object;std.core.String;"); + CheckFunctionExternalFlag("my_class.foo:std.core.String;"); } // === Constructor of class === @@ -144,7 +164,7 @@ TEST_F(DeclareTest, class_constructor_without_parameters_0) static x: double } )"); - CheckExternalFlag("A_class.:void;"); + CheckFunctionExternalFlag("A_class.:void;"); } TEST_F(DeclareTest, class_constructor_without_parameters_1) @@ -154,7 +174,7 @@ TEST_F(DeclareTest, class_constructor_without_parameters_1) constructor(); } )"); - CheckExternalFlag("A.:void;"); + CheckFunctionExternalFlag("A.:void;"); } TEST_F(DeclareTest, class_implicit_constructor_0) @@ -163,7 +183,7 @@ TEST_F(DeclareTest, class_implicit_constructor_0) declare class A { } )"); - CheckExternalFlag("A.:void;"); + CheckFunctionExternalFlag("A.:void;"); } // === Method of interface === @@ -174,8 +194,17 @@ TEST_F(DeclareTest, noImplinterface_def_with_overload_0) foo(arg?: int): void } )"); - CheckExternalFlag("my_inter.foo:std.core.Object;void;"); - CheckExternalFlag("my_inter.foo:void;"); + CheckFunctionExternalFlag("my_inter.foo:std.core.Object;void;"); + CheckFunctionExternalFlag("my_inter.foo:void;"); +} + +TEST_F(DeclareTest, namespace_0) +{ + SetCurrentProgram(R"( + declare namespace A { + } + )"); + CheckRecordExternalFlag("A"); } } // namespace ark::es2panda::compiler::test diff --git a/ets2panda/test/unit/plugin/plugin_proceed_to_state_update_statements_lambda.cpp b/ets2panda/test/unit/plugin/plugin_proceed_to_state_update_statements_lambda.cpp index 187359b54c..b2343247fa 100644 --- a/ets2panda/test/unit/plugin/plugin_proceed_to_state_update_statements_lambda.cpp +++ b/ets2panda/test/unit/plugin/plugin_proceed_to_state_update_statements_lambda.cpp @@ -58,7 +58,7 @@ int main(int argc, char **argv) std::cout << impl->AstNodeDumpJSONConst(context, programNode) << std::endl; - std::cout << impl->IsETSScript(programNode) << std::endl; + std::cout << impl->IsETSModule(programNode) << std::endl; std::size_t n = 0; es2panda_AstNode **statements = impl->BlockStatementStatements(context, programNode, &n); diff --git a/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_iii.cpp b/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_iii.cpp index 5bdf936c54..5975f32f48 100644 --- a/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_iii.cpp +++ b/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_iii.cpp @@ -17,27 +17,33 @@ #include namespace ark::es2panda { -// apiName: CreateETSScript +// apiName: CreateETSModule TEST_F(PluginConversionRuleUnitTest, ParserProgramPtrInputParameter) { std::string targetCAPI {R"( - extern "C" es2panda_AstNode *CreateETSScript([[maybe_unused]] es2panda_Context *context, - [[maybe_unused]] es2panda_AstNode **statementList, size_t statementListLen) + explicit ETSModule(ArenaAllocator *allocator, ArenaVector &&statementList, Identifier *ident, + ModuleFlag flag, parser::Program *program) */ + extern "C" es2panda_AstNode *CreateETSModule([[maybe_unused]] es2panda_Context *context, + [[maybe_unused]] es2panda_AstNode **statementList, + size_t statementListLen, [[maybe_unused]] es2panda_AstNode *ident, + [[maybe_unused]] Es2pandaModuleFlag flag) { auto *allocatorE2p = reinterpret_cast(context)->allocator; - ArenaVector statementListArenaVector {reinterpret_cast(context) - ->allocator->Adapter()}; - for (size_t i = 0; i < statementListLen; ++i) { - auto *statementListElement1 = statementList[i]; - auto *statementListElement1E2p = reinterpret_cast(statementListElement1); - - statementListArenaVector.push_back(statementListElement1E2p); - } + ArenaVector statementListArenaVector { + reinterpret_cast(context)->allocator->Adapter()}; + for (size_t i = 0; i < statementListLen; ++i) { + auto *statementListElement1 = statementList[i]; + auto *statementListElement1E2p = reinterpret_cast(statementListElement1); + + statementListArenaVector.push_back(statementListElement1E2p); + } + auto *identE2p = reinterpret_cast(ident); + auto flagE2p = E2pToIrModuleFlag(flag); auto *programE2p = reinterpret_cast(context)->parserProgram; auto *ctx = reinterpret_cast(context); auto *ctxAllocator = ctx->allocator; - return reinterpret_cast(ctxAllocator->New(allocatorE2p, - std::move(statementListArenaVector), programE2p)); + return reinterpret_cast(ctxAllocator->New( + allocatorE2p, std::move(statementListArenaVector), identE2p, flagE2p, programE2p)); })"}; std::string targetAPIWithNoSpace = RemoveWhitespace(targetCAPI); diff --git a/ets2panda/test/unit/public/ast_verifier_private_access_negative_test.cpp b/ets2panda/test/unit/public/ast_verifier_private_access_negative_test.cpp index dbbbe9783d..476a44a58d 100644 --- a/ets2panda/test/unit/public/ast_verifier_private_access_negative_test.cpp +++ b/ets2panda/test/unit/public/ast_verifier_private_access_negative_test.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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 @@ -17,7 +17,7 @@ #include "checker/ETSchecker.h" using ark::es2panda::compiler::ast_verifier::ModifierAccessValid; -using ark::es2panda::ir::ETSScript; +using ark::es2panda::ir::ETSModule; TEST_F(ASTVerifierTest, PrivateAccessTestNegative1) { @@ -33,9 +33,9 @@ TEST_F(ASTVerifierTest, PrivateAccessTestNegative1) impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); + auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); - ast->AsETSScript() + ast->AsETSModule() ->Statements()[1] ->AsClassDeclaration() ->Definition() @@ -65,9 +65,9 @@ TEST_F(ASTVerifierTest, PrivateAccessTestNegative2) impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); + auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); - ast->AsETSScript() + ast->AsETSModule() ->Statements()[1] ->AsClassDeclaration() ->Definition() @@ -98,9 +98,9 @@ TEST_F(ASTVerifierTest, PrivateAccessTestNegative3) impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); + auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); - ast->AsETSScript() + ast->AsETSModule() ->Statements()[1] ->AsClassDeclaration() ->Definition() @@ -131,9 +131,9 @@ TEST_F(ASTVerifierTest, PrivateAccessTestNegative4) impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); + auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); - ast->AsETSScript() + ast->AsETSModule() ->Statements()[1] ->AsClassDeclaration() ->Definition() @@ -165,9 +165,9 @@ TEST_F(ASTVerifierTest, PrivateAccessTestNegative5) es2panda_Context *ctx = CreateContextAndProceedToState(impl_, cfg_, text, "dummy.sts", ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto ast = GetAstFromContext(impl_, ctx); + auto ast = GetAstFromContext(impl_, ctx); - ast->AsETSScript() + ast->AsETSModule() ->Statements()[0] ->AsClassDeclaration() ->Definition() @@ -211,9 +211,9 @@ TEST_F(ASTVerifierTest, PrivateAccessTestNegative6) es2panda_Context *ctx = CreateContextAndProceedToState(impl_, cfg_, text, "dummy.sts", ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto ast = GetAstFromContext(impl_, ctx); + auto ast = GetAstFromContext(impl_, ctx); - ast->AsETSScript() + ast->AsETSModule() ->Statements()[0] ->AsClassDeclaration() ->Definition() @@ -257,9 +257,9 @@ TEST_F(ASTVerifierTest, PrivateAccessTestNegative7) es2panda_Context *ctx = CreateContextAndProceedToState(impl_, cfg_, text, "dummy.sts", ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto ast = GetAstFromContext(impl_, ctx); + auto ast = GetAstFromContext(impl_, ctx); - ast->AsETSScript() + ast->AsETSModule() ->Statements()[0] ->AsClassDeclaration() ->Definition() diff --git a/ets2panda/test/unit/public/ast_verifier_protected_access_correct_test.cpp b/ets2panda/test/unit/public/ast_verifier_protected_access_correct_test.cpp index 2a6a044c59..c5bf19fdce 100644 --- a/ets2panda/test/unit/public/ast_verifier_protected_access_correct_test.cpp +++ b/ets2panda/test/unit/public/ast_verifier_protected_access_correct_test.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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 @@ -17,7 +17,7 @@ #include "checker/ETSchecker.h" using ark::es2panda::compiler::ast_verifier::ModifierAccessValid; -using ark::es2panda::ir::ETSScript; +using ark::es2panda::ir::ETSModule; TEST_F(ASTVerifierTest, ProtectedAccessTestCorrect) { @@ -32,9 +32,9 @@ TEST_F(ASTVerifierTest, ProtectedAccessTestCorrect) es2panda_Context *ctx = CreateContextAndProceedToState(impl_, cfg_, text, "dummy.sts", ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto ast = GetAstFromContext(impl_, ctx); + auto ast = GetAstFromContext(impl_, ctx); - ast->AsETSScript() + ast->AsETSModule() ->Statements()[1] ->AsClassDeclaration() ->Definition() diff --git a/ets2panda/test/unit/public/ast_verifier_protected_access_negative_test.cpp b/ets2panda/test/unit/public/ast_verifier_protected_access_negative_test.cpp index d85522c66d..df03056b88 100644 --- a/ets2panda/test/unit/public/ast_verifier_protected_access_negative_test.cpp +++ b/ets2panda/test/unit/public/ast_verifier_protected_access_negative_test.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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 @@ -17,7 +17,7 @@ #include "checker/ETSchecker.h" using ark::es2panda::compiler::ast_verifier::ModifierAccessValid; -using ark::es2panda::ir::ETSScript; +using ark::es2panda::ir::ETSModule; TEST_F(ASTVerifierTest, ProtectedAccessTestNegative1) { @@ -34,9 +34,9 @@ TEST_F(ASTVerifierTest, ProtectedAccessTestNegative1) impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); + auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); - ast->AsETSScript() + ast->AsETSModule() ->Statements()[1] ->AsClassDeclaration() ->Definition() @@ -67,9 +67,9 @@ TEST_F(ASTVerifierTest, ProtectedAccessTestNegative2) impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); + auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); - ast->AsETSScript() + ast->AsETSModule() ->Statements()[1] ->AsClassDeclaration() ->Definition() @@ -100,9 +100,9 @@ TEST_F(ASTVerifierTest, ProtectedAccessTestNegative3) impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); + auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); - ast->AsETSScript() + ast->AsETSModule() ->Statements()[1] ->AsClassDeclaration() ->Definition() @@ -134,9 +134,9 @@ TEST_F(ASTVerifierTest, ProtectedAccessTestNegative4) es2panda_Context *ctx = CreateContextAndProceedToState(impl_, cfg_, text, "dummy.sts", ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto ast = GetAstFromContext(impl_, ctx); + auto ast = GetAstFromContext(impl_, ctx); - ast->AsETSScript() + ast->AsETSModule() ->Statements()[0] ->AsClassDeclaration() ->Definition() @@ -180,9 +180,9 @@ TEST_F(ASTVerifierTest, ProtectedAccessTestNegative5) es2panda_Context *ctx = CreateContextAndProceedToState(impl_, cfg_, text, "dummy.sts", ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto ast = GetAstFromContext(impl_, ctx); + auto ast = GetAstFromContext(impl_, ctx); - ast->AsETSScript() + ast->AsETSModule() ->Statements()[0] ->AsClassDeclaration() ->Definition() @@ -226,9 +226,9 @@ TEST_F(ASTVerifierTest, ProtectedAccessTestNegative6) es2panda_Context *ctx = CreateContextAndProceedToState(impl_, cfg_, text, "dummy.sts", ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto ast = GetAstFromContext(impl_, ctx); + auto ast = GetAstFromContext(impl_, ctx); - ast->AsETSScript() + ast->AsETSModule() ->Statements()[0] ->AsClassDeclaration() ->Definition() diff --git a/ets2panda/test/unit/public/ast_verifier_short_test.cpp b/ets2panda/test/unit/public/ast_verifier_short_test.cpp index 81ddefd062..d904303209 100644 --- a/ets2panda/test/unit/public/ast_verifier_short_test.cpp +++ b/ets2panda/test/unit/public/ast_verifier_short_test.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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 @@ -222,10 +222,10 @@ TEST_F(ASTVerifierTest, VariableNameIdentifierNameSameNegative) es2panda_Context *ctx = CreateContextAndProceedToState(impl_, cfg_, text, "dummy.sts", ES2PANDA_STATE_CHECKED); - auto ast = GetAstFromContext(impl_, ctx); + auto ast = GetAstFromContext(impl_, ctx); // Note(@kirillbychkov): Change Identifier name in variable lambda2 - ast->AsETSScript() + ast->AsETSModule() ->Statements()[0] ->AsClassDeclaration() ->Definition() @@ -269,7 +269,7 @@ TEST_F(ASTVerifierTest, VariableNameIdentifierNameSame) es2panda_Context *ctx = CreateContextAndProceedToState(impl_, cfg_, text, "dummy.sts", ES2PANDA_STATE_CHECKED); - auto ast = GetAstFromContext(impl_, ctx); + auto ast = GetAstFromContext(impl_, ctx); const auto &messages = verifier_.Verify(ast); ASSERT_EQ(messages.size(), 0); impl_->DestroyContext(ctx); diff --git a/ets2panda/test/utils/asm_test.cpp b/ets2panda/test/utils/asm_test.cpp index bd76476d89..694be1be59 100644 --- a/ets2panda/test/utils/asm_test.cpp +++ b/ets2panda/test/utils/asm_test.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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 @@ -41,6 +41,16 @@ ark::pandasm::Function *AsmTest::GetFunction(std::string_view functionName, return &it->second; } +ark::pandasm::Record *AsmTest::GetRecord(std::string_view recordName, + const std::unique_ptr &program) +{ + auto it = program->recordTable.find(recordName.data()); + if (it == program->recordTable.end()) { + return nullptr; + } + return &it->second; +} + void AsmTest::CompareActualWithExpected(const std::string &expectedValue, ark::pandasm::ScalarValue *scalarValue, const std::string &field) { diff --git a/ets2panda/test/utils/asm_test.h b/ets2panda/test/utils/asm_test.h index ac68c61ead..ef9510c491 100644 --- a/ets2panda/test/utils/asm_test.h +++ b/ets2panda/test/utils/asm_test.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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 @@ -54,7 +54,7 @@ public: ark::pandasm::Function *GetFunction(std::string_view functionName, const std::unique_ptr &program); - + ark::pandasm::Record *GetRecord(std::string_view recordName, const std::unique_ptr &program); void CompareActualWithExpected(const std::string &expectedValue, ark::pandasm::ScalarValue *scalarValue, const std::string &field); diff --git a/ets2panda/varbinder/ETSBinder.cpp b/ets2panda/varbinder/ETSBinder.cpp index 400c29c383..ccc7b50458 100644 --- a/ets2panda/varbinder/ETSBinder.cpp +++ b/ets2panda/varbinder/ETSBinder.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 @@ -42,7 +42,7 @@ #include "ir/ets/etsTypeReference.h" #include "ir/ets/etsFunctionType.h" #include "ir/ets/etsNeverType.h" -#include "ir/ets/etsScript.h" +#include "ir/ets/etsModule.h" #include "ir/ets/etsImportDeclaration.h" #include "ir/ts/tsInterfaceDeclaration.h" #include "ir/ts/tsTypeParameterDeclaration.h" @@ -100,29 +100,59 @@ void ETSBinder::LookupTypeArgumentReferences(ir::ETSTypeReference *typeRef) } } +static bool IsSpecialName(const util::StringView &name) +{ + return name == compiler::Signatures::UNDEFINED || name == compiler::Signatures::NULL_LITERAL || + name == compiler::Signatures::READONLY_TYPE_NAME || name == compiler::Signatures::PARTIAL_TYPE_NAME || + name == compiler::Signatures::REQUIRED_TYPE_NAME; +} + +bool ETSBinder::HandleDynamicVariables(ir::Identifier *ident, Variable *variable, bool allowDynamicNamespaces) +{ + if (IsDynamicModuleVariable(variable)) { + ident->SetVariable(variable); + return true; + } + + if (allowDynamicNamespaces && IsDynamicNamespaceVariable(variable)) { + ident->SetVariable(variable); + return true; + } + return false; +} + +bool ETSBinder::LookupInDebugInfoPlugin(ir::Identifier *ident) +{ + auto *checker = GetContext()->checker->AsETSChecker(); + auto *debugInfoPlugin = checker->GetDebugInfoPlugin(); + if (UNLIKELY(debugInfoPlugin)) { + auto *var = debugInfoPlugin->FindClass(ident); + if (var != nullptr) { + ident->SetVariable(var); + return true; + } + } + // NOTE: search an imported module's name in case of 'import "file" as xxx'. + return false; +} + void ETSBinder::LookupTypeReference(ir::Identifier *ident, bool allowDynamicNamespaces) { const auto &name = ident->Name(); - if (name == compiler::Signatures::UNDEFINED || name == compiler::Signatures::NULL_LITERAL || - name == compiler::Signatures::READONLY_TYPE_NAME || name == compiler::Signatures::PARTIAL_TYPE_NAME || - name == compiler::Signatures::REQUIRED_TYPE_NAME) { + if (IsSpecialName(name)) { return; } auto *iter = GetScope(); while (iter != nullptr) { - auto res = iter->Find(name, ResolveBindingOptions::DECLARATION | ResolveBindingOptions::TYPE_ALIASES); + auto options = ResolveBindingOptions::DECLARATION | ResolveBindingOptions::TYPE_ALIASES | + ResolveBindingOptions::STATIC_DECLARATION; + auto res = iter->Find(name, options); if (res.variable == nullptr) { break; } - if (IsDynamicModuleVariable(res.variable)) { - ident->SetVariable(res.variable); - return; - } - - if (allowDynamicNamespaces && IsDynamicNamespaceVariable(res.variable)) { - ident->SetVariable(res.variable); + if (HandleDynamicVariables(ident, res.variable, allowDynamicNamespaces)) { return; } @@ -145,15 +175,8 @@ void ETSBinder::LookupTypeReference(ir::Identifier *ident, bool allowDynamicName } } - auto *checker = GetContext()->checker->AsETSChecker(); - auto *debugInfoPlugin = checker->GetDebugInfoPlugin(); - if (UNLIKELY(debugInfoPlugin)) { - auto *var = debugInfoPlugin->FindClass(ident); - if (var != nullptr) { - ident->SetVariable(var); - return; - } - // NOTE: search an imported module's name in case of 'import "file" as xxx'. + if (LookupInDebugInfoPlugin(ident)) { + return; } ThrowUnresolvableType(ident->Start(), name); @@ -525,9 +548,12 @@ void ETSBinder::InsertForeignBinding(ir::AstNode *const specifier, const ir::ETS std::string RedeclarationErrorMessageAssembler(const Variable *const var, const Variable *const variable, util::StringView localName) { - auto type = var->Declaration()->Node()->IsClassDefinition() ? "Class '" - : var->Declaration()->IsFunctionDecl() ? "Function '" - : "Variable '"; + bool isNamespace = var->Declaration()->Node()->IsClassDefinition() && + var->Declaration()->Node()->AsClassDefinition()->IsNamespaceTransformed(); + auto type = isNamespace ? "Namespace '" + : var->Declaration()->Node()->IsClassDefinition() ? "Class '" + : var->Declaration()->IsFunctionDecl() ? "Function '" + : "Variable '"; auto str = util::Helpers::AppendAll(type, localName.Utf8(), "'"); str += variable->Declaration()->Type() == var->Declaration()->Type() ? " is already defined." : " is already defined with different type."; @@ -543,7 +569,7 @@ void AddOverloadFlag(ArenaAllocator *allocator, bool isStdLib, varbinder::Variab // Necessary because stdlib and escompat handled as same package, it can be removed after fixing package handling auto const getPackageName = [](Variable *var) { - return var->GetScope()->Node()->GetTopStatement()->AsETSScript()->Program()->ModuleName(); + return var->GetScope()->Node()->GetTopStatement()->AsETSModule()->Program()->ModuleName(); }; if (isStdLib && (getPackageName(importedVar) != getPackageName(variable))) { return; diff --git a/ets2panda/varbinder/ETSBinder.h b/ets2panda/varbinder/ETSBinder.h index 73271b6645..f3cc055b8c 100644 --- a/ets2panda/varbinder/ETSBinder.h +++ b/ets2panda/varbinder/ETSBinder.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 @@ -114,6 +114,8 @@ public: bool BuildInternalName(ir::ScriptFunction *scriptFunc) override; void AddCompilableFunction(ir::ScriptFunction *func) override; + bool HandleDynamicVariables(ir::Identifier *ident, Variable *variable, bool allowDynamicNamespaces); + bool LookupInDebugInfoPlugin(ir::Identifier *ident); void LookupTypeReference(ir::Identifier *ident, bool allowDynamicNamespaces); void LookupTypeArgumentReferences(ir::ETSTypeReference *typeRef); void BuildInterfaceDeclaration(ir::TSInterfaceDeclaration *decl); diff --git a/ets2panda/varbinder/scope.cpp b/ets2panda/varbinder/scope.cpp index 38d3f978e0..df88969974 100644 --- a/ets2panda/varbinder/scope.cpp +++ b/ets2panda/varbinder/scope.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 @@ -179,20 +179,21 @@ Scope::VariableMap::size_type Scope::EraseBinding(const util::StringView &name) ConstScopeFindResult Scope::FindInGlobal(const util::StringView &name, const ResolveBindingOptions options) const { const auto *scopeIter = this; - const auto *scopeParent = this->Parent(); - // One scope below true global is ETSGLOBAL - while (scopeParent != nullptr && !scopeParent->IsGlobalScope()) { - scopeIter = scopeParent; - scopeParent = scopeIter->Parent(); + Variable *resolved = nullptr; + while (scopeIter != nullptr && !scopeIter->IsGlobalScope()) { + bool isModule = scopeIter->Node() != nullptr && scopeIter->Node()->IsClassDefinition() && + scopeIter->Node()->AsClassDefinition()->IsModule(); + if (isModule) { + resolved = scopeIter->FindLocal(name, options); + if (resolved != nullptr) { + break; + } + } + scopeIter = scopeIter->Parent(); } - - auto *resolved = scopeIter->FindLocal(name, options); - if (resolved == nullptr && scopeParent != nullptr) { - // If the variable cannot be found in the scope of the local ETSGLOBAL, than we still need to check the true - // global scope which contains all the imported ETSGLOBALs - resolved = scopeParent->FindLocal(name, options); + if (resolved == nullptr && scopeIter != nullptr && scopeIter->IsGlobalScope()) { + resolved = scopeIter->FindLocal(name, options); } - return {name, scopeIter, 0, 0, resolved}; } @@ -293,9 +294,9 @@ Variable *Scope::AddLocal(ArenaAllocator *allocator, Variable *currentVariable, .first->second; } case DeclType::CLASS: { - auto *var = - bindings_.insert({newDecl->Name(), allocator->New(newDecl, VariableFlags::CLASS)}) - .first->second; + auto isNamespaceTransformed = newDecl->Node()->AsClassDefinition()->IsNamespaceTransformed(); + VariableFlags flag = isNamespaceTransformed ? VariableFlags::NAMESPACE : VariableFlags::CLASS; + auto *var = bindings_.insert({newDecl->Name(), allocator->New(newDecl, flag)}).first->second; newDecl->Node()->AsClassDefinition()->Ident()->SetVariable(var); return var; } @@ -503,8 +504,10 @@ Variable *FunctionScope::AddBinding(ArenaAllocator *allocator, Variable *current break; } case DeclType::CLASS: { + auto isNamespaceTransformed = newDecl->Node()->AsClassDefinition()->IsNamespaceTransformed(); + VariableFlags flag = isNamespaceTransformed ? VariableFlags::NAMESPACE : VariableFlags::CLASS; ident = newDecl->Node()->AsClassDefinition()->Ident(); - var = InsertBindingIfAbsentInScope(allocator, currentVariable, newDecl, VariableFlags::CLASS); + var = InsertBindingIfAbsentInScope(allocator, currentVariable, newDecl, flag); break; } case DeclType::TYPE_ALIAS: { @@ -915,7 +918,11 @@ void ClassScope::SetBindingProps(Decl *newDecl, BindingProps *props, bool isStat break; } case DeclType::CLASS: { - props->SetBindingProps(VariableFlags::CLASS, newDecl->Node()->AsClassDefinition()->Ident(), + VariableFlags flag = VariableFlags::CLASS; + if (newDecl->Node()->AsClassDefinition()->IsNamespaceTransformed()) { + flag = VariableFlags::NAMESPACE; + } + props->SetBindingProps(flag, newDecl->Node()->AsClassDefinition()->Ident(), isStatic ? staticDeclScope_ : instanceDeclScope_); break; } diff --git a/ets2panda/varbinder/variableFlags.h b/ets2panda/varbinder/variableFlags.h index 7a07326c67..86463b08f8 100644 --- a/ets2panda/varbinder/variableFlags.h +++ b/ets2panda/varbinder/variableFlags.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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 @@ -165,6 +165,7 @@ enum class VariableFlags : uint64_t { CAPTURED_MODIFIED = 1ULL << 32ULL, ANNOTATIONDECL = 1ULL << 33ULL, ANNOTATIONUSAGE = 1ULL << 34ULL, + NAMESPACE = 1ULL << 35ULL, HOIST_VAR = HOIST | VAR, CLASS_OR_INTERFACE = CLASS | INTERFACE, -- Gitee