• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ast_verifier_test.h"
17 #include "checker/ETSchecker.h"
18 #include "ir/astNode.h"
19 
20 #include <gtest/gtest.h>
21 
22 using ark::es2panda::checker::ETSChecker;
23 using ark::es2panda::compiler::ast_verifier::ASTVerifier;
24 using ark::es2panda::compiler::ast_verifier::InvariantNameSet;
25 using ark::es2panda::ir::AstNode;
26 using ark::es2panda::ir::ETSParameterExpression;
27 using ark::es2panda::ir::Identifier;
28 using ark::es2panda::ir::MethodDefinitionKind;
29 
30 namespace {
31 
TEST_F(ASTVerifierTest,ValidateGetterArguments)32 TEST_F(ASTVerifierTest, ValidateGetterArguments)
33 {
34     ETSChecker checker {};
35     ASTVerifier verifier {Allocator()};
36 
37     char const *text =
38         R"(
39         class A {
40             private _value: number = 0;
41             get value(): number {
42                 return this._value
43             }
44 
45             set value(v: number): void {
46                 this._value = v
47             }
48         }
49     )";
50 
51     es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.ets");
52     impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED);
53     ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED);
54 
55     auto *ast = reinterpret_cast<AstNode *>(impl_->ProgramAst(impl_->ContextProgram(ctx)));
56 
57     // Create argument
58     auto *ident = checker.AllocNode<Identifier>("ident", Allocator());
59     auto *param = checker.AllocNode<ETSParameterExpression>(ident, nullptr);
60 
61     // Add argument to getter
62     ast->IterateRecursively([param](ark::es2panda::ir::AstNode *child) {
63         if (child->IsMethodDefinition()) {
64             auto *const method = child->AsMethodDefinition();
65             if (method->Kind() == MethodDefinitionKind::GET && method->Value()->IsFunctionExpression()) {
66                 auto *const function = method->Value()->AsFunctionExpression()->Function();
67                 auto &params = function->Params();
68                 ASSERT_EQ(params.size(), 0);
69                 params.push_back(param);
70             }
71         }
72     });
73 
74     InvariantNameSet checks;
75     checks.insert("GetterSetterValidationForAll");
76     const auto &messages = verifier.Verify(ast, checks);
77 
78     // Expecting warning
79     ASSERT_EQ(messages.size(), 1);
80     ASSERT_EQ(messages[0].Cause(), "GETTER METHOD HAS INCORRECT NUMBER OF ARGUMENTS");
81 
82     impl_->DestroyContext(ctx);
83 }
84 
TEST_F(ASTVerifierTest,ValidateSetterReturnType)85 TEST_F(ASTVerifierTest, ValidateSetterReturnType)
86 {
87     ETSChecker checker {};
88     ASTVerifier verifier {Allocator()};
89 
90     char const *text =
91         R"(
92         class A {
93             private _value: number = 0;
94             set value(v: number): void {
95                 this._value = v
96             }
97 
98             get value(): number {
99                 return this._value
100             }
101         }
102     )";
103 
104     es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.ets");
105     impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED);
106     ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED);
107 
108     auto *ast = reinterpret_cast<AstNode *>(impl_->ProgramAst(impl_->ContextProgram(ctx)));
109 
110     // Change setter return type
111     ast->IterateRecursively([&checker](ark::es2panda::ir::AstNode *child) {
112         if (child->IsMethodDefinition()) {
113             auto *const method = child->AsMethodDefinition();
114             if (method->Kind() == MethodDefinitionKind::SET && method->Value()->IsFunctionExpression()) {
115                 auto *const function = method->Value()->AsFunctionExpression()->Function();
116                 ASSERT_NE(function->ReturnTypeAnnotation(), nullptr);
117                 function->ReturnTypeAnnotation()->SetTsType(checker.GlobalIntType());
118             }
119         }
120     });
121 
122     InvariantNameSet checks;
123     checks.insert("GetterSetterValidationForAll");
124     const auto &messages = verifier.Verify(ast, checks);
125 
126     // Expecting warning
127     ASSERT_EQ(messages.size(), 1);
128     ASSERT_EQ(messages[0].Cause(), "SETTER METHOD HAS NON-VOID RETURN TYPE");
129 
130     impl_->DestroyContext(ctx);
131 }
132 
TEST_F(ASTVerifierTest,ValidateSetterArguments)133 TEST_F(ASTVerifierTest, ValidateSetterArguments)
134 {
135     ETSChecker checker {};
136     ASTVerifier verifier {Allocator()};
137 
138     char const *text =
139         R"(
140         class A {
141             private _value: number = 0;
142             set value(v: number): void {
143                 this._value = v
144             }
145 
146             get value(): number {
147                 return this._value
148             }
149         }
150     )";
151 
152     es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.ets");
153     impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED);
154     ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED);
155 
156     auto *ast = reinterpret_cast<AstNode *>(impl_->ProgramAst(impl_->ContextProgram(ctx)));
157 
158     // Change setter arguments
159     ast->IterateRecursively([](ark::es2panda::ir::AstNode *child) {
160         if (child->IsMethodDefinition()) {
161             auto *const method = child->AsMethodDefinition();
162             if (method->Kind() == MethodDefinitionKind::SET && method->Value()->IsFunctionExpression()) {
163                 auto *const function = method->Value()->AsFunctionExpression()->Function();
164                 auto &params = function->Params();
165                 ASSERT_EQ(params.size(), 1);
166                 params.clear();
167             }
168         }
169     });
170 
171     InvariantNameSet checks;
172     checks.insert("GetterSetterValidationForAll");
173     const auto &messages = verifier.Verify(ast, checks);
174 
175     // Expecting warning
176     ASSERT_EQ(messages.size(), 1);
177     ASSERT_EQ(messages[0].Cause(), "SETTER METHOD HAS INCORRECT NUMBER OF ARGUMENTS");
178 
179     impl_->DestroyContext(ctx);
180 }
181 }  // anonymous namespace
182