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