1 /**
2 * Copyright (c) 2021-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 "checker/ETSchecker.h"
17
18 #include "checker/types/ets/etsAsyncFuncReturnType.h"
19 #include "checker/types/ets/etsEnumType.h"
20 #include "checker/types/ets/etsDynamicFunctionType.h"
21 #include "checker/types/ets/etsResizableArrayType.h"
22 #include "checker/types/globalTypesHolder.h"
23 #include "checker/types/type.h"
24 #include "ir/statements/annotationDeclaration.h"
25
26 namespace ark::es2panda::checker {
27
CreateByteType(int8_t value)28 ByteType *ETSChecker::CreateByteType(int8_t value)
29 {
30 return ProgramAllocator()->New<ByteType>(value);
31 }
32
CreateETSBooleanType(bool value)33 ETSBooleanType *ETSChecker::CreateETSBooleanType(bool value)
34 {
35 return ProgramAllocator()->New<ETSBooleanType>(value);
36 }
37
CreateDoubleType(double value)38 DoubleType *ETSChecker::CreateDoubleType(double value)
39 {
40 return ProgramAllocator()->New<DoubleType>(value);
41 }
42
CreateFloatType(float value)43 FloatType *ETSChecker::CreateFloatType(float value)
44 {
45 return ProgramAllocator()->New<FloatType>(value);
46 }
47
CreateIntType(int32_t value)48 IntType *ETSChecker::CreateIntType(int32_t value)
49 {
50 return ProgramAllocator()->New<IntType>(value);
51 }
52
CreateIntTypeFromType(Type * type)53 IntType *ETSChecker::CreateIntTypeFromType(Type *type)
54 {
55 if (!type->HasTypeFlag(TypeFlag::CONSTANT)) {
56 return GlobalIntType()->AsIntType();
57 }
58
59 if (type->IsIntType()) {
60 return type->AsIntType();
61 }
62
63 switch (ETSType(type)) {
64 case TypeFlag::CHAR: {
65 return CreateIntType(static_cast<int32_t>(type->AsCharType()->GetValue()));
66 }
67 case TypeFlag::BYTE: {
68 return CreateIntType(static_cast<int32_t>(type->AsByteType()->GetValue()));
69 }
70 case TypeFlag::SHORT: {
71 return CreateIntType(static_cast<int32_t>(type->AsShortType()->GetValue()));
72 }
73 default: {
74 return nullptr;
75 }
76 }
77 }
78
CreateLongType(int64_t value)79 LongType *ETSChecker::CreateLongType(int64_t value)
80 {
81 return ProgramAllocator()->New<LongType>(value);
82 }
83
CreateShortType(int16_t value)84 ShortType *ETSChecker::CreateShortType(int16_t value)
85 {
86 return ProgramAllocator()->New<ShortType>(value);
87 }
88
CreateCharType(char16_t value)89 CharType *ETSChecker::CreateCharType(char16_t value)
90 {
91 return ProgramAllocator()->New<CharType>(value);
92 }
93
CreateETSBigIntLiteralType(util::StringView value)94 ETSBigIntType *ETSChecker::CreateETSBigIntLiteralType(util::StringView value)
95 {
96 return ProgramAllocator()->New<ETSBigIntType>(ProgramAllocator(), GlobalBuiltinETSBigIntType(), Relation(), value);
97 }
98
CreateETSStringLiteralType(util::StringView value)99 ETSStringType *ETSChecker::CreateETSStringLiteralType(util::StringView value)
100 {
101 return ProgramAllocator()->New<ETSStringType>(ProgramAllocator(), GlobalBuiltinETSStringType(), Relation(), value);
102 }
103
CreateETSMultiDimResizableArrayType(Type * element,size_t dimSize)104 ETSResizableArrayType *ETSChecker::CreateETSMultiDimResizableArrayType(Type *element, size_t dimSize)
105 {
106 ETSObjectType *type = GlobalBuiltinETSResizableArrayType();
107 ES2PANDA_ASSERT(type != nullptr);
108 ETSResizableArrayType *const arrayType = type->AsETSResizableArrayType();
109 ES2PANDA_ASSERT(arrayType->TypeArguments().size() == 1U);
110
111 Type *baseArrayType = element;
112
113 for (size_t dim = 0; dim < dimSize; ++dim) {
114 Substitution *tmpSubstitution = NewSubstitution();
115 EmplaceSubstituted(tmpSubstitution, arrayType->TypeArguments()[0]->AsETSTypeParameter()->GetOriginal(),
116 MaybeBoxType(baseArrayType));
117 baseArrayType = arrayType->Substitute(Relation(), tmpSubstitution);
118 }
119 return baseArrayType->AsETSResizableArrayType();
120 }
121
CreateETSResizableArrayType(Type * element)122 ETSResizableArrayType *ETSChecker::CreateETSResizableArrayType(Type *element)
123 {
124 ETSObjectType *type = GlobalBuiltinETSResizableArrayType();
125 ES2PANDA_ASSERT(type != nullptr);
126 ETSResizableArrayType *arrayType = type->AsETSResizableArrayType();
127 ES2PANDA_ASSERT(arrayType->TypeArguments().size() == 1U);
128
129 Substitution *substitution = NewSubstitution();
130 EmplaceSubstituted(substitution, arrayType->TypeArguments()[0]->AsETSTypeParameter()->GetOriginal(),
131 MaybeBoxType(element));
132 return arrayType->Substitute(Relation(), substitution);
133 }
134
CreateETSArrayType(Type * elementType,bool isCachePolluting)135 ETSArrayType *ETSChecker::CreateETSArrayType(Type *elementType, bool isCachePolluting)
136 {
137 auto res = arrayTypes_.find({elementType, isCachePolluting});
138 if (res != arrayTypes_.end()) {
139 return res->second;
140 }
141
142 auto *arrayType = ProgramAllocator()->New<ETSArrayType>(elementType);
143
144 ES2PANDA_ASSERT(arrayType != nullptr);
145 std::stringstream ss;
146 arrayType->ToAssemblerTypeWithRank(ss);
147 // arrayType->SetAssemblerName(util::UString(ss.str(), ProgramAllocator()).View());
148
149 auto it = arrayTypes_.insert({{elementType, isCachePolluting}, arrayType});
150 if (it.second && (!elementType->IsTypeParameter() || !elementType->IsETSTypeParameter())) {
151 CreateBuiltinArraySignature(arrayType, arrayType->Rank());
152 }
153
154 return arrayType;
155 }
156
CreateETSUnionType(Span<Type * const> constituentTypes)157 Type *ETSChecker::CreateETSUnionType(Span<Type *const> constituentTypes)
158 {
159 if (constituentTypes.empty()) {
160 return nullptr;
161 }
162
163 ArenaVector<Type *> newConstituentTypes(ProgramAllocator()->Adapter());
164 newConstituentTypes.assign(constituentTypes.begin(), constituentTypes.end());
165
166 ETSUnionType::NormalizeTypes(Relation(), newConstituentTypes);
167 if (newConstituentTypes.size() == 1) {
168 return newConstituentTypes[0];
169 }
170
171 return ProgramAllocator()->New<ETSUnionType>(this, std::move(newConstituentTypes));
172 }
173
CreateETSTypeAliasType(util::StringView name,const ir::AstNode * declNode,bool isRecursive)174 ETSTypeAliasType *ETSChecker::CreateETSTypeAliasType(util::StringView name, const ir::AstNode *declNode,
175 bool isRecursive)
176 {
177 return ProgramAllocator()->New<ETSTypeAliasType>(this, name, declNode, isRecursive);
178 }
179
CreateETSArrowType(Signature * signature)180 ETSFunctionType *ETSChecker::CreateETSArrowType(Signature *signature)
181 {
182 return ProgramAllocator()->New<ETSFunctionType>(this, signature);
183 }
184
CreateETSMethodType(util::StringView name,ArenaVector<Signature * > && signatures)185 ETSFunctionType *ETSChecker::CreateETSMethodType(util::StringView name, ArenaVector<Signature *> &&signatures)
186 {
187 return ProgramAllocator()->New<ETSFunctionType>(this, name, std::move(signatures));
188 }
189
CreateETSDynamicArrowType(Signature * signature,Language lang)190 ETSFunctionType *ETSChecker::CreateETSDynamicArrowType(Signature *signature, Language lang)
191 {
192 return ProgramAllocator()->New<ETSDynamicFunctionType>(this, signature, lang);
193 }
194
CreateETSDynamicMethodType(util::StringView name,ArenaVector<Signature * > && signatures,Language lang)195 ETSFunctionType *ETSChecker::CreateETSDynamicMethodType(util::StringView name, ArenaVector<Signature *> &&signatures,
196 Language lang)
197 {
198 return ProgramAllocator()->New<ETSDynamicFunctionType>(this, name, std::move(signatures), lang);
199 }
200
ConvertToSignatureFlags(ir::ModifierFlags inModifiers,ir::ScriptFunctionFlags inFunctionFlags)201 static SignatureFlags ConvertToSignatureFlags(ir::ModifierFlags inModifiers, ir::ScriptFunctionFlags inFunctionFlags)
202 {
203 SignatureFlags outFlags = SignatureFlags::NO_OPTS;
204
205 const auto convertModifier = [&outFlags, inModifiers](ir::ModifierFlags astFlag, SignatureFlags sigFlag) {
206 if ((inModifiers & astFlag) != 0U) {
207 outFlags |= sigFlag;
208 }
209 };
210 const auto convertFlag = [&outFlags, inFunctionFlags](ir::ScriptFunctionFlags funcFlag, SignatureFlags sigFlag) {
211 if ((inFunctionFlags & funcFlag) != 0U) {
212 outFlags |= sigFlag;
213 }
214 };
215
216 convertFlag(ir::ScriptFunctionFlags::THROWS, SignatureFlags::THROWS);
217 convertFlag(ir::ScriptFunctionFlags::RETHROWS, SignatureFlags::RETHROWS);
218
219 convertFlag(ir::ScriptFunctionFlags::CONSTRUCTOR, SignatureFlags::CONSTRUCTOR);
220 convertFlag(ir::ScriptFunctionFlags::SETTER, SignatureFlags::SETTER);
221 convertFlag(ir::ScriptFunctionFlags::GETTER, SignatureFlags::GETTER);
222
223 convertModifier(ir::ModifierFlags::ABSTRACT, SignatureFlags::ABSTRACT);
224 convertModifier(ir::ModifierFlags::PROTECTED, SignatureFlags::PROTECTED);
225 convertModifier(ir::ModifierFlags::FINAL, SignatureFlags::FINAL);
226 convertModifier(ir::ModifierFlags::STATIC, SignatureFlags::STATIC);
227 convertModifier(ir::ModifierFlags::PUBLIC, SignatureFlags::PUBLIC);
228 convertModifier(ir::ModifierFlags::PRIVATE, SignatureFlags::PRIVATE);
229 convertModifier(ir::ModifierFlags::INTERNAL, SignatureFlags::INTERNAL);
230
231 return outFlags;
232 }
233
CreateSignature(SignatureInfo * info,Type * returnType,ir::ScriptFunction * func)234 Signature *ETSChecker::CreateSignature(SignatureInfo *info, Type *returnType, ir::ScriptFunction *func)
235 {
236 if (info == nullptr) { // #23134
237 ES2PANDA_ASSERT(IsAnyError());
238 return nullptr;
239 }
240 auto signature = ProgramAllocator()->New<Signature>(info, returnType, func);
241 auto convertedFlag = ConvertToSignatureFlags(func->Modifiers(), func->Flags());
242 ES2PANDA_ASSERT(signature != nullptr);
243 func->HasReceiver() ? signature->AddSignatureFlag(SignatureFlags::EXTENSION_FUNCTION | convertedFlag)
244 : signature->AddSignatureFlag(convertedFlag);
245 return signature;
246 }
247
CreateSignature(SignatureInfo * info,Type * returnType,ir::ScriptFunctionFlags sff,bool hasReceiver)248 Signature *ETSChecker::CreateSignature(SignatureInfo *info, Type *returnType, ir::ScriptFunctionFlags sff,
249 bool hasReceiver)
250 {
251 if (info == nullptr) { // #23134
252 ES2PANDA_ASSERT(IsAnyError());
253 return nullptr;
254 }
255 auto signature = ProgramAllocator()->New<Signature>(info, returnType, nullptr);
256 ES2PANDA_ASSERT(signature != nullptr);
257 signature->AddSignatureFlag(ConvertToSignatureFlags(ir::ModifierFlags::NONE, sff));
258 // synthetic arrow type signature flags
259 auto extraFlags = SignatureFlags::ABSTRACT | SignatureFlags::CALL | SignatureFlags::PUBLIC;
260 hasReceiver ? signature->AddSignatureFlag(SignatureFlags::EXTENSION_FUNCTION | extraFlags)
261 : signature->AddSignatureFlag(extraFlags);
262 return signature;
263 }
264
CreateSignatureInfo()265 SignatureInfo *ETSChecker::CreateSignatureInfo()
266 {
267 return ProgramAllocator()->New<SignatureInfo>(ProgramAllocator());
268 }
269
CreateTypeParameter()270 ETSTypeParameter *ETSChecker::CreateTypeParameter()
271 {
272 return ProgramAllocator()->New<ETSTypeParameter>();
273 }
274
CreateETSExtensionFuncHelperType(ETSFunctionType * classMethodType,ETSFunctionType * extensionFunctionType)275 ETSExtensionFuncHelperType *ETSChecker::CreateETSExtensionFuncHelperType(ETSFunctionType *classMethodType,
276 ETSFunctionType *extensionFunctionType)
277 {
278 return ProgramAllocator()->New<ETSExtensionFuncHelperType>(classMethodType, extensionFunctionType);
279 }
280
GetObjectTypeDeclNames(ir::AstNode * node)281 static std::pair<util::StringView, util::StringView> GetObjectTypeDeclNames(ir::AstNode *node)
282 {
283 if (node->IsClassDefinition()) {
284 return {node->AsClassDefinition()->Ident()->Name(), node->AsClassDefinition()->InternalName()};
285 }
286 if (node->IsTSInterfaceDeclaration()) {
287 return {node->AsTSInterfaceDeclaration()->Id()->Name(), node->AsTSInterfaceDeclaration()->InternalName()};
288 }
289 return {node->AsAnnotationDeclaration()->GetBaseName()->Name(), node->AsAnnotationDeclaration()->InternalName()};
290 }
291
292 // CC-OFFNXT(huge_method[C++], G.FUN.01-CPP) solid logic, big switch case
InitializeGlobalBuiltinObjectType(ETSChecker * checker,GlobalTypeId globalId,ir::AstNode * declNode,ETSObjectFlags flags)293 static ETSObjectType *InitializeGlobalBuiltinObjectType(ETSChecker *checker, GlobalTypeId globalId,
294 ir::AstNode *declNode, ETSObjectFlags flags)
295 {
296 auto const create = [checker, declNode, flags](ETSObjectFlags addFlags = ETSObjectFlags::NO_OPTS) {
297 return checker->CreateETSObjectType(declNode, flags | addFlags);
298 };
299
300 auto const setType = [checker](GlobalTypeId slotId, Type *type) {
301 auto &slot = checker->GetGlobalTypesHolder()->GlobalTypes()[helpers::ToUnderlying(slotId)];
302 if (slot == nullptr) {
303 slot = type;
304 }
305 return slot;
306 };
307
308 auto *const programAllocator = checker->ProgramAllocator();
309
310 switch (globalId) {
311 case GlobalTypeId::ETS_OBJECT_BUILTIN: {
312 auto *objType = setType(GlobalTypeId::ETS_OBJECT_BUILTIN, create())->AsETSObjectType();
313 auto null = checker->GlobalETSNullType();
314 auto undef = checker->GlobalETSUndefinedType();
315 setType(GlobalTypeId::ETS_UNION_UNDEFINED_NULL_OBJECT, checker->CreateETSUnionType({objType, null, undef}));
316 setType(GlobalTypeId::ETS_UNION_UNDEFINED_NULL, checker->CreateETSUnionType({null, undef}));
317 return objType;
318 }
319 case GlobalTypeId::ETS_STRING_BUILTIN: {
320 auto *stringObj = setType(GlobalTypeId::ETS_STRING_BUILTIN,
321 create(ETSObjectFlags::BUILTIN_STRING | ETSObjectFlags::STRING))
322 ->AsETSObjectType();
323 setType(GlobalTypeId::ETS_STRING,
324 programAllocator->New<ETSStringType>(programAllocator, stringObj, checker->Relation()));
325 return stringObj;
326 }
327 case GlobalTypeId::ETS_BIG_INT_BUILTIN: {
328 auto *bigIntObj =
329 setType(GlobalTypeId::ETS_BIG_INT_BUILTIN, create(ETSObjectFlags::BUILTIN_BIGINT))->AsETSObjectType();
330 setType(GlobalTypeId::ETS_BIG_INT, programAllocator->New<ETSBigIntType>(programAllocator, bigIntObj));
331 return bigIntObj;
332 }
333 case GlobalTypeId::ETS_ARRAY_BUILTIN: {
334 if (declNode->AsClassDefinition()->InternalName().Utf8() != "escompat.Array") {
335 return checker->CreateETSObjectType(declNode, flags);
336 }
337 auto *arrayObj =
338 setType(GlobalTypeId::ETS_ARRAY_BUILTIN, create(ETSObjectFlags::BUILTIN_ARRAY))->AsETSObjectType();
339 setType(GlobalTypeId::ETS_ARRAY, programAllocator->New<ETSResizableArrayType>(programAllocator, arrayObj));
340 return arrayObj;
341 }
342 case GlobalTypeId::ETS_BOOLEAN_BUILTIN:
343 return create(ETSObjectFlags::BUILTIN_BOOLEAN);
344 case GlobalTypeId::ETS_BYTE_BUILTIN:
345 return create(ETSObjectFlags::BUILTIN_BYTE);
346 case GlobalTypeId::ETS_CHAR_BUILTIN:
347 return create(ETSObjectFlags::BUILTIN_CHAR);
348 case GlobalTypeId::ETS_SHORT_BUILTIN:
349 return create(ETSObjectFlags::BUILTIN_SHORT);
350 case GlobalTypeId::ETS_INT_BUILTIN:
351 return create(ETSObjectFlags::BUILTIN_INT);
352 case GlobalTypeId::ETS_LONG_BUILTIN:
353 return create(ETSObjectFlags::BUILTIN_LONG);
354 case GlobalTypeId::ETS_FLOAT_BUILTIN:
355 return create(ETSObjectFlags::BUILTIN_FLOAT);
356 case GlobalTypeId::ETS_DOUBLE_BUILTIN:
357 return create(ETSObjectFlags::BUILTIN_DOUBLE);
358 default:
359 return create();
360 }
361 }
362
CreateETSObjectTypeOrBuiltin(ir::AstNode * declNode,ETSObjectFlags flags)363 ETSObjectType *ETSChecker::CreateETSObjectTypeOrBuiltin(ir::AstNode *declNode, ETSObjectFlags flags)
364 {
365 if (LIKELY(HasStatus(CheckerStatus::BUILTINS_INITIALIZED))) {
366 return CreateETSObjectType(declNode, flags);
367 }
368 auto const globalId = GetGlobalTypesHolder()->NameToId(GetObjectTypeDeclNames(declNode).first);
369 if (!globalId.has_value()) {
370 return CreateETSObjectType(declNode, flags);
371 }
372 return InitializeGlobalBuiltinObjectType(this, globalId.value(), declNode, flags);
373 }
374
CheckForDynamicLang(ir::AstNode * declNode,util::StringView assemblerName)375 std::tuple<Language, bool> ETSChecker::CheckForDynamicLang(ir::AstNode *declNode, util::StringView assemblerName)
376 {
377 Language lang(Language::Id::ETS);
378 bool hasDecl = false;
379
380 if (declNode->IsClassDefinition()) {
381 auto *clsDef = declNode->AsClassDefinition();
382 lang = clsDef->Language();
383 hasDecl = clsDef->IsDeclare();
384 }
385
386 if (declNode->IsTSInterfaceDeclaration()) {
387 auto *ifaceDecl = declNode->AsTSInterfaceDeclaration();
388 lang = ifaceDecl->Language();
389 hasDecl = ifaceDecl->IsDeclare();
390 }
391
392 auto res = compiler::Signatures::Dynamic::LanguageFromType(assemblerName.Utf8());
393 if (res) {
394 lang = *res;
395 }
396
397 return std::make_tuple(lang, hasDecl);
398 }
399
CreateETSObjectType(ir::AstNode * declNode,ETSObjectFlags flags)400 ETSObjectType *ETSChecker::CreateETSObjectType(ir::AstNode *declNode, ETSObjectFlags flags)
401 {
402 auto const [name, internalName] = GetObjectTypeDeclNames(declNode);
403
404 if (declNode->IsClassDefinition() && (declNode->AsClassDefinition()->IsEnumTransformed())) {
405 if (declNode->AsClassDefinition()->IsIntEnumTransformed()) {
406 return ProgramAllocator()->New<ETSIntEnumType>(ProgramAllocator(), name, internalName, declNode,
407 Relation());
408 }
409 ES2PANDA_ASSERT(declNode->AsClassDefinition()->IsStringEnumTransformed());
410 return ProgramAllocator()->New<ETSStringEnumType>(ProgramAllocator(), name, internalName, declNode, Relation());
411 }
412
413 if (internalName == compiler::Signatures::BUILTIN_ARRAY) {
414 return ProgramAllocator()->New<ETSResizableArrayType>(ProgramAllocator(), name,
415 std::make_tuple(declNode, flags, Relation()));
416 }
417
418 if (auto [lang, hasDecl] = CheckForDynamicLang(declNode, internalName); lang.IsDynamic()) {
419 return ProgramAllocator()->New<ETSDynamicType>(ProgramAllocator(), std::make_tuple(name, internalName, lang),
420 std::make_tuple(declNode, flags, Relation()), hasDecl);
421 }
422
423 return ProgramAllocator()->New<ETSObjectType>(ProgramAllocator(), name, internalName,
424 std::make_tuple(declNode, flags, Relation()));
425 }
426
CreateBuiltinArraySignatureInfo(const ETSArrayType * arrayType,size_t dim)427 std::tuple<util::StringView, SignatureInfo *> ETSChecker::CreateBuiltinArraySignatureInfo(const ETSArrayType *arrayType,
428 size_t dim)
429 {
430 std::stringstream ss;
431 arrayType->ToAssemblerTypeWithRank(ss);
432 ss << compiler::Signatures::METHOD_SEPARATOR << compiler::Signatures::CTOR << compiler::Signatures::MANGLE_BEGIN;
433 arrayType->ToAssemblerTypeWithRank(ss);
434
435 auto *info = CreateSignatureInfo();
436 ES2PANDA_ASSERT(info != nullptr);
437 info->minArgCount = dim;
438
439 for (size_t i = 0; i < dim; i++) {
440 util::UString param(std::to_string(i), ProgramAllocator());
441 auto *paramVar =
442 varbinder::Scope::CreateVar(ProgramAllocator(), param.View(), varbinder::VariableFlags::NONE, nullptr);
443 ES2PANDA_ASSERT(paramVar != nullptr);
444 paramVar->SetTsType(GlobalIntType());
445
446 info->params.push_back(paramVar);
447
448 ss << compiler::Signatures::MANGLE_SEPARATOR << compiler::Signatures::PRIMITIVE_INT;
449 }
450
451 ss << compiler::Signatures::MANGLE_SEPARATOR << compiler::Signatures::PRIMITIVE_VOID
452 << compiler::Signatures::MANGLE_SEPARATOR;
453 auto internalName = util::UString(ss.str(), ProgramAllocator()).View();
454
455 return {internalName, info};
456 }
457
CreateBuiltinArraySignature(const ETSArrayType * arrayType,size_t dim)458 Signature *ETSChecker::CreateBuiltinArraySignature(const ETSArrayType *arrayType, size_t dim)
459 {
460 auto res = globalArraySignatures_.find(arrayType);
461 if (res != globalArraySignatures_.end()) {
462 return res->second;
463 }
464
465 auto [internalName, info] = CreateBuiltinArraySignatureInfo(arrayType, dim);
466 auto *signature = CreateSignature(info, GlobalVoidType(), ir::ScriptFunctionFlags::NONE, false);
467 ES2PANDA_ASSERT(signature != nullptr);
468 signature->SetInternalName(internalName);
469 globalArraySignatures_.insert({arrayType, signature});
470
471 return signature;
472 }
473
CreatePromiseOf(Type * type)474 ETSObjectType *ETSChecker::CreatePromiseOf(Type *type)
475 {
476 ETSObjectType *const promiseType = GlobalBuiltinPromiseType();
477 ES2PANDA_ASSERT(promiseType->TypeArguments().size() == 1U);
478
479 Substitution *substitution = NewSubstitution();
480 ES2PANDA_ASSERT(promiseType != nullptr);
481 EmplaceSubstituted(substitution, promiseType->TypeArguments()[0]->AsETSTypeParameter()->GetOriginal(), type);
482
483 return promiseType->Substitute(Relation(), substitution);
484 }
485
IsInValidKeyofTypeNode(ir::AstNode * node)486 static bool IsInValidKeyofTypeNode(ir::AstNode *node)
487 {
488 return (node->Modifiers() & ir::ModifierFlags::PRIVATE) != 0 ||
489 (node->Modifiers() & ir::ModifierFlags::PROTECTED) != 0;
490 }
491
ProcessTypeMembers(ETSObjectType * type,ArenaVector<Type * > & literals)492 void ETSChecker::ProcessTypeMembers(ETSObjectType *type, ArenaVector<Type *> &literals)
493 {
494 if (type == GlobalETSObjectType()) {
495 return;
496 }
497
498 for (auto *method : type->Methods()) {
499 auto *methodDef = method->Declaration()->Node()->AsMethodDefinition();
500 for (auto *overload : methodDef->Overloads()) {
501 if (IsInValidKeyofTypeNode(overload)) {
502 continue;
503 }
504 literals.push_back(CreateETSStringLiteralType(overload->Key()->Variable()->Name()));
505 }
506 if (!IsInValidKeyofTypeNode(method->Declaration()->Node())) {
507 literals.push_back(CreateETSStringLiteralType(method->Name()));
508 }
509 }
510
511 for (auto *field : type->Fields()) {
512 if (IsInValidKeyofTypeNode(field->Declaration()->Node())) {
513 continue;
514 }
515 literals.push_back(CreateETSStringLiteralType(field->Name()));
516 }
517 }
518
CreateUnionFromKeyofType(ETSObjectType * const type)519 Type *ETSChecker::CreateUnionFromKeyofType(ETSObjectType *const type)
520 {
521 ArenaVector<Type *> stringLiterals(ProgramAllocator()->Adapter());
522 std::deque<ETSObjectType *> superTypes;
523 superTypes.push_back(type);
524 auto enqueueSupers = [&](ETSObjectType *currentType) {
525 if (currentType->SuperType() != nullptr) {
526 superTypes.push_back(currentType->SuperType());
527 }
528 for (auto interface : currentType->Interfaces()) {
529 superTypes.push_back(interface);
530 }
531 };
532
533 while (!superTypes.empty()) {
534 auto *currentType = superTypes.front();
535 superTypes.pop_front();
536
537 ProcessTypeMembers(currentType, stringLiterals);
538 enqueueSupers(currentType);
539 }
540
541 return stringLiterals.empty() ? GlobalETSNeverType() : CreateETSUnionType(std::move(stringLiterals));
542 }
543
CreateETSAsyncFuncReturnTypeFromPromiseType(ETSObjectType * promiseType)544 ETSAsyncFuncReturnType *ETSChecker::CreateETSAsyncFuncReturnTypeFromPromiseType(ETSObjectType *promiseType)
545 {
546 return ProgramAllocator()->New<ETSAsyncFuncReturnType>(ProgramAllocator(), Relation(), promiseType);
547 }
548
CreateETSAsyncFuncReturnTypeFromBaseType(Type * baseType)549 ETSAsyncFuncReturnType *ETSChecker::CreateETSAsyncFuncReturnTypeFromBaseType(Type *baseType)
550 {
551 auto const promiseType = CreatePromiseOf(MaybeBoxType(baseType));
552 return ProgramAllocator()->New<ETSAsyncFuncReturnType>(ProgramAllocator(), Relation(), promiseType);
553 }
554
555 } // namespace ark::es2panda::checker
556