• 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/expressions/identifier.h"
19 #include "ir/astNode.h"
20 #include "parser/ETSparser.h"
21 
22 #include <gtest/gtest.h>
23 
24 using ark::es2panda::compiler::ast_verifier::ASTVerifier;
25 using ark::es2panda::compiler::ast_verifier::InvariantNameSet;
26 using ark::es2panda::ir::AstNode;
27 
28 namespace {
TEST_F(ASTVerifierTest,LabelsHaveReferences)29 TEST_F(ASTVerifierTest, LabelsHaveReferences)
30 {
31     ASTVerifier verifier {Allocator()};
32 
33     char const *text = R"(
34         function main(): void {
35         loop: for (let i = 0; i < 10; i++) {
36         break loop;
37         }
38         }
39     )";
40 
41     es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.sts");
42     impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED);
43     ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED);
44 
45     auto *ast = reinterpret_cast<AstNode *>(impl_->ProgramAst(impl_->ContextProgram(ctx)));
46 
47     InvariantNameSet checks;
48     checks.insert("IdentifierHasVariableForAll");
49     const auto &messages = verifier.Verify(ast, checks);
50     ASSERT_EQ(messages.size(), 0);
51 
52     impl_->DestroyContext(ctx);
53 }
54 
TEST_F(ASTVerifierTest,ExtensionFunction)55 TEST_F(ASTVerifierTest, ExtensionFunction)
56 {
57     ASTVerifier verifier {Allocator()};
58 
59     char const *text = R"(
60         class Fruit {
61             name(): void {
62             }
63         }
64 
65         function Fruit.name(id: int): void {
66         }
67 
68         function test() {
69         let fruit = new Fruit();
70         fruit.name()
71         }
72     )";
73 
74     es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.sts");
75     impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED);
76     ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED);
77 
78     auto *ast = reinterpret_cast<AstNode *>(impl_->ProgramAst(impl_->ContextProgram(ctx)));
79 
80     InvariantNameSet checks;
81     checks.insert("IdentifierHasVariableForAll");
82     const auto &messages = verifier.Verify(ast, checks);
83     ASSERT_EQ(messages.size(), 0);
84 
85     impl_->DestroyContext(ctx);
86 }
87 
TEST_F(ASTVerifierTest,Imports)88 TEST_F(ASTVerifierTest, Imports)
89 {
90     ASTVerifier verifier {Allocator()};
91 
92     char const *text = R"(
93         import { PI } from "std/math";
94         import { A } from "dynamic_js_import_tests"
95         import default_imported from "import_tests/modules/default_export";
96         import * as Time from "std/time";
97     )";
98 
99     es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.sts");
100     impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED);
101     ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED);
102 
103     auto *ast = reinterpret_cast<AstNode *>(impl_->ProgramAst(impl_->ContextProgram(ctx)));
104 
105     InvariantNameSet checks;
106     checks.insert("IdentifierHasVariableForAll");
107     const auto &messages = verifier.Verify(ast, checks);
108     ASSERT_EQ(messages.size(), 0);
109 
110     impl_->DestroyContext(ctx);
111 }
112 
TEST_F(ASTVerifierTest,TSQualifiedName)113 TEST_F(ASTVerifierTest, TSQualifiedName)
114 {
115     ASTVerifier verifier {Allocator()};
116 
117     char const *text = R"(
118         import * as Time from "std/time";
119 
120         function main() {
121         let value = new Time.Chrono();
122         }
123     )";
124 
125     es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.sts");
126     impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED);
127     ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED);
128 
129     auto *ast = reinterpret_cast<AstNode *>(impl_->ProgramAst(impl_->ContextProgram(ctx)));
130 
131     InvariantNameSet checks;
132     checks.insert("IdentifierHasVariableForAll");
133     const auto &messages = verifier.Verify(ast, checks);
134     ASSERT_EQ(messages.size(), 0);
135 
136     impl_->DestroyContext(ctx);
137 }
138 
TEST_F(ASTVerifierTest,ParametersInArrowFunctionExpression)139 TEST_F(ASTVerifierTest, ParametersInArrowFunctionExpression)
140 {
141     ASTVerifier verifier {Allocator()};
142 
143     char const *text = R"(
144         let b = 1;
145         let f = (p: double) => b + p;
146         function main () {
147             assert f(42) == 43
148         }
149     )";
150 
151     es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.sts");
152     impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED);
153     ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED);
154 
155     auto *ast = reinterpret_cast<AstNode *>(impl_->ProgramAst(impl_->ContextProgram(ctx)));
156 
157     InvariantNameSet checks;
158     checks.insert("IdentifierHasVariableForAll");
159     const auto &messages = verifier.Verify(ast, checks);
160     ASSERT_EQ(messages.size(), 0);
161 
162     impl_->DestroyContext(ctx);
163 }
164 
TEST_F(ASTVerifierTest,Lambdas)165 TEST_F(ASTVerifierTest, Lambdas)
166 {
167     ASTVerifier verifier {Allocator()};
168 
169     char const *text = R"(
170         type asyncLambda = () => Promise<void>;
171 
172         async function asyncFunc(): Promise<boolean> {
173             return true;
174         }
175 
176         function callAsyncLambda(): void {
177             let is_call_async_lambda: boolean = false;
178 
179             let async_lambda: asyncLambda = async (): Promise<void> => {
180                 await asyncFunc();
181                 is_call_async_lambda = true;
182             };
183         }
184 
185         type I2v = (i: int) => void;
186         type T1 = (lambda: (arg: int) => int, arg: int) => int;
187         type T2 = (c: int) => int;
188 
189         const F1: I2v = (counter: int) => {
190             let funcWithLambda: T1 = (lambda: (arg: int) => int, arg: int) => {
191                 return lambda(arg);
192             };
193 
194             let it: T2 = (c: int): int => {
195                 return c;
196             };
197 
198             while (counter > 0) counter = funcWithLambda(it, counter);
199         };
200 
201         function main() {
202             F1(44);
203             return 0;
204         }
205     )";
206 
207     es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.sts");
208     impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED);
209     ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED);
210 
211     auto *ast = reinterpret_cast<AstNode *>(impl_->ProgramAst(impl_->ContextProgram(ctx)));
212 
213     InvariantNameSet checks;
214     checks.insert("IdentifierHasVariableForAll");
215     const auto &messages = verifier.Verify(ast, checks);
216     ASSERT_EQ(messages.size(), 0);
217 
218     impl_->DestroyContext(ctx);
219 }
220 }  // namespace
221