diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index f4fc39afe2cbbbfa87ae49415e1b620b75fec8d2..5fa64dc38bbf15ae7892276152d128f51ee3e75c 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -3049,8 +3049,9 @@ checker::Type *ETSAnalyzer::Check(ir::AnnotationDeclaration *st) const } } - if (st->GetBaseName()->Variable()->Declaration()->Node()->IsAnnotationDeclaration()) { - auto *annoDecl = st->GetBaseName()->Variable()->Declaration()->Node()->AsAnnotationDeclaration(); + auto baseName = st->GetBaseName(); + if (!baseName->IsErrorPlaceHolder()) { + auto *annoDecl = baseName->Variable()->Declaration()->Node()->AsAnnotationDeclaration(); if (annoDecl != st && annoDecl->IsDeclare()) { checker->CheckAmbientAnnotation(st, annoDecl); } @@ -3082,13 +3083,17 @@ checker::Type *ETSAnalyzer::Check(ir::AnnotationUsage *st) const ETSChecker *checker = GetETSChecker(); st->Expr()->Check(checker); - if (st->GetBaseName()->Variable() == nullptr || - !st->GetBaseName()->Variable()->Declaration()->Node()->IsAnnotationDeclaration()) { - checker->LogError(diagnostic::NOT_AN_ANNOTATION, {st->GetBaseName()->Name()}, st->GetBaseName()->Start()); + auto *baseName = st->GetBaseName(); + if (baseName->Variable() == nullptr || !baseName->Variable()->Declaration()->Node()->IsAnnotationDeclaration()) { + if (!baseName->IsErrorPlaceHolder()) { + checker->LogError(diagnostic::NOT_AN_ANNOTATION, {baseName->Name()}, baseName->Start()); + } + + ES2PANDA_ASSERT(checker->IsAnyError()); return ReturnTypeForStatement(st); } - auto *annoDecl = st->GetBaseName()->Variable()->Declaration()->Node()->AsAnnotationDeclaration(); + auto *annoDecl = baseName->Variable()->Declaration()->Node()->AsAnnotationDeclaration(); annoDecl->Check(checker); ArenaUnorderedMap fieldMap {checker->ProgramAllocator()->Adapter()}; @@ -3108,7 +3113,7 @@ checker::Type *ETSAnalyzer::Check(ir::AnnotationUsage *st) const checker->CheckSinglePropertyAnnotation(st, annoDecl); fieldMap.clear(); } else { - checker->CheckMultiplePropertiesAnnotation(st, st->GetBaseName()->Name(), fieldMap); + checker->CheckMultiplePropertiesAnnotation(st, baseName->Name(), fieldMap); } ProcessRequiredFields(fieldMap, st, checker); diff --git a/ets2panda/ir/statements/annotationDeclaration.cpp b/ets2panda/ir/statements/annotationDeclaration.cpp index 574088a82d19d93f217b40ccfde029f6b603427f..7b88482674bbafcf6f06c8758b981d2db1f84318 100644 --- a/ets2panda/ir/statements/annotationDeclaration.cpp +++ b/ets2panda/ir/statements/annotationDeclaration.cpp @@ -153,14 +153,7 @@ Identifier *AnnotationDeclaration::GetBaseName() const if (Expr()->IsIdentifier()) { return GetHistoryNodeAs()->expr_->AsIdentifier(); } - auto *part = Expr()->AsETSTypeReference()->Part(); - if (part->Name()->IsIdentifier()) { - return part->Name()->AsIdentifier(); - } - if (part->Name()->IsTSQualifiedName()) { - return part->Name()->AsTSQualifiedName()->Right(); - } - return nullptr; + return expr_->AsETSTypeReference()->Part()->GetIdent(); } AnnotationDeclaration *AnnotationDeclaration::Construct(ArenaAllocator *allocator) { diff --git a/ets2panda/ir/statements/annotationUsage.cpp b/ets2panda/ir/statements/annotationUsage.cpp index 1183e94543c49daac4bee8fd86eabf07723fc836..2d22aed190e78bad6be6a27631fd2357ed62daaf 100644 --- a/ets2panda/ir/statements/annotationUsage.cpp +++ b/ets2panda/ir/statements/annotationUsage.cpp @@ -120,7 +120,6 @@ Identifier *AnnotationUsage::GetBaseName() const if (expr_->IsIdentifier()) { return expr_->AsIdentifier(); } - auto *part = expr_->AsETSTypeReference()->Part(); - return part->Name()->AsTSQualifiedName()->Right(); + return expr_->AsETSTypeReference()->Part()->GetIdent(); } } // namespace ark::es2panda::ir diff --git a/ets2panda/parser/ETSparserAnnotations.cpp b/ets2panda/parser/ETSparserAnnotations.cpp index f2aa9bbd5df3ff64ee969e236c94d867bcb333cd..3a10ab70728f5ce09cec93ec17f9e9a893a66ae3 100644 --- a/ets2panda/parser/ETSparserAnnotations.cpp +++ b/ets2panda/parser/ETSparserAnnotations.cpp @@ -56,26 +56,32 @@ ir::Expression *ETSParser::ParseAnnotationName() } }; auto save = Lexer()->Save(); + ir::Identifier *ident = nullptr; Lexer()->NextToken(); if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) { Lexer()->Rewind(save); expr = ExpectIdentifier(); ES2PANDA_ASSERT(expr != nullptr); - setAnnotation(expr->AsIdentifier()); - return expr; - } - Lexer()->Rewind(save); - if (Lexer()->Lookahead() == '.') { - auto opt = TypeAnnotationParsingOptions::NO_OPTS; - expr = ParseTypeReference(&opt); - ES2PANDA_ASSERT(expr != nullptr); - setAnnotation(expr->AsETSTypeReference()->Part()->GetIdent()); + ident = expr->AsIdentifier(); } else { - expr = ExpectIdentifier(); - ES2PANDA_ASSERT(expr != nullptr); - setAnnotation(expr->AsIdentifier()); + Lexer()->Rewind(save); + if (Lexer()->Lookahead() == '.') { + auto opt = TypeAnnotationParsingOptions::NO_OPTS; + expr = ParseTypeReference(&opt); + ES2PANDA_ASSERT(expr != nullptr); + ident = expr->AsETSTypeReference()->Part()->GetIdent(); + } else { + expr = ExpectIdentifier(); + ES2PANDA_ASSERT(expr != nullptr); + ident = expr->AsIdentifier(); + } + } + + if (ident->IsBrokenExpression()) { + LogError(diagnostic::INVALID_ANNOTATION_NAME, {}, expr->Start()); } + setAnnotation(ident); return expr; } @@ -367,17 +373,14 @@ void ETSParser::ApplyAnnotationsToSpecificNodeType(ir::AstNode *node, ArenaVecto } } -static lexer::SourcePosition GetExpressionEndLoc(ir::Expression *expr) +static lexer::SourcePosition GetAnnotationExpressionEndLoc(ir::Expression *expr) { ES2PANDA_ASSERT(expr != nullptr); if (expr->IsIdentifier()) { return expr->AsIdentifier()->End(); } - auto *part = expr->AsETSTypeReference()->Part(); - if (part->Name()->IsBrokenExpression()) { - return part->Name()->End(); - } - return part->Name()->AsTSQualifiedName()->Right()->End(); + + return expr->AsETSTypeReference()->Part()->GetIdent()->End(); } ir::AnnotationUsage *ETSParser::ParseAnnotationUsage() @@ -389,7 +392,7 @@ ir::AnnotationUsage *ETSParser::ParseAnnotationUsage() ArenaVector properties(Allocator()->Adapter()); if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS && - !IsArrowFunctionExpressionStart() && IsAnnotationUsageStart(GetExpressionEndLoc(expr))) { + !IsArrowFunctionExpressionStart() && IsAnnotationUsageStart(GetAnnotationExpressionEndLoc(expr))) { Lexer()->NextToken(); // eat '(' if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { properties = ParseAnnotationProperties(flags); @@ -425,7 +428,7 @@ ir::AnnotationUsage *ETSParser::ParseAnnotationUsage() auto *annotationUsage = AllocNode(expr, std::move(properties)); ES2PANDA_ASSERT(annotationUsage != nullptr); annotationUsage->AddModifier(flags); - annotationUsage->SetRange({startLoc, GetExpressionEndLoc(expr)}); + annotationUsage->SetRange({startLoc, GetAnnotationExpressionEndLoc(expr)}); return annotationUsage; } diff --git a/ets2panda/test/ast/compiler/ets/annotation_decl_dot_empty.ets b/ets2panda/test/ast/compiler/ets/annotation_decl_dot_empty.ets new file mode 100644 index 0000000000000000000000000000000000000000..c077a76fd0de0cd1798da4d69b10e1ffa6f67022 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/annotation_decl_dot_empty.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. + */ + +@interface Message. +{ +} + +/* @@? 16:12 Error SyntaxError: Invalid annotation name. */ +/* @@? 17:1 Error SyntaxError: Identifier expected. */ diff --git a/ets2panda/test/ast/compiler/ets/annotation_dot_with_empty.ets b/ets2panda/test/ast/compiler/ets/annotation_dot_with_empty.ets new file mode 100644 index 0000000000000000000000000000000000000000..195205770f44ca73bc0d7620e1f006014838e9d9 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/annotation_dot_with_empty.ets @@ -0,0 +1,23 @@ +/* + * 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 MyTest { + @Consume. + private property1; +} + +/* @@? 17:6 Error SyntaxError: Invalid annotation name. */ +/* @@? 18:5 Error SyntaxError: Identifier expected. */ +/* @@? 18:22 Error SyntaxError: Field type annotation expected. */ diff --git a/ets2panda/test/ast/compiler/ets/binary_operator_neg.ets b/ets2panda/test/ast/compiler/ets/binary_operator_neg.ets index 8b71c849f8ad5d88e633c11d47ad0de13bdd8ae8..4bee69637bc0a64837cb1169e070ffe61136a56f 100644 --- a/ets2panda/test/ast/compiler/ets/binary_operator_neg.ets +++ b/ets2panda/test/ast/compiler/ets/binary_operator_neg.ets @@ -15,7 +15,8 @@ /* @@ 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 +/* @@@ label1 Error SyntaxError: Unexpected token '@@'. */ +/* @@? 23:1 Error SyntaxError: Identifier expected, got 'end of stream'. */ +/* @@? 23:1 Error SyntaxError: Invalid annotation name. */ +/* @@? 23:1 Error SyntaxError: Unexpected token 'end of stream'. */ +/* @@? 23:1 Error SyntaxError: Annotations are not allowed on this type of declaration. */ diff --git a/ets2panda/test/ast/parser/ets/interface_parser_error_1.ets b/ets2panda/test/ast/parser/ets/interface_parser_error_1.ets index 05540be90decdb67f05112134428cda9dd1abc45..589da49e760f1e3394d3d72d49cc066c66bae60c 100644 --- a/ets2panda/test/ast/parser/ets/interface_parser_error_1.ets +++ b/ets2panda/test/ast/parser/ets/interface_parser_error_1.ets @@ -55,14 +55,15 @@ function mdin() { let a = new A(); /* @@? 24:20 Error TypeError: Interface name 'I' used in the wrong context */ /* @@? 24:22 Error SyntaxError: Unexpected token '{'. */ /* @@? 25:4 Error TypeError: Unresolved reference reanstructor */ -/* @@? 26:19 Error SyntaxError: Unexpected token '�ls'. */ /* @@? 26:19 Error SyntaxError: Unexpected token, expected an identifier. */ +/* @@? 26:19 Error SyntaxError: Unexpected token '�ls'. */ /* @@? 27:5 Error SyntaxError: Unexpected token 'A'. */ /* @@? 27:7 Error SyntaxError: Unexpected token '{'. */ /* @@? 28:5 Error SyntaxError: Hard keyword 'constructor' cannot be used as identifier */ /* @@? 28:5 Error SyntaxError: Identifier expected, got 'constructor'. */ +/* @@? 28:16 Error SyntaxError: Invalid annotation name. */ /* @@? 28:19 Error SyntaxError: Annotations are not allowed on this type of declaration. */ /* @@? 29:18 Error SyntaxError: Unexpected token, expected an identifier. */ /* @@? 31:2 Error SyntaxError: Unexpected token '*'. */ /* @@? 32:1 Error SyntaxError: Nested functions are not allowed. */ -/* @@? 69:1 Error SyntaxError: Expected '}', got 'end of stream'. */ +/* @@? 70:1 Error SyntaxError: Expected '}', got 'end of stream'. */ diff --git a/ets2panda/util/diagnostic/syntax.yaml b/ets2panda/util/diagnostic/syntax.yaml index a2ff88fa46a357daa0d686c15cc28defc83aa23d..6e77a84dfedf7564e99c2a38da49f4d57110205d 100644 --- a/ets2panda/util/diagnostic/syntax.yaml +++ b/ets2panda/util/diagnostic/syntax.yaml @@ -505,6 +505,10 @@ syntax: id: 159 message: "Invalid accessor." +- name: INVALID_ANNOTATION_NAME + id: 329 + message: "Invalid annotation name." + - name: INVALID_ARGUMENT_ETSNOLINT id: 278 message: "Invalid argument for ETSNOLINT!"