diff --git a/ets2panda/compiler/lowering/ets/constantExpressionLowering.cpp b/ets2panda/compiler/lowering/ets/constantExpressionLowering.cpp index 57b3ae2698198bf3160c4d3369bf256939d3aa4e..a33932a5ba9b315ae98daa24330c2fe50d813d18 100644 --- a/ets2panda/compiler/lowering/ets/constantExpressionLowering.cpp +++ b/ets2panda/compiler/lowering/ets/constantExpressionLowering.cpp @@ -312,6 +312,9 @@ static ir::AstNode *CastNumberOrCharLiteralFrom(const ir::Literal *lit, ir::Prim public_lib::Context *context) { switch (type) { + case ir::PrimitiveType::BOOLEAN: + // Note: we do nothing for `class A {b5 : boolean = 7;}` here, type error will be thrown in checker. + return const_cast(lit); case ir::PrimitiveType::CHAR: return CastNumberOrCharLiteralFromTo(lit, context); case ir::PrimitiveType::BYTE: diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp b/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp index 1aaced464c532f04aa6bacb6cf8da99fa1347f62..2f41123fae683588e1868c13f9983712857d3e77 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp @@ -184,18 +184,18 @@ ArenaVector GlobalClassHandler::TransformNamespaces(ArenaVector return classDecls; } -void GlobalClassHandler::TransformBrokenNamespace() +void GlobalClassHandler::TransformBrokenNamespace(ir::AstNode *node) { - globalProgram_->Ast()->TransformChildrenRecursively( + node->TransformChildrenRecursively( // clang-format off // CC-OFFNXT(G.FMT.14-CPP) project code style - [this](ir::AstNode *node) -> ir::AstNode* { - if (node->IsETSModule() && node->AsETSModule()->IsNamespace()) { - auto res = TransformNamespace(node->AsETSModule()); - res->SetParent(node->Parent()); + [this](ir::AstNode *child) -> ir::AstNode* { + if (child->IsETSModule() && child->AsETSModule()->IsNamespace()) { + auto res = TransformNamespace(child->AsETSModule()); + res->SetParent(child->Parent()); return res; } - return node; + return child; }, // clang-format on "TransformBrokenNamespace"); @@ -321,7 +321,7 @@ void GlobalClassHandler::SetupGlobalClass(const ArenaVector & globalClass->SetGlobalInitialized(); CollectProgramGlobalClasses(namespaces); - TransformBrokenNamespace(); + TransformBrokenNamespace(globalProgram_->Ast()); auto initializerBlockStmts = FormInitStaticBlockMethodStatements(moduleDependencies, std::move(initializerBlock)); CollectExportedClasses(globalClass, globalProgram_->Ast()->Statements()); @@ -434,6 +434,7 @@ ArenaVector GlobalClassHandler::FormInitMethodStatements(const statements.insert(statements.end(), ps.begin(), ps.end()); } for (auto st : statements) { + TransformBrokenNamespace(st); st->SetParent(nullptr); } return statements; diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.h b/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.h index 0a861be7a743c15560cf63f0131c93d5bca0c8bb..2b9027158a8c0fdd542f8e321cf6fce8f33e4dfb 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.h +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.h @@ -82,7 +82,7 @@ private: ArenaVector> FormInitStaticBlockMethodStatements( const ModuleDependencies *moduleDependencies, ArenaVector &&initStatements); - void TransformBrokenNamespace(); + void TransformBrokenNamespace(ir::AstNode *node); ArenaVector FormInitMethodStatements(const ModuleDependencies *moduleDependencies, ArenaVector &&initStatements); diff --git a/ets2panda/parser/ETSFormattedParser.cpp b/ets2panda/parser/ETSFormattedParser.cpp index d0b01fdad556ca202f89738c1de968e4313372a7..f5bb28b326c8842ce9440128323fe9f1ce3f4ad6 100644 --- a/ets2panda/parser/ETSFormattedParser.cpp +++ b/ets2panda/parser/ETSFormattedParser.cpp @@ -71,7 +71,7 @@ ir::Expression *ETSParser::ParseExpressionFormatPlaceholder() LogUnexpectedToken(lexer::TokenType::PUNCTUATOR_FORMAT); const auto &rangeToken = Lexer()->GetToken().Loc(); Lexer()->NextToken(); - return AllocBrokenType(rangeToken); + return AllocBrokenExpression(rangeToken); } ParserImpl::NodeFormatType nodeFormat = GetFormatPlaceholderType(); diff --git a/ets2panda/parser/ETSparser.h b/ets2panda/parser/ETSparser.h index 94f513f1db57af6433b6bc822f4c66d0b8410d6b..aa60762d9a5accbc99b22d772d7a164c79ccd5bd 100644 --- a/ets2panda/parser/ETSparser.h +++ b/ets2panda/parser/ETSparser.h @@ -396,7 +396,7 @@ private: ir::ModifierFlags flags = ir::ModifierFlags::NONE) override; bool CheckInNamespaceContextIsExported(); ir::ETSModule *ParseNamespaceStatement(ir::ModifierFlags memberModifiers); - ir::ETSModule *ParseNamespace(ir::ModifierFlags flags); + ir::Statement *ParseNamespace(ir::ModifierFlags flags) override; ir::ETSModule *ParseNamespaceImp(ir::ModifierFlags flags); using NamespaceBody = std::tuple, lexer::SourceRange>; NamespaceBody ParseNamespaceBody(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags); diff --git a/ets2panda/parser/ETSparserNamespaces.cpp b/ets2panda/parser/ETSparserNamespaces.cpp index 50240599974741629a8b0ec7b6ceb6b993125256..72c121d5fcc513418234cb33dcc2e181e924627f 100644 --- a/ets2panda/parser/ETSparserNamespaces.cpp +++ b/ets2panda/parser/ETSparserNamespaces.cpp @@ -41,7 +41,7 @@ ir::ETSModule *ETSParser::ParseNamespaceStatement(ir::ModifierFlags memberModifi GetContext().Status() |= ParserStatus::IN_NAMESPACE; IncrementNamespaceNestedRank(); - ir::ETSModule *result = ParseNamespace(modifiers); + auto *result = ParseNamespace(modifiers); DecrementNamespaceNestedRank(); if (GetNamespaceNestedRank() == 0) { @@ -50,10 +50,10 @@ ir::ETSModule *ETSParser::ParseNamespaceStatement(ir::ModifierFlags memberModifi if ((memberModifiers & ir::ModifierFlags::DECLARE) != 0) { GetContext().Status() &= ~ParserStatus::IN_AMBIENT_CONTEXT; } - return result; + return result->AsETSModule(); } -ir::ETSModule *ETSParser::ParseNamespace(ir::ModifierFlags flags) +ir::Statement *ETSParser::ParseNamespace(ir::ModifierFlags flags) { if ((GetContext().Status() & ParserStatus::IN_NAMESPACE) == 0) { LogError(diagnostic::NAMESPACE_ONLY_TOP_OR_IN_NAMESPACE); diff --git a/ets2panda/parser/TypedParser.cpp b/ets2panda/parser/TypedParser.cpp index 02dd76cabd71dcb5ba8e2fb610a58f19923b1729..c47a3e4c7a760ae2cc816b4c5e91dcbbca43a64a 100644 --- a/ets2panda/parser/TypedParser.cpp +++ b/ets2panda/parser/TypedParser.cpp @@ -170,7 +170,7 @@ ir::Statement *TypedParser::ParsePotentialExpressionStatement(StatementParsingFl } case lexer::TokenType::KEYW_NAMESPACE: { if (((GetContext().Status() & ParserStatus::IN_AMBIENT_CONTEXT) != 0U) || IsNamespaceDecl()) { - return ParseModuleDeclaration(); + return ParseNamespace(ir::ModifierFlags::NONE); } [[fallthrough]]; } @@ -225,6 +225,11 @@ ir::Statement *TypedParser::ParseModuleDeclaration([[maybe_unused]] StatementPar return ParseModuleOrNamespaceDeclaration(startLoc); } +ir::Statement *TypedParser::ParseNamespace([[maybe_unused]] ir::ModifierFlags flags) +{ + return ParseModuleDeclaration(); +} + ir::ArrowFunctionExpression *TypedParser::ParseGenericArrowFunction(bool isThrowError) { ArrowFunctionContext arrowFunctionContext(this, false); diff --git a/ets2panda/parser/TypedParser.h b/ets2panda/parser/TypedParser.h index 226f8052e60091819685c1e28bacbb8ec0b2e4d0..ec50263d42e420e7fa022d4de04cda7b54178c35 100644 --- a/ets2panda/parser/TypedParser.h +++ b/ets2panda/parser/TypedParser.h @@ -87,6 +87,7 @@ protected: // NOLINTNEXTLINE(google-default-arguments) ir::Statement *ParseModuleDeclaration(StatementParsingFlags flags = StatementParsingFlags::NONE) override; + virtual ir::Statement *ParseNamespace(ir::ModifierFlags flags); virtual void CheckIfTypeParameterNameIsReserved() {}; virtual ArenaVector ParseInterfaceExtendsClause(); virtual ir::Statement *ParseDeclareAndDecorators(StatementParsingFlags flags); diff --git a/ets2panda/test/ast/compiler/ets/binary_operator_neg.ets b/ets2panda/test/ast/compiler/ets/binary_operator_neg.ets new file mode 100644 index 0000000000000000000000000000000000000000..8b71c849f8ad5d88e633c11d47ad0de13bdd8ae8 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/binary_operator_neg.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* @@ label1 */@@/@ + +/* @@@ label1 Error SyntaxError: Unexpected token '@@'. */ +/* @@? 21:93 Error SyntaxError: Identifier expected, got 'end of stream'. */ +/* @@? 21:93 Error SyntaxError: Unexpected token 'end of stream'. */ +/* @@? 21:93 Error SyntaxError: Annotations are not allowed on this type of declaration. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/classproperty_init_neg.ets b/ets2panda/test/ast/compiler/ets/classproperty_init_neg.ets new file mode 100644 index 0000000000000000000000000000000000000000..4f419d33d4438b4b395457fc8365a9d31fd174ef --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/classproperty_init_neg.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class A {b5 : boolean = /* @@ label1 */7;} + +/* @@@ label1 Error TypeError: Type 'Int' cannot be assigned to type 'Boolean' */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/invalid_namespace_neg.ets b/ets2panda/test/ast/compiler/ets/invalid_namespace_neg.ets new file mode 100644 index 0000000000000000000000000000000000000000..2f3707f2acf87959d1beed916ef47f23830e600c --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/invalid_namespace_neg.ets @@ -0,0 +1,27 @@ +/* + * 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. + */ + +namespace C{ + { + let y: number = + /* @@ label1 */} + + namespace C { + let xsx = 1 + } +} + +/* @@@ label1 Error SyntaxError: Unexpected token '}'. */ +/* @@? 28:1 Error SyntaxError: Unexpected token. */ diff --git a/ets2panda/test/ast/compiler/ets/invalid_namespace_neg2.ets b/ets2panda/test/ast/compiler/ets/invalid_namespace_neg2.ets new file mode 100644 index 0000000000000000000000000000000000000000..c7941e4248b1d7fc9f997fb803fba3db4fd1d678 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/invalid_namespace_neg2.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + /* @@ label1 */namespace C { + let my:number = 1 + } +} + +/* @@@ label1 Error SyntaxError: Namespace is allowed only at the top level or inside a namespace. */