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,TSQualifiedName)29 TEST_F(ASTVerifierTest, TSQualifiedName)
30 {
31 ASTVerifier verifier {Allocator()};
32
33 char const *text = R"(
34 import * as Time from "std/time";
35
36 function main() {
37 let value = new Time.Chrono();
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,ParametersInArrowFunctionExpression)55 TEST_F(ASTVerifierTest, ParametersInArrowFunctionExpression)
56 {
57 ASTVerifier verifier {Allocator()};
58
59 char const *text = R"(
60 let b = 1;
61 let f = (p: double) => b + p;
62 function main () {
63 assert f(42) == 43
64 }
65 )";
66
67 es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.sts");
68 impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED);
69 ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED);
70
71 auto *ast = reinterpret_cast<AstNode *>(impl_->ProgramAst(impl_->ContextProgram(ctx)));
72
73 InvariantNameSet checks;
74 checks.insert("IdentifierHasVariableForAll");
75 const auto &messages = verifier.Verify(ast, checks);
76 ASSERT_EQ(messages.size(), 0);
77
78 impl_->DestroyContext(ctx);
79 }
80
TEST_F(ASTVerifierTest,Lambdas)81 TEST_F(ASTVerifierTest, Lambdas)
82 {
83 ASTVerifier verifier {Allocator()};
84
85 char const *text = R"(
86 type asyncLambda = () => Promise<void>;
87
88 async function asyncFunc(): Promise<boolean> {
89 return true;
90 }
91
92 function callAsyncLambda(): void {
93 let is_call_async_lambda: boolean = false;
94
95 let async_lambda: asyncLambda = async (): Promise<void> => {
96 await asyncFunc();
97 is_call_async_lambda = true;
98 };
99 }
100
101 type I2v = (i: int) => void;
102 type T1 = (lambda: (arg: int) => int, arg: int) => int;
103 type T2 = (c: int) => int;
104
105 const F1: I2v = (counter: int) => {
106 let funcWithLambda: T1 = (lambda: (arg: int) => int, arg: int) => {
107 return lambda(arg);
108 };
109
110 let it: T2 = (c: int): int => {
111 return c;
112 };
113
114 while (counter > 0) counter = funcWithLambda(it, counter);
115 };
116
117 function main() {
118 F1(44);
119 return 0;
120 }
121 )";
122
123 es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.sts");
124 impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED);
125 ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED);
126
127 auto *ast = reinterpret_cast<AstNode *>(impl_->ProgramAst(impl_->ContextProgram(ctx)));
128
129 InvariantNameSet checks;
130 checks.insert("IdentifierHasVariableForAll");
131 const auto &messages = verifier.Verify(ast, checks);
132 ASSERT_EQ(messages.size(), 0);
133
134 impl_->DestroyContext(ctx);
135 }
136
TEST_F(ASTVerifierTest,PromiseUndefined)137 TEST_F(ASTVerifierTest, PromiseUndefined)
138 {
139 ASTVerifier verifier {Allocator()};
140
141 char const *text = R"(
142 async function testAsyncVoidNothing() {}
143 )";
144
145 es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.sts");
146 impl_->ProceedToState(ctx, ES2PANDA_STATE_LOWERED);
147 ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_LOWERED);
148
149 auto *ast = reinterpret_cast<AstNode *>(impl_->ProgramAst(impl_->ContextProgram(ctx)));
150
151 InvariantNameSet checks;
152 checks.insert("IdentifierHasVariableForAll");
153 const auto &messages = verifier.Verify(ast, checks);
154 ASSERT_EQ(messages.size(), 0);
155
156 impl_->DestroyContext(ctx);
157 }
158
TEST_F(ASTVerifierTest,AnonymousClassId)159 TEST_F(ASTVerifierTest, AnonymousClassId)
160 {
161 ASTVerifier verifier {Allocator()};
162
163 char const *text = R"(
164 interface H {
165 }
166
167 class B {
168 func: H = new H() {
169 }
170 }
171
172 function main() {}
173 )";
174
175 es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.sts");
176 impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED);
177 ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED);
178
179 auto *ast = reinterpret_cast<AstNode *>(impl_->ProgramAst(impl_->ContextProgram(ctx)));
180
181 InvariantNameSet checks;
182 checks.insert("IdentifierHasVariableForAll");
183 const auto &messages = verifier.Verify(ast, checks);
184 ASSERT_EQ(messages.size(), 0);
185
186 impl_->DestroyContext(ctx);
187 }
188
TEST_F(ASTVerifierTest,EnumInts)189 TEST_F(ASTVerifierTest, EnumInts)
190 {
191 ASTVerifier verifier {Allocator()};
192
193 char const *text = R"(
194 enum Color {
195 Red = 1,
196 Blue = 2
197 }
198
199 function main() {
200 let color: Color = Color.Red;
201 let name = color.getName();
202 }
203 )";
204
205 es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.sts");
206 impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED);
207 ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED);
208
209 auto *ast = reinterpret_cast<AstNode *>(impl_->ProgramAst(impl_->ContextProgram(ctx)));
210
211 InvariantNameSet checks;
212 checks.insert("IdentifierHasVariableForAll");
213 const auto &messages = verifier.Verify(ast, checks);
214 ASSERT_EQ(messages.size(), 0);
215
216 impl_->DestroyContext(ctx);
217 }
218
TEST_F(ASTVerifierTest,EnumStrings)219 TEST_F(ASTVerifierTest, EnumStrings)
220 {
221 ASTVerifier verifier {Allocator()};
222
223 char const *text = R"(
224 enum Shape {
225 Circle = "CIRCLE",
226 Square = "SQUARE",
227 Triangle = "TRIANGLE"
228 }
229
230 function main() {
231 let shape = Shape.Circle.valueOf();
232 }
233 )";
234
235 es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.sts");
236 impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED);
237 ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED);
238
239 auto *ast = reinterpret_cast<AstNode *>(impl_->ProgramAst(impl_->ContextProgram(ctx)));
240
241 InvariantNameSet checks;
242 checks.insert("IdentifierHasVariableForAll");
243 const auto &messages = verifier.Verify(ast, checks);
244 ASSERT_EQ(messages.size(), 0);
245
246 impl_->DestroyContext(ctx);
247 }
248
249 } // namespace
250