From 4bc5171d8e9b173222afde908b10e868971522fa Mon Sep 17 00:00:00 2001 From: Redkin Mikhail Date: Tue, 13 Feb 2024 16:08:34 +0300 Subject: [PATCH] Add new verifier checks Issue [ArkTS Frontend] Add ASTVerifier check all source ranges are set, check child is in parents range Reason Add ASTVerifier check all source ranges are set, check child is in parents range Description Add ASTVerifier check all source ranges are set, check child is in parents range Tests All required pre-merge tests passed. Results are available in the ggwatcher. Signed-off-by: Redkin Mikhail --- ets2panda/compiler/core/ASTVerifier.cpp | 49 +++++++++++++++++++ ets2panda/compiler/core/ASTVerifier.h | 2 + .../test/unit/public/ast_verifier_test.cpp | 16 ++++++ ets2panda/util/options.cpp | 4 +- 4 files changed, 69 insertions(+), 2 deletions(-) diff --git a/ets2panda/compiler/core/ASTVerifier.cpp b/ets2panda/compiler/core/ASTVerifier.cpp index b364674a60..faa26247ca 100644 --- a/ets2panda/compiler/core/ASTVerifier.cpp +++ b/ets2panda/compiler/core/ASTVerifier.cpp @@ -421,6 +421,22 @@ public: } }; +class NodeHasSourceRange { +public: + explicit NodeHasSourceRange([[maybe_unused]] ArenaAllocator &allocator) {} + + [[nodiscard]] CheckResult operator()(CheckContext &ctx, const ir::AstNode *ast) + { + const auto hasRange = + ast->Start().line != 0 || ast->Start().index != 0 || ast->End().line != 0 || ast->End().index != 0; + if (!hasRange) { + ctx.AddCheckMessage("NULL_RANGE", *ast, ast->Start()); + return {CheckDecision::INCORRECT, CheckAction::CONTINUE}; + } + return {CheckDecision::CORRECT, CheckAction::CONTINUE}; + } +}; + class IdentifierHasVariable { public: explicit IdentifierHasVariable([[maybe_unused]] ArenaAllocator &allocator) {} @@ -671,6 +687,37 @@ private: ArenaAllocator &allocator_; }; +class EveryChildInParentRange { +public: + explicit EveryChildInParentRange([[maybe_unused]] ArenaAllocator &allocator) {} + + [[nodiscard]] CheckResult operator()(CheckContext &ctx, const ir::AstNode *ast) + { + auto result = std::make_tuple(CheckDecision::CORRECT, CheckAction::CONTINUE); + if (ast->Parent() == nullptr) { + return result; + } + ast->Iterate([&](const ir::AstNode *node) { + if (ast != node->Parent()) { + result = {CheckDecision::INCORRECT, CheckAction::CONTINUE}; + } + if (ast->Start().line > node->Start().line || ast->End().line < node->End().line) { + result = {CheckDecision::INCORRECT, CheckAction::CONTINUE}; + } + if (ast->Start().line == node->Start().line && ast->Start().index > node->Start().index) { + result = {CheckDecision::INCORRECT, CheckAction::CONTINUE}; + } + if (ast->End().line == node->End().line && ast->End().index < node->End().index) { + result = {CheckDecision::INCORRECT, CheckAction::CONTINUE}; + } + ctx.AddCheckMessage("INCORRECT_CHILD_RANGE", *node, node->Start()); + }); + return result; + } + +private: +}; + class EveryChildHasValidParent { public: explicit EveryChildHasValidParent([[maybe_unused]] ArenaAllocator &allocator) {} @@ -1082,10 +1129,12 @@ private: ASTVerifier::ASTVerifier(ArenaAllocator *allocator) { AddInvariant(allocator, "NodeHasParent"); + AddInvariant(allocator, "NodeHasSourceRange"); AddInvariant(allocator, "NodeHasType"); AddInvariant(allocator, "IdentifierHasVariable"); AddInvariant(allocator, "VariableHasScope"); AddInvariant(allocator, "EveryChildHasValidParent"); + AddInvariant(allocator, "EveryChildInParentRange"); AddInvariant(allocator, "VariableHasEnclosingScope"); AddInvariant(allocator, "ForLoopCorrectlyInitialized"); AddInvariant(allocator, "ModifierAccessValid"); diff --git a/ets2panda/compiler/core/ASTVerifier.h b/ets2panda/compiler/core/ASTVerifier.h index b8bcf3152e..d5673d966a 100644 --- a/ets2panda/compiler/core/ASTVerifier.h +++ b/ets2panda/compiler/core/ASTVerifier.h @@ -95,7 +95,9 @@ public: { if (phaseName == "ScopesInitPhase") { accumulatedChecks_.insert("NodeHasParentForAll"); + accumulatedChecks_.insert("NodeHasSourceRangeForAll"); accumulatedChecks_.insert("EveryChildHasValidParentForAll"); + accumulatedChecks_.insert("EveryChildInParentRangeForAll"); accumulatedChecks_.insert("VariableHasScopeForAll"); } if (phaseName == "CheckerPhase") { diff --git a/ets2panda/test/unit/public/ast_verifier_test.cpp b/ets2panda/test/unit/public/ast_verifier_test.cpp index 1ca8571522..7c82b31884 100644 --- a/ets2panda/test/unit/public/ast_verifier_test.cpp +++ b/ets2panda/test/unit/public/ast_verifier_test.cpp @@ -121,6 +121,22 @@ TEST_F(ASTVerifierTest, NullParent) ASSERT_EQ(messages[0].Invariant(), check); } +TEST_F(ASTVerifierTest, NullRange) +{ + ark::es2panda::compiler::ast_verifier::ASTVerifier verifier {Allocator()}; + StringLiteral emptyNode; + + const auto check = "NodeHasSourceRange"; + auto checks = ark::es2panda::compiler::ast_verifier::InvariantNameSet {}; + checks.insert(check); + const auto &messages = verifier.Verify(&emptyNode, checks); + bool hasSourceRange = messages.empty(); + ASSERT_FALSE(hasSourceRange); + ASSERT_EQ(messages.size(), 1); + + ASSERT_EQ(messages[0].Invariant(), check); +} + TEST_F(ASTVerifierTest, NullType) { ASTVerifier verifier {Allocator()}; diff --git a/ets2panda/util/options.cpp b/ets2panda/util/options.cpp index 22519a040f..c1fe15242d 100644 --- a/ets2panda/util/options.cpp +++ b/ets2panda/util/options.cpp @@ -187,7 +187,7 @@ bool Options::Parse(int argc, const char **argv) "NodeHasParentForAll,EveryChildHasValidParentForAll,VariableHasScopeForAll,NodeHasTypeForAll," "IdentifierHasVariableForAll,ArithmeticOperationValidForAll,SequenceExpressionHasLastTypeForAll," "ForLoopCorrectlyInitializedForAll,VariableHasEnclosingScopeForAll,ModifierAccessValidForAll," - "ImportExportAccessValid"); + "ImportExportAccessValid,NodeHasSourceRangeForAll,EveryChildInParentRangeForAll"); ark::PandArg verifierErrors( "verifier-errors", "ForLoopCorrectlyInitializedForAll,SequenceExpressionHasLastTypeForAll,NodeHasTypeForAll,NodeHasParentForAll," @@ -198,7 +198,7 @@ bool Options::Parse(int argc, const char **argv) "NodeHasParentForAll,EveryChildHasValidParentForAll,VariableHasScopeForAll,NodeHasTypeForAll," "IdentifierHasVariableForAll,ArithmeticOperationValidForAll,SequenceExpressionHasLastTypeForAll," "ForLoopCorrectlyInitializedForAll,VariableHasEnclosingScopeForAll,ModifierAccessValidForAll," - "ImportExportAccessValid"); + "ImportExportAccessValid,NodeHasSourceRangeForAll,EveryChildInParentRangeForAll"); ark::PandArg verifierAllChecks( "verifier-all-checks", false, "Run verifier checks on every phase, monotonically expanding them on every phase"); -- Gitee