• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-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 <gtest/gtest.h>
17 #include <algorithm>
18 
19 #include "checker/ETSAnalyzer.h"
20 #include "checker/ETSchecker.h"
21 #include "compiler/core/compilerImpl.h"
22 #include "compiler/core/ETSCompiler.h"
23 #include "compiler/core/ETSemitter.h"
24 #include "compiler/core/ETSGen.h"
25 #include "compiler/core/regSpiller.h"
26 #include "compiler/lowering/phase.h"
27 #include "es2panda.h"
28 #include "mem/arena_allocator.h"
29 #include "mem/pool_manager.h"
30 #include "public/public.h"
31 #include "util/arktsconfig.h"
32 #include "util/generateBin.h"
33 #include "varbinder/ETSBinder.h"
34 #include "test/utils/panda_executable_path_getter.h"
35 #include "checker/types/globalTypesHolder.h"
36 #include "test/unit/union_normalisation_test.h"
37 
38 using ark::es2panda::gtests::UnionNormalizationTest;
39 
40 namespace ark::es2panda {
41 
TEST_F(UnionNormalizationTest,UnionWithSubTypes)42 TEST_F(UnionNormalizationTest, UnionWithSubTypes)
43 {
44     // Test 4 cases of normalization
45     static constexpr std::string_view SRC =
46         "\
47         class Base {}\
48         class Derived1 extends Base {}\
49         class Derived2 extends Base {}\
50         ";
51     InitializeChecker("_.sts", SRC);
52 
53     auto program = Program();
54     ASSERT(program);
55 
56     auto *const baseType = FindClassType(program->VarBinder()->AsETSBinder(), "Base");
57     ASSERT_NE(baseType, nullptr);
58     auto *const derived1Type = FindClassType(program->VarBinder()->AsETSBinder(), "Derived1");
59     ASSERT_NE(derived1Type, nullptr);
60     auto *const derived2Type = FindClassType(program->VarBinder()->AsETSBinder(), "Derived2");
61     ASSERT_NE(derived2Type, nullptr);
62 
63     auto checker = Checker();
64     ASSERT(checker);
65 
66     // Test normalization: Derived1 | Base ==> Base
67     ArenaVector<checker::Type *> unionConstituents1(checker->Allocator()->Adapter());
68     unionConstituents1.emplace_back(derived1Type);
69     unionConstituents1.emplace_back(baseType);
70 
71     // Create union type, which will be normalized inside creation function
72     auto *const normalizedType1 = checker->CreateETSUnionType(std::move(unionConstituents1));
73     ASSERT_NE(normalizedType1, nullptr);
74     ASSERT_TRUE(normalizedType1->IsETSObjectType());
75     ASSERT_EQ(normalizedType1, baseType);
76 
77     // Test normalization: Base | Derived2 ==> Base
78     ArenaVector<checker::Type *> unionConstituents2(checker->Allocator()->Adapter());
79     unionConstituents2.emplace_back(baseType);
80     unionConstituents2.emplace_back(derived2Type);
81 
82     // Create union type, which will be normalized inside creation function
83     auto *const normalizedType2 = checker->CreateETSUnionType(std::move(unionConstituents2));
84     ASSERT_NE(normalizedType2, nullptr);
85     ASSERT_TRUE(normalizedType2->IsETSObjectType());
86     ASSERT_EQ(normalizedType2, baseType);
87 
88     // Test normalization: Derived1 | Derived2 ==> Derived1 | Derived2
89     ArenaVector<checker::Type *> unionConstituents3(checker->Allocator()->Adapter());
90     unionConstituents3.emplace_back(derived1Type);
91     unionConstituents3.emplace_back(derived2Type);
92 
93     // Create union type, which will be normalized inside creation function
94     auto *const normalizedType3 = checker->CreateETSUnionType(std::move(unionConstituents3));
95     ASSERT_NE(normalizedType3, nullptr);
96     auto *const unionType = normalizedType3->AsETSUnionType();
97     ASSERT_EQ(unionType->ConstituentTypes().size(), SIZE2);
98     ASSERT_EQ(unionType->ConstituentTypes().at(IDX0), derived1Type);
99     ASSERT_EQ(unionType->ConstituentTypes().at(IDX1), derived2Type);
100 
101     // Test normalization: Derived2 | Base | Derived1 ==> Base
102     ArenaVector<checker::Type *> unionConstituents4(checker->Allocator()->Adapter());
103     unionConstituents4.emplace_back(derived1Type);
104     unionConstituents4.emplace_back(baseType);
105     unionConstituents4.emplace_back(derived2Type);
106 
107     // Create union type, which will be normalized inside creation function
108     auto *const normalizedType4 = checker->CreateETSUnionType(std::move(unionConstituents4));
109     ASSERT_NE(normalizedType4, nullptr);
110     ASSERT_TRUE(normalizedType4->IsETSObjectType());
111     ASSERT_EQ(normalizedType4, baseType);
112 }
113 
TEST_F(UnionNormalizationTest,DISABLED_UnionLinearization)114 TEST_F(UnionNormalizationTest, DISABLED_UnionLinearization)
115 {
116     // Test 3 cases of normalization
117     static constexpr std::string_view SRC =
118         "\
119         class Base {}\
120         class Derived1 extends Base {}\
121         class Derived2 extends Base {}\
122         type UT = int | string\
123         \
124         type UT1 = int | (int | string) | number\
125         type UT2 = int | UT | number\
126         type UT3 = int | (Derived2 | Base) | Derived1 | (string | number | short) | (int | string)\
127         ";
128     InitializeChecker("_.sts", SRC);
129 
130     auto program = Program();
131     ASSERT(program);
132 
133     auto *varbinder = program->VarBinder()->AsETSBinder();
134     auto *const baseType = FindClassType(varbinder, "Base");
135     ASSERT_NE(baseType, nullptr);
136     auto *const derived1Type = FindClassType(program->VarBinder()->AsETSBinder(), "Derived1");
137     ASSERT_NE(derived1Type, nullptr);
138     auto *const derived2Type = FindClassType(program->VarBinder()->AsETSBinder(), "Derived2");
139     ASSERT_NE(derived2Type, nullptr);
140 
141     auto checker = Checker();
142     ASSERT(checker);
143 
144     // Test normalization: int | (int | string) | number ==> string | number
145     auto *const ut1Type = FindTypeAlias(checker, "UT1");
146     ASSERT_NE(ut1Type, nullptr);
147     ASSERT_TRUE(ut1Type->IsETSUnionType());
148     auto *ut1 = ut1Type->AsETSUnionType();
149     ASSERT_EQ(ut1->ConstituentTypes().size(), SIZE2);
150     ASSERT_EQ(ut1->ConstituentTypes().at(IDX0), checker->GlobalBuiltinETSStringType());
151     ASSERT_EQ(ut1->ConstituentTypes().at(IDX1), checker->GetGlobalTypesHolder()->GlobalDoubleBuiltinType());
152 
153     // Test normalization: int | UT | number ==> string | number
154     auto *const ut2Type = FindTypeAlias(checker, "UT2");
155     ASSERT_NE(ut2Type, nullptr);
156     ASSERT_TRUE(ut2Type->IsETSUnionType());
157     auto *ut2 = ut2Type->AsETSUnionType();
158     ASSERT_EQ(ut2->ConstituentTypes().size(), SIZE2);
159     ASSERT_EQ(ut2->ConstituentTypes().at(IDX0), checker->GlobalBuiltinETSStringType());
160     ASSERT_EQ(ut2->ConstituentTypes().at(IDX1), checker->GetGlobalTypesHolder()->GlobalDoubleBuiltinType());
161 
162     // Test normalization:
163     // int | (Derived2 | Base) | Derived1 | (string | number | short) | (int | string) ==> Base | string | number
164     auto *const ut3Type = FindTypeAlias(checker, "UT3");
165     ASSERT_NE(ut3Type, nullptr);
166     ASSERT_TRUE(ut3Type->IsETSUnionType());
167     auto *ut3 = ut3Type->AsETSUnionType();
168     ASSERT_EQ(ut3->ConstituentTypes().size(), SIZE3);
169     ASSERT_EQ(ut3->ConstituentTypes().at(IDX0), baseType);
170     ASSERT_EQ(ut3->ConstituentTypes().at(IDX1), checker->GlobalBuiltinETSStringType());
171     ASSERT_EQ(ut3->ConstituentTypes().at(IDX2), checker->GetGlobalTypesHolder()->GlobalDoubleBuiltinType());
172 }
173 
TEST_F(UnionNormalizationTest,UnionStringLiterals1)174 TEST_F(UnionNormalizationTest, UnionStringLiterals1)
175 {
176     InitializeChecker("_.sts", "");
177 
178     auto checker = Checker();
179     ASSERT(checker);
180 
181     // Test normalization: string | "abc" ==> string
182     ArenaVector<checker::Type *> unionConstituents1(checker->Allocator()->Adapter());
183     unionConstituents1.emplace_back(checker->GlobalBuiltinETSStringType());
184     unionConstituents1.emplace_back(checker->CreateETSStringLiteralType("abc"));
185 
186     // Create union type, which will be normalized inside creation function
187     auto *const normalizedType1 = checker->CreateETSUnionType(std::move(unionConstituents1));
188     ASSERT_NE(normalizedType1, nullptr);
189     ASSERT_TRUE(normalizedType1->IsETSObjectType());
190     ASSERT_EQ(normalizedType1, checker->GlobalBuiltinETSStringType());
191 
192     // Test normalization: "abc" | string | string ==> string
193     ArenaVector<checker::Type *> unionConstituents2(checker->Allocator()->Adapter());
194     unionConstituents2.emplace_back(checker->CreateETSStringLiteralType("abc"));
195     unionConstituents2.emplace_back(checker->GlobalBuiltinETSStringType());
196     unionConstituents2.emplace_back(checker->GlobalBuiltinETSStringType());
197 
198     // Create union type, which will be normalized inside creation function
199     auto *const normalizedType2 = checker->CreateETSUnionType(std::move(unionConstituents2));
200     ASSERT_NE(normalizedType2, nullptr);
201     ASSERT_TRUE(normalizedType2->IsETSObjectType());
202     ASSERT_EQ(normalizedType2, checker->GlobalBuiltinETSStringType());
203 
204     // Test normalization: number | "abc" | string | "xy" ==> number | string
205     ArenaVector<checker::Type *> unionConstituents3(checker->Allocator()->Adapter());
206     unionConstituents3.emplace_back(checker->GlobalDoubleType());
207     unionConstituents3.emplace_back(checker->CreateETSStringLiteralType("abc"));
208     unionConstituents3.emplace_back(checker->GlobalBuiltinETSStringType());
209     unionConstituents3.emplace_back(checker->CreateETSStringLiteralType("xy"));
210 
211     // Create union type, which will be normalized inside creation function
212     auto *const normalizedType3 = checker->CreateETSUnionType(std::move(unionConstituents3));
213     ASSERT_NE(normalizedType3, nullptr);
214     ASSERT_TRUE(normalizedType3->IsETSUnionType());
215     auto *const unionType = normalizedType3->AsETSUnionType();
216     ASSERT_EQ(unionType->ConstituentTypes().size(), SIZE2);
217     ASSERT_EQ(unionType->ConstituentTypes().at(IDX0), checker->GetGlobalTypesHolder()->GlobalDoubleBuiltinType());
218     ASSERT_EQ(unionType->ConstituentTypes().at(IDX1), checker->GlobalBuiltinETSStringType());
219 
220     // Test normalization: "abcd" | "abcd" | "abcd" ==> "abcd"
221     ArenaVector<checker::Type *> unionConstituents4(checker->Allocator()->Adapter());
222     unionConstituents4.emplace_back(checker->CreateETSStringLiteralType("abcd"));
223     unionConstituents4.emplace_back(checker->CreateETSStringLiteralType("abcd"));
224     unionConstituents4.emplace_back(checker->CreateETSStringLiteralType("abcd"));
225 
226     // Create union type, which will be normalized inside creation function
227     auto *const normalizedType4 = checker->CreateETSUnionType(std::move(unionConstituents4));
228     ASSERT_NE(normalizedType4, nullptr);
229     ASSERT_TRUE(normalizedType4->IsETSStringType());
230     ASSERT_EQ(normalizedType4->AsETSStringType()->GetValue(), "abcd");
231 }
232 
TEST_F(UnionNormalizationTest,UnionStringLiterals2)233 TEST_F(UnionNormalizationTest, UnionStringLiterals2)
234 {
235     InitializeChecker("_.sts", "");
236 
237     auto checker = Checker();
238     ASSERT(checker);
239 
240     // Test absence of normalization: "ab1" | "bc2" | "cd3" ==> "ab1" | "bc2" | "cd3"
241     ArenaVector<checker::Type *> unionConstituents1(checker->Allocator()->Adapter());
242     unionConstituents1.emplace_back(checker->CreateETSStringLiteralType("ab1"));
243     unionConstituents1.emplace_back(checker->CreateETSStringLiteralType("bc2"));
244     unionConstituents1.emplace_back(checker->CreateETSStringLiteralType("cd3"));
245 
246     // Create union type, which will be normalized inside creation function
247     auto *const normalizedType1 = checker->CreateETSUnionType(std::move(unionConstituents1));
248     ASSERT_NE(normalizedType1, nullptr);
249     ASSERT_TRUE(normalizedType1->IsETSUnionType());
250     auto *const unionType1 = normalizedType1->AsETSUnionType();
251     ASSERT_EQ(unionType1->ConstituentTypes().size(), SIZE3);
252     ASSERT_TRUE(unionType1->ConstituentTypes().at(IDX0)->IsETSStringType());
253     ASSERT_EQ(unionType1->ConstituentTypes().at(IDX0)->AsETSStringType()->GetValue(), "ab1");
254     ASSERT_TRUE(unionType1->ConstituentTypes().at(IDX1)->IsETSStringType());
255     ASSERT_EQ(unionType1->ConstituentTypes().at(IDX1)->AsETSStringType()->GetValue(), "bc2");
256     ASSERT_TRUE(unionType1->ConstituentTypes().at(IDX2)->IsETSStringType());
257     ASSERT_EQ(unionType1->ConstituentTypes().at(IDX2)->AsETSStringType()->GetValue(), "cd3");
258 
259     // Test normalization: "ab1" | "bc2" | "ab1" ==> "ab1" | "bc2"
260     ArenaVector<checker::Type *> unionConstituents2(checker->Allocator()->Adapter());
261     unionConstituents2.emplace_back(checker->CreateETSStringLiteralType("ab1"));
262     unionConstituents2.emplace_back(checker->CreateETSStringLiteralType("bc2"));
263     unionConstituents2.emplace_back(checker->CreateETSStringLiteralType("ab1"));
264 
265     // Create union type, which will be normalized inside creation function
266     auto *const normalizedType2 = checker->CreateETSUnionType(std::move(unionConstituents2));
267     ASSERT_NE(normalizedType2, nullptr);
268     ASSERT_TRUE(normalizedType2->IsETSUnionType());
269     auto *const unionType2 = normalizedType2->AsETSUnionType();
270     ASSERT_EQ(unionType2->ConstituentTypes().size(), SIZE2);
271     ASSERT_TRUE(unionType2->ConstituentTypes().at(IDX0)->IsETSStringType());
272     ASSERT_EQ(unionType2->ConstituentTypes().at(IDX0)->AsETSStringType()->GetValue(), "ab1");
273     ASSERT_TRUE(unionType2->ConstituentTypes().at(IDX1)->IsETSStringType());
274     ASSERT_EQ(unionType2->ConstituentTypes().at(IDX1)->AsETSStringType()->GetValue(), "bc2");
275 
276     // Test absence of normalization: "ab1" | "bc2" | "cd3" | string | int ==> string | int
277     ArenaVector<checker::Type *> unionConstituents3(checker->Allocator()->Adapter());
278     unionConstituents3.emplace_back(checker->CreateETSStringLiteralType("ab1"));
279     unionConstituents3.emplace_back(checker->CreateETSStringLiteralType("bc2"));
280     unionConstituents3.emplace_back(checker->CreateETSStringLiteralType("cd3"));
281     unionConstituents3.emplace_back(checker->GlobalBuiltinETSStringType());
282     unionConstituents3.emplace_back(checker->GlobalIntType());
283 
284     // Create union type, which will be normalized inside creation function
285     auto *const normalizedType3 = checker->CreateETSUnionType(std::move(unionConstituents3));
286     ASSERT_NE(normalizedType3, nullptr);
287     ASSERT_TRUE(normalizedType3->IsETSUnionType());
288     auto *const unionType3 = normalizedType3->AsETSUnionType();
289     ASSERT_EQ(unionType3->ConstituentTypes().size(), SIZE2);
290     ASSERT_EQ(unionType3->ConstituentTypes().at(IDX0), checker->GlobalBuiltinETSStringType());
291     ASSERT_EQ(unionType3->ConstituentTypes().at(IDX1), checker->GetGlobalTypesHolder()->GlobalIntegerBuiltinType());
292 }
293 
TEST_F(UnionNormalizationTest,DISABLED_UnionWithNever)294 TEST_F(UnionNormalizationTest, DISABLED_UnionWithNever)
295 {
296     // Test normalization: int | never | number ==> number
297     InitializeChecker("_.sts", "");
298 
299     auto checker = Checker();
300     ASSERT(checker);
301 
302     ArenaVector<checker::Type *> unionConstituents(checker->Allocator()->Adapter());
303     unionConstituents.emplace_back(checker->GlobalIntType());
304     unionConstituents.emplace_back(checker->GetGlobalTypesHolder()->GlobalETSNeverType());
305     unionConstituents.emplace_back(checker->GetGlobalTypesHolder()->GlobalDoubleBuiltinType());
306 
307     // Create union type, which will be normalized inside creation function
308     auto *const normalizedType = checker->CreateETSUnionType(std::move(unionConstituents));
309     ASSERT_NE(normalizedType, nullptr);
310     ASSERT_TRUE(normalizedType->IsETSObjectType());
311     ASSERT_EQ(normalizedType, checker->GetGlobalTypesHolder()->GlobalDoubleBuiltinType());
312 }
313 
314 }  // namespace ark::es2panda
315