1 /**
2 * Copyright (c) 2024-2025 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 "es2panda.h"
19 #include "ir/expressions/literals/stringLiteral.h"
20 #include "ir/expressions/identifier.h"
21 #include "ir/expressions/literals/numberLiteral.h"
22 #include "ir/expressions/literals/booleanLiteral.h"
23 #include "macros.h"
24 #include "varbinder/ETSBinder.h"
25 #include "util/diagnosticEngine.h"
26
27 namespace {
28
29 using ark::es2panda::ScriptExtension;
30 using ark::es2panda::checker::ETSChecker;
31 using ark::es2panda::compiler::ast_verifier::ArithmeticOperationValid;
32 using ark::es2panda::compiler::ast_verifier::NodeHasParent;
33 using ark::es2panda::compiler::ast_verifier::NodeHasSourceRange;
34 using ark::es2panda::compiler::ast_verifier::NodeHasType;
35 using ark::es2panda::compiler::ast_verifier::NoPrimitiveTypes;
36 using ark::es2panda::compiler::ast_verifier::SequenceExpressionHasLastType;
37 using ark::es2panda::compiler::ast_verifier::VariableHasEnclosingScope;
38 using ark::es2panda::compiler::ast_verifier::VariableHasScope;
39 using ark::es2panda::compiler::ast_verifier::VariableNameIdentifierNameSame;
40 using ark::es2panda::ir::BinaryExpression;
41 using ark::es2panda::ir::BooleanLiteral;
42 using ark::es2panda::ir::Expression;
43 using ark::es2panda::ir::Identifier;
44 using ark::es2panda::ir::NumberLiteral;
45 using ark::es2panda::ir::SequenceExpression;
46 using ark::es2panda::ir::StringLiteral;
47 using ark::es2panda::lexer::Number;
48 using ark::es2panda::lexer::TokenType;
49 using ark::es2panda::util::DiagnosticEngine;
50 using ark::es2panda::util::StringView;
51 using ark::es2panda::varbinder::FunctionScope;
52 using ark::es2panda::varbinder::LetDecl;
53 using ark::es2panda::varbinder::LocalScope;
54 using ark::es2panda::varbinder::LocalVariable;
55 using ark::es2panda::varbinder::VariableFlags;
56
TEST_F(ASTVerifierTest,NullParent)57 TEST_F(ASTVerifierTest, NullParent)
58 {
59 StringLiteral emptyNode;
60 EXPECT_TRUE(VerifyNode<NodeHasParent>(&emptyNode, ExpectVerifierMessage {"NULL_PARENT"}));
61 }
62
TEST_F(ASTVerifierTest,NullRange)63 TEST_F(ASTVerifierTest, NullRange)
64 {
65 StringLiteral emptyNode;
66 EXPECT_TRUE(VerifyNode<NodeHasSourceRange>(&emptyNode, ExpectVerifierMessage {"NULL_RANGE"}));
67 }
68
69 // NOTE(dkofanov): #22355 'NodeHasType' is broken.
TEST_F(ASTVerifierTest,DISABLED_NullType)70 TEST_F(ASTVerifierTest, DISABLED_NullType)
71 {
72 StringLiteral emptyNode;
73 EXPECT_TRUE(VerifyNode<NodeHasType>(&emptyNode, ExpectVerifierMessage {"NULL_TS_TYPE"}));
74 }
75
TEST_F(ASTVerifierTest,WithoutScope)76 TEST_F(ASTVerifierTest, WithoutScope)
77 {
78 StringLiteral emptyNode;
79 EXPECT_TRUE(VerifyNode<VariableHasScope>(&emptyNode));
80 }
81
TEST_F(ASTVerifierTest,ScopeTest)82 TEST_F(ASTVerifierTest, ScopeTest)
83 {
84 Identifier ident(StringView("var_decl"), Allocator());
85 LetDecl decl("test", &ident);
86 LocalVariable local(&decl, VariableFlags::LOCAL);
87 ident.SetVariable(&local);
88
89 LocalScope scope(Allocator(), nullptr);
90 FunctionScope parentScope(Allocator(), nullptr);
91 scope.SetParent(&parentScope);
92 scope.AddDecl(Allocator(), &decl, ScriptExtension::ETS);
93 scope.BindNode(&ident);
94
95 local.SetScope(&scope);
96
97 EXPECT_TRUE(VerifyNode<VariableHasScope>(&ident));
98 }
99
TEST_F(ASTVerifierTest,ScopeNodeTest)100 TEST_F(ASTVerifierTest, ScopeNodeTest)
101 {
102 Identifier ident(StringView("var_decl"), Allocator());
103 LetDecl decl("test", &ident);
104 LocalVariable local(&decl, VariableFlags::LOCAL);
105 ident.SetVariable(&local);
106
107 LocalScope scope(Allocator(), nullptr);
108 FunctionScope parentScope(Allocator(), nullptr);
109 scope.SetParent(&parentScope);
110 scope.AddDecl(Allocator(), &decl, ScriptExtension::ETS);
111 scope.BindNode(&ident);
112 parentScope.BindNode(&ident);
113
114 local.SetScope(&scope);
115
116 EXPECT_TRUE(VerifyNode<VariableHasEnclosingScope>(&ident));
117 }
118
TEST_F(ASTVerifierTest,ArithmeticExpressionCorrect1)119 TEST_F(ASTVerifierTest, ArithmeticExpressionCorrect1)
120 {
121 DiagnosticEngine de {};
122 ETSChecker etschecker {de};
123
124 auto left = NumberLiteral(Number {1});
125 auto right = NumberLiteral(Number {6});
126 auto arithmeticExpression = BinaryExpression(&left, &right, TokenType::PUNCTUATOR_PLUS);
127
128 left.SetTsType(etschecker.GlobalIntType());
129 right.SetTsType(etschecker.GlobalIntType());
130
131 EXPECT_TRUE(VerifyNode<ArithmeticOperationValid>(arithmeticExpression.AsBinaryExpression()));
132 }
133
TEST_F(ASTVerifierTest,ArithmeticExpressionCorrect2)134 TEST_F(ASTVerifierTest, ArithmeticExpressionCorrect2)
135 {
136 DiagnosticEngine de {};
137 ETSChecker etschecker {de};
138
139 constexpr uint32_t LEFT1_PARAM = 1;
140 constexpr uint32_t LEFT2_PARAM = 12;
141 constexpr uint32_t RIGHT2_PARAM = 6;
142 auto left1 = NumberLiteral(Number {LEFT1_PARAM});
143 auto left2 = NumberLiteral(Number {LEFT2_PARAM});
144 auto right2 = NumberLiteral(Number {RIGHT2_PARAM});
145 auto right1 = BinaryExpression(&left2, &right2, TokenType::PUNCTUATOR_MULTIPLY);
146 auto arithmeticExpression = BinaryExpression(&left1, &right1, TokenType::PUNCTUATOR_PLUS);
147
148 left1.SetTsType(etschecker.GlobalIntType());
149 right1.SetTsType(etschecker.GlobalIntType());
150 left2.SetTsType(etschecker.GlobalIntType());
151 right2.SetTsType(etschecker.GlobalIntType());
152
153 EXPECT_TRUE(VerifyNode<ArithmeticOperationValid>(arithmeticExpression.AsBinaryExpression()));
154 }
155
TEST_F(ASTVerifierTest,ArithmeticExpressionNegative1)156 TEST_F(ASTVerifierTest, ArithmeticExpressionNegative1)
157 {
158 DiagnosticEngine de {};
159 ETSChecker etschecker {de};
160
161 const StringView leftParam("1");
162 constexpr uint32_t RIGHT_PARAM = 1;
163 auto left = StringLiteral(leftParam);
164 auto right = NumberLiteral(Number {RIGHT_PARAM});
165 auto arithmeticExpression = BinaryExpression(&left, &right, TokenType::PUNCTUATOR_DIVIDE);
166
167 left.SetTsType(etschecker.GlobalETSStringLiteralType());
168 right.SetTsType(etschecker.GlobalIntType());
169
170 EXPECT_TRUE(VerifyNode<ArithmeticOperationValid>(arithmeticExpression.AsBinaryExpression(),
171 ExpectVerifierMessage {"Not a numeric type"}));
172 }
173
TEST_F(ASTVerifierTest,ArithmeticExpressionNegative2)174 TEST_F(ASTVerifierTest, ArithmeticExpressionNegative2)
175 {
176 DiagnosticEngine de {};
177 ETSChecker etschecker {de};
178
179 auto left = BooleanLiteral(true);
180 auto right = NumberLiteral(Number {1});
181 auto arithmeticExpression = BinaryExpression(&left, &right, TokenType::PUNCTUATOR_DIVIDE);
182
183 left.SetTsType(etschecker.GlobalETSStringLiteralType());
184 right.SetTsType(etschecker.GlobalIntType());
185
186 EXPECT_TRUE(VerifyNode<ArithmeticOperationValid>(arithmeticExpression.AsBinaryExpression(),
187 ExpectVerifierMessage {"Not a numeric type"}));
188 }
189
TEST_F(ASTVerifierTest,PrimitiveType)190 TEST_F(ASTVerifierTest, PrimitiveType)
191 {
192 DiagnosticEngine de {};
193 ETSChecker etschecker {de};
194
195 auto ast = BooleanLiteral(true);
196 ast.SetTsType(etschecker.CreateETSBooleanType(true));
197
198 ASSERT_TRUE(VerifyNode<NoPrimitiveTypes>(&ast, ExpectVerifierMessage {"PRIMITIVE_BEFORE_LOWERING"}));
199 Get<NoPrimitiveTypes>()->SetNumberLoweringOccured();
200 ASSERT_TRUE(VerifyNode<NoPrimitiveTypes>(&ast));
201 Get<NoPrimitiveTypes>()->SetNumberLoweringOccured(false);
202 }
203
TEST_F(ASTVerifierTest,SequenceExpressionType)204 TEST_F(ASTVerifierTest, SequenceExpressionType)
205 {
206 auto de = DiagnosticEngine();
207 auto checker = ETSChecker(de);
208 const auto literalsCount = 3;
209 std::array<NumberLiteral, literalsCount> literals {NumberLiteral {Number {1}}, NumberLiteral {Number {2}},
210 NumberLiteral {Number {3}}};
211 ark::ArenaVector<Expression *> expressions {Allocator()->Adapter()};
212 expressions.insert(expressions.end(), {&literals[0], &literals[1], &literals[2]});
213 SequenceExpression sequenceExpression {std::move(expressions)};
214
215 literals[literalsCount - 1].SetTsType(checker.GlobalIntType());
216 sequenceExpression.SetTsType(checker.GlobalIntType());
217
218 EXPECT_TRUE(VerifyNode<SequenceExpressionHasLastType>(&sequenceExpression));
219 }
220
TEST_F(ASTVerifierTest,VariableNameIdentifierNameSameNegative)221 TEST_F(ASTVerifierTest, VariableNameIdentifierNameSameNegative)
222 {
223 char const *text = R"(
224 function main(): void {
225 let tmp = 1;
226 let lambda2: (value: int) => Int = (value: int): Int => {
227 let a = 42;
228 let num: Int = new Int(a + value);
229 return num;
230 }
231 let n_tmp = tmp + 2;
232 }
233 )";
234
235 CONTEXT(ES2PANDA_STATE_CHECKED, text)
236 {
237 // Note(@kirillbychkov): Change Identifier name in variable lambda2
238 GetAst()
239 ->AsETSModule()
240 ->Statements()[0]
241 ->AsClassDeclaration()
242 ->Definition()
243 ->AsClassDefinition()
244 ->Body()[1]
245 ->AsClassElement()
246 ->Value()
247 ->AsFunctionExpression()
248 ->Function()
249 ->AsScriptFunction()
250 ->Body()
251 ->AsBlockStatement()
252 ->Statements()[1]
253 ->AsVariableDeclaration()
254 ->Declarators()[0]
255 ->AsVariableDeclarator()
256 ->Id()
257 ->AsIdentifier()
258 ->SetName("not_name");
259
260 EXPECT_TRUE(Verify<VariableNameIdentifierNameSame>(ExpectVerifierMessage {"IDENTIFIER_NAME_DIFFERENCE"}));
261 }
262 }
263
TEST_F(ASTVerifierTest,VariableNameIdentifierNameSame)264 TEST_F(ASTVerifierTest, VariableNameIdentifierNameSame)
265 {
266 char const *text = R"(
267 function main(): void {
268 let tmp = 1;
269 let lambda2: (value: int) => Int = (value: int): Int => {
270 let a = 42;
271 let num: Int = new Int(a + value);
272 return num;
273 }
274 let n_tmp = tmp + 2;
275 }
276 )";
277
278 CONTEXT(ES2PANDA_STATE_CHECKED, text)
279 {
280 EXPECT_TRUE(Verify<VariableNameIdentifierNameSame>());
281 }
282 }
283
284 } // namespace
285