diff --git a/ets2panda/parser/ETSparserAnnotations.cpp b/ets2panda/parser/ETSparserAnnotations.cpp index 1194431c6943fda737dfb374414c7a1b38799bd9..218b519d199fa6a4d8a9327246ff00aacc7cb6f8 100644 --- a/ets2panda/parser/ETSparserAnnotations.cpp +++ b/ets2panda/parser/ETSparserAnnotations.cpp @@ -407,13 +407,21 @@ ir::AnnotationUsage *ETSParser::ParseAnnotationUsage() {singleParamName->Start(), initializer != nullptr ? initializer->End() : singleParamName->End()}); properties.push_back(singleParam); } + + auto *annotationUsage = AllocNode(expr, std::move(properties)); + annotationUsage->AddModifier(flags); + annotationUsage->SetRange({startLoc, Lexer()->GetToken().End()}); + ExpectToken(lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS, true); // eat ')' + + return annotationUsage; } auto *annotationUsage = AllocNode(expr, std::move(properties)); ES2PANDA_ASSERT(annotationUsage != nullptr); annotationUsage->AddModifier(flags); - annotationUsage->SetRange({startLoc, Lexer()->GetToken().End()}); + annotationUsage->SetRange({startLoc, GetExpressionEndLoc(expr)}); + return annotationUsage; } diff --git a/ets2panda/parser/ETSparserClasses.cpp b/ets2panda/parser/ETSparserClasses.cpp index 57e844e8c20a422931efce38a01a26acac9fd680..533cc50310edfa1508a6673ed2c6ea67859d276c 100644 --- a/ets2panda/parser/ETSparserClasses.cpp +++ b/ets2panda/parser/ETSparserClasses.cpp @@ -792,6 +792,7 @@ ir::MethodDefinition *ETSParser::ParseClassGetterSetterMethod(const ArenaVector< ClassElementDescriptor desc(Allocator()); desc.methodKind = Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_GET ? ir::MethodDefinitionKind::GET : ir::MethodDefinitionKind::SET; + desc.propStart = Lexer()->GetToken().Start(); Lexer()->NextToken(); // eat get/set auto *methodName = ExpectIdentifier(); ES2PANDA_ASSERT(methodName != nullptr); @@ -803,7 +804,6 @@ ir::MethodDefinition *ETSParser::ParseClassGetterSetterMethod(const ArenaVector< desc.newStatus = ParserStatus::ALLOW_SUPER; desc.hasSuperClass = (modifiers & ir::ClassDefinitionModifiers::HAS_SUPER) != 0U; - desc.propStart = Lexer()->GetToken().Start(); desc.modifiers = memberModifiers; lexer::SourcePosition propEnd = methodName->End(); diff --git a/ets2panda/test/compiler/ets/generic_class_getter_setter-expected.txt b/ets2panda/test/compiler/ets/generic_class_getter_setter-expected.txt index fb6cf3a2db824837cc46cf3c598825bef0b63297..cbdc373de73b2eb6a09364160dc14bbe8a6240e8 100644 --- a/ets2panda/test/compiler/ets/generic_class_getter_setter-expected.txt +++ b/ets2panda/test/compiler/ets/generic_class_getter_setter-expected.txt @@ -420,7 +420,7 @@ "loc": { "start": { "line": 18, - "column": 13, + "column": 5, "program": "generic_class_getter_setter.ets" }, "end": { @@ -435,7 +435,7 @@ "loc": { "start": { "line": 17, - "column": 13, + "column": 5, "program": "generic_class_getter_setter.ets" }, "end": { diff --git a/ets2panda/test/parser/ets/getterOverride-expected.txt b/ets2panda/test/parser/ets/getterOverride-expected.txt index e223479634015a073306b06ad469b143ac9ffac0..7173f758c6400792c092d476e7762f2cfbc81e8b 100644 --- a/ets2panda/test/parser/ets/getterOverride-expected.txt +++ b/ets2panda/test/parser/ets/getterOverride-expected.txt @@ -449,7 +449,7 @@ "loc": { "start": { "line": 22, - "column": 24, + "column": 14, "program": "getterOverride.ets" }, "end": { diff --git a/ets2panda/test/parser/ets/getter_setter_access_modifiers-expected.txt b/ets2panda/test/parser/ets/getter_setter_access_modifiers-expected.txt index 25155cb55341d4b606b596af3a75e6c12be927d6..a66d8980037d159a0be775d4a7086e4f128a8fea 100644 --- a/ets2panda/test/parser/ets/getter_setter_access_modifiers-expected.txt +++ b/ets2panda/test/parser/ets/getter_setter_access_modifiers-expected.txt @@ -353,7 +353,7 @@ "loc": { "start": { "line": 21, - "column": 21, + "column": 14, "program": "getter_setter_access_modifiers.ets" }, "end": { @@ -368,7 +368,7 @@ "loc": { "start": { "line": 20, - "column": 21, + "column": 14, "program": "getter_setter_access_modifiers.ets" }, "end": { @@ -597,7 +597,7 @@ "loc": { "start": { "line": 23, - "column": 23, + "column": 14, "program": "getter_setter_access_modifiers.ets" }, "end": { @@ -612,7 +612,7 @@ "loc": { "start": { "line": 22, - "column": 23, + "column": 14, "program": "getter_setter_access_modifiers.ets" }, "end": { @@ -1347,7 +1347,7 @@ "loc": { "start": { "line": 35, - "column": 21, + "column": 14, "program": "getter_setter_access_modifiers.ets" }, "end": { @@ -1362,7 +1362,7 @@ "loc": { "start": { "line": 31, - "column": 21, + "column": 14, "program": "getter_setter_access_modifiers.ets" }, "end": { @@ -1786,7 +1786,7 @@ "loc": { "start": { "line": 43, - "column": 23, + "column": 14, "program": "getter_setter_access_modifiers.ets" }, "end": { @@ -1801,7 +1801,7 @@ "loc": { "start": { "line": 39, - "column": 23, + "column": 14, "program": "getter_setter_access_modifiers.ets" }, "end": { diff --git a/ets2panda/test/parser/ets/optional_field_interface-expected.txt b/ets2panda/test/parser/ets/optional_field_interface-expected.txt index d96c964004a36bee90c4635d80e52da07db476e9..544d6d8bb942e96a47fd1a706f6e9f2d21e60728 100644 --- a/ets2panda/test/parser/ets/optional_field_interface-expected.txt +++ b/ets2panda/test/parser/ets/optional_field_interface-expected.txt @@ -1170,7 +1170,7 @@ "loc": { "start": { "line": 29, - "column": 13, + "column": 4, "program": "optional_field_interface.ets" }, "end": { @@ -1185,7 +1185,7 @@ "loc": { "start": { "line": 25, - "column": 13, + "column": 4, "program": "optional_field_interface.ets" }, "end": { diff --git a/ets2panda/test/parser/ets/optional_field_interfaceUnion-expected.txt b/ets2panda/test/parser/ets/optional_field_interfaceUnion-expected.txt index 7b334ffa2e7cee2f95fa638135b16a1f26f04275..a9bed28059f4083608fa68fb00e429962da5e708 100644 --- a/ets2panda/test/parser/ets/optional_field_interfaceUnion-expected.txt +++ b/ets2panda/test/parser/ets/optional_field_interfaceUnion-expected.txt @@ -1533,7 +1533,7 @@ "loc": { "start": { "line": 29, - "column": 13, + "column": 4, "program": "optional_field_interfaceUnion.ets" }, "end": { @@ -1548,7 +1548,7 @@ "loc": { "start": { "line": 25, - "column": 13, + "column": 4, "program": "optional_field_interfaceUnion.ets" }, "end": { diff --git a/ets2panda/test/unit/plugin/CMakeLists.txt b/ets2panda/test/unit/plugin/CMakeLists.txt index 672aff08e47fc7bb6d04a499fb451dc6d7bcff1e..fd18ff92ddbd5b90435eb016afde6cb95a585433 100644 --- a/ets2panda/test/unit/plugin/CMakeLists.txt +++ b/ets2panda/test/unit/plugin/CMakeLists.txt @@ -111,6 +111,7 @@ set(PLUGIN_TESTS "plugin_proceed_to_state_test_interface_duplicate_setter compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" "plugin_proceed_to_state_test_case_block_dump compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" "plugin_proceed_to_state_function_dump compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" + "pugin_proceed_to_state_annotationUsage_source_range_access compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" ) set(RUNTIME_ARGUMENTS diff --git a/ets2panda/test/unit/plugin/pugin_proceed_to_state_annotationUsage_source_range_access.cpp b/ets2panda/test/unit/plugin/pugin_proceed_to_state_annotationUsage_source_range_access.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c7b783272e66c83bb6e596d5de2fba1422573e15 --- /dev/null +++ b/ets2panda/test/unit/plugin/pugin_proceed_to_state_annotationUsage_source_range_access.cpp @@ -0,0 +1,128 @@ +/** + * 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. + */ + +#include +#include +#include + +#include "os/library_loader.h" + +#include "public/es2panda_lib.h" +#include "util.h" + +// NOLINTBEGIN + +static es2panda_Impl *impl = nullptr; + +static constexpr size_t START_INDEX = 101; +static constexpr size_t START_LINE = 4; +static constexpr size_t END_INDEX = 110; +static constexpr size_t END_LINE = 4; + +static std::string source = R"( +@interface Component {} + +// expected annotationUsage location: start: 'C', end: 't' of @Component. +@Component +class A { + name: string = "Tom"; +} +)"; + +static std::vector classDeclarations; + +static void CollectDeclarations(es2panda_AstNode *node) +{ + if (impl->IsClassDeclaration(node)) { + classDeclarations.push_back(node); + } +} + +static es2panda_AstNode *GetAnnotationUsage(es2panda_Context *context, es2panda_AstNode *classDecl) +{ + size_t n; + auto *classDef = impl->ClassDeclarationDefinition(context, classDecl); + auto **annotations = impl->ClassDefinitionAnnotations(context, classDef, &n); + if (n != 1) { + return nullptr; + } + return impl->AnnotationUsageIrExpr(context, annotations[0]); +} + +static bool ValidateAnnotationSourceRange(es2panda_Context *context) +{ + auto *classDel = classDeclarations.front(); + auto *annotationUsage = GetAnnotationUsage(context, classDel); + auto range = impl->AstNodeRangeConst(context, annotationUsage); + auto start = impl->SourceRangeStart(context, const_cast(range)); + auto end = impl->SourceRangeEnd(context, const_cast(range)); + if (start == nullptr || end == nullptr) { + return false; + } + if (START_INDEX != impl->SourcePositionIndex(context, start) || + START_LINE != impl->SourcePositionLine(context, start) || + END_INDEX != impl->SourcePositionIndex(context, end) || END_LINE != impl->SourcePositionLine(context, end)) { + return false; + } + return true; +} + +int main(int argc, char **argv) +{ + if (argc < MIN_ARGC) { + return INVALID_ARGC_ERROR_CODE; + } + + impl = GetImpl(); + if (impl == nullptr) { + return NULLPTR_IMPL_ERROR_CODE; + } + auto config = impl->CreateConfig(argc - 1, argv + 1); + auto context = impl->CreateContextFromString(config, source.data(), argv[argc - 1]); + if (context == nullptr) { + std::cerr << "FAILED TO CREATE CONTEXT" << std::endl; + return NULLPTR_CONTEXT_ERROR_CODE; + } + + impl->ProceedToState(context, ES2PANDA_STATE_PARSED); + + auto *ast = impl->ProgramAst(context, impl->ContextProgram(context)); + impl->AstNodeIterateConst(context, ast, CollectDeclarations); + + if (!ValidateAnnotationSourceRange(context)) { + impl->DestroyContext(context); + impl->DestroyConfig(config); + return PROCEED_ERROR_CODE; + } + + impl->ProceedToState(context, ES2PANDA_STATE_CHECKED); + if (impl->ContextState(context) == ES2PANDA_STATE_ERROR) { + return PROCEED_ERROR_CODE; + } + + impl->AstNodeRecheck(context, ast); + + impl->ProceedToState(context, ES2PANDA_STATE_BIN_GENERATED); + if (impl->ContextState(context) == ES2PANDA_STATE_ERROR) { + return PROCEED_ERROR_CODE; + } + + impl->DestroyContext(context); + impl->DestroyConfig(config); + + return 0; +} + +// NOLINTEND \ No newline at end of file