• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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