13af6ab5fSopenharmony_ci/** 23af6ab5fSopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License. 53af6ab5fSopenharmony_ci * You may obtain a copy of the License at 63af6ab5fSopenharmony_ci * 73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 83af6ab5fSopenharmony_ci * 93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and 133af6ab5fSopenharmony_ci * limitations under the License. 143af6ab5fSopenharmony_ci */ 153af6ab5fSopenharmony_ci 163af6ab5fSopenharmony_ci#include "ir/expressions/literals/bigIntLiteral.h" 173af6ab5fSopenharmony_ci#include "ir/expressions/literals/numberLiteral.h" 183af6ab5fSopenharmony_ci#include "ir/expressions/literals/stringLiteral.h" 193af6ab5fSopenharmony_ci#include "ir/expressions/functionExpression.h" 203af6ab5fSopenharmony_ci#include "ir/expressions/memberExpression.h" 213af6ab5fSopenharmony_ci#include "ir/expressions/identifier.h" 223af6ab5fSopenharmony_ci#include "ir/base/property.h" 233af6ab5fSopenharmony_ci#include "ir/base/scriptFunction.h" 243af6ab5fSopenharmony_ci#include "ir/base/spreadElement.h" 253af6ab5fSopenharmony_ci#include "ir/base/tsIndexSignature.h" 263af6ab5fSopenharmony_ci#include "ir/base/tsMethodSignature.h" 273af6ab5fSopenharmony_ci#include "ir/base/tsPropertySignature.h" 283af6ab5fSopenharmony_ci#include "ir/base/tsSignatureDeclaration.h" 293af6ab5fSopenharmony_ci#include "ir/ts/tsTypeLiteral.h" 303af6ab5fSopenharmony_ci#include "ir/ts/tsInterfaceDeclaration.h" 313af6ab5fSopenharmony_ci#include "ir/ts/tsInterfaceHeritage.h" 323af6ab5fSopenharmony_ci#include "ir/ts/tsInterfaceBody.h" 333af6ab5fSopenharmony_ci#include "util/helpers.h" 343af6ab5fSopenharmony_ci#include "varbinder/variable.h" 353af6ab5fSopenharmony_ci#include "varbinder/scope.h" 363af6ab5fSopenharmony_ci 373af6ab5fSopenharmony_ci#include "checker/TSchecker.h" 383af6ab5fSopenharmony_ci#include "checker/types/ts/indexInfo.h" 393af6ab5fSopenharmony_ci 403af6ab5fSopenharmony_cinamespace ark::es2panda::checker { 413af6ab5fSopenharmony_civoid TSChecker::CheckIndexConstraints(Type *type) 423af6ab5fSopenharmony_ci{ 433af6ab5fSopenharmony_ci if (!type->IsObjectType()) { 443af6ab5fSopenharmony_ci return; 453af6ab5fSopenharmony_ci } 463af6ab5fSopenharmony_ci 473af6ab5fSopenharmony_ci ObjectType *objType = type->AsObjectType(); 483af6ab5fSopenharmony_ci ResolveStructuredTypeMembers(objType); 493af6ab5fSopenharmony_ci 503af6ab5fSopenharmony_ci IndexInfo *numberInfo = objType->NumberIndexInfo(); 513af6ab5fSopenharmony_ci IndexInfo *stringInfo = objType->StringIndexInfo(); 523af6ab5fSopenharmony_ci const ArenaVector<varbinder::LocalVariable *> &properties = objType->Properties(); 533af6ab5fSopenharmony_ci 543af6ab5fSopenharmony_ci if (numberInfo != nullptr) { 553af6ab5fSopenharmony_ci for (auto *it : properties) { 563af6ab5fSopenharmony_ci if (it->HasFlag(varbinder::VariableFlags::NUMERIC_NAME)) { 573af6ab5fSopenharmony_ci Type *propType = GetTypeOfVariable(it); 583af6ab5fSopenharmony_ci IsTypeAssignableTo(propType, numberInfo->GetType(), 593af6ab5fSopenharmony_ci {"Property '", it->Name(), "' of type '", propType, 603af6ab5fSopenharmony_ci "' is not assignable to numeric index type '", numberInfo->GetType(), "'."}, 613af6ab5fSopenharmony_ci it->Declaration()->Node()->Start()); 623af6ab5fSopenharmony_ci } 633af6ab5fSopenharmony_ci } 643af6ab5fSopenharmony_ci } 653af6ab5fSopenharmony_ci 663af6ab5fSopenharmony_ci if (stringInfo != nullptr) { 673af6ab5fSopenharmony_ci for (auto *it : properties) { 683af6ab5fSopenharmony_ci Type *propType = GetTypeOfVariable(it); 693af6ab5fSopenharmony_ci IsTypeAssignableTo(propType, stringInfo->GetType(), 703af6ab5fSopenharmony_ci {"Property '", it->Name(), "' of type '", propType, 713af6ab5fSopenharmony_ci "' is not assignable to string index type '", stringInfo->GetType(), "'."}, 723af6ab5fSopenharmony_ci it->Declaration()->Node()->Start()); 733af6ab5fSopenharmony_ci } 743af6ab5fSopenharmony_ci 753af6ab5fSopenharmony_ci if (numberInfo != nullptr && !IsTypeAssignableTo(numberInfo->GetType(), stringInfo->GetType())) { 763af6ab5fSopenharmony_ci ThrowTypeError({"Number index info type ", numberInfo->GetType(), 773af6ab5fSopenharmony_ci " is not assignable to string index info type ", stringInfo->GetType(), "."}, 783af6ab5fSopenharmony_ci numberInfo->Pos()); 793af6ab5fSopenharmony_ci } 803af6ab5fSopenharmony_ci } 813af6ab5fSopenharmony_ci} 823af6ab5fSopenharmony_ci 833af6ab5fSopenharmony_civoid TSChecker::ResolveStructuredTypeMembers(Type *type) 843af6ab5fSopenharmony_ci{ 853af6ab5fSopenharmony_ci if (type->IsObjectType()) { 863af6ab5fSopenharmony_ci ObjectType *objType = type->AsObjectType(); 873af6ab5fSopenharmony_ci 883af6ab5fSopenharmony_ci if (objType->IsObjectLiteralType()) { 893af6ab5fSopenharmony_ci ResolveObjectTypeMembers(objType); 903af6ab5fSopenharmony_ci return; 913af6ab5fSopenharmony_ci } 923af6ab5fSopenharmony_ci 933af6ab5fSopenharmony_ci if (objType->IsInterfaceType()) { 943af6ab5fSopenharmony_ci ResolveInterfaceOrClassTypeMembers(objType->AsInterfaceType()); 953af6ab5fSopenharmony_ci return; 963af6ab5fSopenharmony_ci } 973af6ab5fSopenharmony_ci } 983af6ab5fSopenharmony_ci 993af6ab5fSopenharmony_ci if (type->IsUnionType()) { 1003af6ab5fSopenharmony_ci ResolveUnionTypeMembers(type->AsUnionType()); 1013af6ab5fSopenharmony_ci return; 1023af6ab5fSopenharmony_ci } 1033af6ab5fSopenharmony_ci} 1043af6ab5fSopenharmony_ci 1053af6ab5fSopenharmony_civoid TSChecker::ResolveUnionTypeMembers(UnionType *type) 1063af6ab5fSopenharmony_ci{ 1073af6ab5fSopenharmony_ci if (type->MergedObjectType() != nullptr) { 1083af6ab5fSopenharmony_ci return; 1093af6ab5fSopenharmony_ci } 1103af6ab5fSopenharmony_ci 1113af6ab5fSopenharmony_ci ObjectDescriptor *desc = Allocator()->New<ObjectDescriptor>(Allocator()); 1123af6ab5fSopenharmony_ci ArenaVector<Type *> stringInfoTypes(Allocator()->Adapter()); 1133af6ab5fSopenharmony_ci ArenaVector<Type *> numberInfoTypes(Allocator()->Adapter()); 1143af6ab5fSopenharmony_ci ArenaVector<Signature *> callSignatures(Allocator()->Adapter()); 1153af6ab5fSopenharmony_ci ArenaVector<Signature *> constructSignatures(Allocator()->Adapter()); 1163af6ab5fSopenharmony_ci 1173af6ab5fSopenharmony_ci for (auto *it : type->AsUnionType()->ConstituentTypes()) { 1183af6ab5fSopenharmony_ci if (!it->IsObjectType()) { 1193af6ab5fSopenharmony_ci continue; 1203af6ab5fSopenharmony_ci } 1213af6ab5fSopenharmony_ci 1223af6ab5fSopenharmony_ci ObjectType *objType = it->AsObjectType(); 1233af6ab5fSopenharmony_ci ResolveObjectTypeMembers(objType); 1243af6ab5fSopenharmony_ci 1253af6ab5fSopenharmony_ci if (!objType->CallSignatures().empty()) { 1263af6ab5fSopenharmony_ci for (auto *signature : objType->CallSignatures()) { 1273af6ab5fSopenharmony_ci callSignatures.push_back(signature); 1283af6ab5fSopenharmony_ci } 1293af6ab5fSopenharmony_ci } 1303af6ab5fSopenharmony_ci 1313af6ab5fSopenharmony_ci if (!objType->ConstructSignatures().empty()) { 1323af6ab5fSopenharmony_ci for (auto *signature : objType->ConstructSignatures()) { 1333af6ab5fSopenharmony_ci constructSignatures.push_back(signature); 1343af6ab5fSopenharmony_ci } 1353af6ab5fSopenharmony_ci } 1363af6ab5fSopenharmony_ci 1373af6ab5fSopenharmony_ci if (objType->StringIndexInfo() != nullptr) { 1383af6ab5fSopenharmony_ci stringInfoTypes.push_back(objType->StringIndexInfo()->GetType()); 1393af6ab5fSopenharmony_ci } 1403af6ab5fSopenharmony_ci 1413af6ab5fSopenharmony_ci if (objType->NumberIndexInfo() != nullptr) { 1423af6ab5fSopenharmony_ci numberInfoTypes.push_back(objType->NumberIndexInfo()->GetType()); 1433af6ab5fSopenharmony_ci } 1443af6ab5fSopenharmony_ci } 1453af6ab5fSopenharmony_ci 1463af6ab5fSopenharmony_ci desc->callSignatures = callSignatures; 1473af6ab5fSopenharmony_ci desc->constructSignatures = constructSignatures; 1483af6ab5fSopenharmony_ci 1493af6ab5fSopenharmony_ci if (!stringInfoTypes.empty()) { 1503af6ab5fSopenharmony_ci desc->stringIndexInfo = Allocator()->New<IndexInfo>(CreateUnionType(std::move(stringInfoTypes)), "x", false); 1513af6ab5fSopenharmony_ci } 1523af6ab5fSopenharmony_ci 1533af6ab5fSopenharmony_ci if (!numberInfoTypes.empty()) { 1543af6ab5fSopenharmony_ci desc->numberIndexInfo = Allocator()->New<IndexInfo>(CreateUnionType(std::move(numberInfoTypes)), "x", false); 1553af6ab5fSopenharmony_ci } 1563af6ab5fSopenharmony_ci 1573af6ab5fSopenharmony_ci ObjectType *mergedType = Allocator()->New<ObjectLiteralType>(desc); 1583af6ab5fSopenharmony_ci mergedType->AddObjectFlag(ObjectFlags::RESOLVED_MEMBERS); 1593af6ab5fSopenharmony_ci type->SetMergedObjectType(mergedType); 1603af6ab5fSopenharmony_ci} 1613af6ab5fSopenharmony_ci 1623af6ab5fSopenharmony_civoid TSChecker::ResolveInterfaceOrClassTypeMembers(InterfaceType *type) 1633af6ab5fSopenharmony_ci{ 1643af6ab5fSopenharmony_ci if (type->HasObjectFlag(ObjectFlags::RESOLVED_MEMBERS)) { 1653af6ab5fSopenharmony_ci return; 1663af6ab5fSopenharmony_ci } 1673af6ab5fSopenharmony_ci 1683af6ab5fSopenharmony_ci ResolveDeclaredMembers(type); 1693af6ab5fSopenharmony_ci GetBaseTypes(type); 1703af6ab5fSopenharmony_ci 1713af6ab5fSopenharmony_ci type->AddObjectFlag(ObjectFlags::RESOLVED_MEMBERS); 1723af6ab5fSopenharmony_ci} 1733af6ab5fSopenharmony_ci 1743af6ab5fSopenharmony_civoid TSChecker::ResolveObjectTypeMembers(ObjectType *type) 1753af6ab5fSopenharmony_ci{ 1763af6ab5fSopenharmony_ci if (!type->IsObjectLiteralType() || type->HasObjectFlag(ObjectFlags::RESOLVED_MEMBERS)) { 1773af6ab5fSopenharmony_ci return; 1783af6ab5fSopenharmony_ci } 1793af6ab5fSopenharmony_ci 1803af6ab5fSopenharmony_ci ASSERT(type->Variable() && type->Variable()->Declaration()->Node()->IsTSTypeLiteral()); 1813af6ab5fSopenharmony_ci auto *typeLiteral = type->Variable()->Declaration()->Node()->AsTSTypeLiteral(); 1823af6ab5fSopenharmony_ci ArenaVector<ir::TSSignatureDeclaration *> signatureDeclarations(Allocator()->Adapter()); 1833af6ab5fSopenharmony_ci ArenaVector<ir::TSIndexSignature *> indexDeclarations(Allocator()->Adapter()); 1843af6ab5fSopenharmony_ci 1853af6ab5fSopenharmony_ci for (auto *it : typeLiteral->Members()) { 1863af6ab5fSopenharmony_ci ResolvePropertiesOfObjectType(type, it, signatureDeclarations, indexDeclarations, false); 1873af6ab5fSopenharmony_ci } 1883af6ab5fSopenharmony_ci 1893af6ab5fSopenharmony_ci type->AddObjectFlag(ObjectFlags::RESOLVED_MEMBERS); 1903af6ab5fSopenharmony_ci 1913af6ab5fSopenharmony_ci ResolveSignaturesOfObjectType(type, signatureDeclarations); 1923af6ab5fSopenharmony_ci ResolveIndexInfosOfObjectType(type, indexDeclarations); 1933af6ab5fSopenharmony_ci} 1943af6ab5fSopenharmony_ci 1953af6ab5fSopenharmony_civoid TSChecker::ResolvePropertiesOfObjectType(ObjectType *type, ir::AstNode *member, 1963af6ab5fSopenharmony_ci ArenaVector<ir::TSSignatureDeclaration *> &signatureDeclarations, 1973af6ab5fSopenharmony_ci ArenaVector<ir::TSIndexSignature *> &indexDeclarations, bool isInterface) 1983af6ab5fSopenharmony_ci{ 1993af6ab5fSopenharmony_ci if (member->IsTSPropertySignature()) { 2003af6ab5fSopenharmony_ci varbinder::Variable *prop = member->AsTSPropertySignature()->Variable(); 2013af6ab5fSopenharmony_ci 2023af6ab5fSopenharmony_ci if (!isInterface || 2033af6ab5fSopenharmony_ci ValidateInterfaceMemberRedeclaration(type, prop, member->AsTSPropertySignature()->Key()->Start())) { 2043af6ab5fSopenharmony_ci type->AddProperty(prop->AsLocalVariable()); 2053af6ab5fSopenharmony_ci } 2063af6ab5fSopenharmony_ci 2073af6ab5fSopenharmony_ci return; 2083af6ab5fSopenharmony_ci } 2093af6ab5fSopenharmony_ci 2103af6ab5fSopenharmony_ci if (member->IsTSMethodSignature()) { 2113af6ab5fSopenharmony_ci varbinder::Variable *method = member->AsTSMethodSignature()->Variable(); 2123af6ab5fSopenharmony_ci 2133af6ab5fSopenharmony_ci if (!isInterface || 2143af6ab5fSopenharmony_ci ValidateInterfaceMemberRedeclaration(type, method, member->AsTSMethodSignature()->Key()->Start())) { 2153af6ab5fSopenharmony_ci type->AddProperty(method->AsLocalVariable()); 2163af6ab5fSopenharmony_ci } 2173af6ab5fSopenharmony_ci 2183af6ab5fSopenharmony_ci return; 2193af6ab5fSopenharmony_ci } 2203af6ab5fSopenharmony_ci 2213af6ab5fSopenharmony_ci if (member->IsTSSignatureDeclaration()) { 2223af6ab5fSopenharmony_ci signatureDeclarations.push_back(member->AsTSSignatureDeclaration()); 2233af6ab5fSopenharmony_ci return; 2243af6ab5fSopenharmony_ci } 2253af6ab5fSopenharmony_ci 2263af6ab5fSopenharmony_ci ASSERT(member->IsTSIndexSignature()); 2273af6ab5fSopenharmony_ci indexDeclarations.push_back(member->AsTSIndexSignature()); 2283af6ab5fSopenharmony_ci} 2293af6ab5fSopenharmony_ci 2303af6ab5fSopenharmony_civoid TSChecker::ResolveSignaturesOfObjectType(ObjectType *type, 2313af6ab5fSopenharmony_ci ArenaVector<ir::TSSignatureDeclaration *> &signatureDeclarations) 2323af6ab5fSopenharmony_ci{ 2333af6ab5fSopenharmony_ci for (auto *it : signatureDeclarations) { 2343af6ab5fSopenharmony_ci Type *placeholderObj = it->Check(this); 2353af6ab5fSopenharmony_ci 2363af6ab5fSopenharmony_ci if (it->AsTSSignatureDeclaration()->Kind() == 2373af6ab5fSopenharmony_ci ir::TSSignatureDeclaration::TSSignatureDeclarationKind::CALL_SIGNATURE) { 2383af6ab5fSopenharmony_ci type->AddCallSignature(placeholderObj->AsObjectType()->CallSignatures()[0]); 2393af6ab5fSopenharmony_ci continue; 2403af6ab5fSopenharmony_ci } 2413af6ab5fSopenharmony_ci 2423af6ab5fSopenharmony_ci type->AddConstructSignature(placeholderObj->AsObjectType()->ConstructSignatures()[0]); 2433af6ab5fSopenharmony_ci } 2443af6ab5fSopenharmony_ci} 2453af6ab5fSopenharmony_civoid TSChecker::ResolveIndexInfosOfObjectType(ObjectType *type, ArenaVector<ir::TSIndexSignature *> &indexDeclarations) 2463af6ab5fSopenharmony_ci{ 2473af6ab5fSopenharmony_ci for (auto *it : indexDeclarations) { 2483af6ab5fSopenharmony_ci Type *placeholderObj = it->Check(this); 2493af6ab5fSopenharmony_ci 2503af6ab5fSopenharmony_ci if (it->AsTSIndexSignature()->Kind() == ir::TSIndexSignature::TSIndexSignatureKind::NUMBER) { 2513af6ab5fSopenharmony_ci IndexInfo *numberInfo = placeholderObj->AsObjectType()->NumberIndexInfo(); 2523af6ab5fSopenharmony_ci 2533af6ab5fSopenharmony_ci if (type->NumberIndexInfo() != nullptr) { 2543af6ab5fSopenharmony_ci ThrowTypeError("Duplicated index signature for type 'number'", it->Start()); 2553af6ab5fSopenharmony_ci } 2563af6ab5fSopenharmony_ci 2573af6ab5fSopenharmony_ci type->Desc()->numberIndexInfo = numberInfo; 2583af6ab5fSopenharmony_ci continue; 2593af6ab5fSopenharmony_ci } 2603af6ab5fSopenharmony_ci 2613af6ab5fSopenharmony_ci IndexInfo *stringInfo = placeholderObj->AsObjectType()->StringIndexInfo(); 2623af6ab5fSopenharmony_ci 2633af6ab5fSopenharmony_ci if (type->StringIndexInfo() != nullptr) { 2643af6ab5fSopenharmony_ci ThrowTypeError("Duplicated index signature for type 'string'", it->Start()); 2653af6ab5fSopenharmony_ci } 2663af6ab5fSopenharmony_ci 2673af6ab5fSopenharmony_ci type->Desc()->stringIndexInfo = stringInfo; 2683af6ab5fSopenharmony_ci } 2693af6ab5fSopenharmony_ci} 2703af6ab5fSopenharmony_ci 2713af6ab5fSopenharmony_civarbinder::Variable *TSChecker::GetPropertyOfType(Type *type, const util::StringView &name, bool getPartial, 2723af6ab5fSopenharmony_ci varbinder::VariableFlags propagateFlags) 2733af6ab5fSopenharmony_ci{ 2743af6ab5fSopenharmony_ci if (type->IsObjectType()) { 2753af6ab5fSopenharmony_ci ResolveObjectTypeMembers(type->AsObjectType()); 2763af6ab5fSopenharmony_ci return type->AsObjectType()->GetProperty(name, true); 2773af6ab5fSopenharmony_ci } 2783af6ab5fSopenharmony_ci 2793af6ab5fSopenharmony_ci if (type->IsUnionType()) { 2803af6ab5fSopenharmony_ci return GetPropertyOfUnionType(type->AsUnionType(), name, getPartial, propagateFlags); 2813af6ab5fSopenharmony_ci } 2823af6ab5fSopenharmony_ci 2833af6ab5fSopenharmony_ci return nullptr; 2843af6ab5fSopenharmony_ci} 2853af6ab5fSopenharmony_ci 2863af6ab5fSopenharmony_civarbinder::Variable *TSChecker::GetPropertyOfUnionType(UnionType *type, const util::StringView &name, bool getPartial, 2873af6ab5fSopenharmony_ci varbinder::VariableFlags propagateFlags) 2883af6ab5fSopenharmony_ci{ 2893af6ab5fSopenharmony_ci auto found = type->CachedSyntheticProperties().find(name); 2903af6ab5fSopenharmony_ci if (found != type->CachedSyntheticProperties().end()) { 2913af6ab5fSopenharmony_ci return found->second; 2923af6ab5fSopenharmony_ci } 2933af6ab5fSopenharmony_ci 2943af6ab5fSopenharmony_ci varbinder::VariableFlags flags = varbinder::VariableFlags::PROPERTY; 2953af6ab5fSopenharmony_ci ArenaVector<Type *> collectedTypes(Allocator()->Adapter()); 2963af6ab5fSopenharmony_ci 2973af6ab5fSopenharmony_ci for (auto *it : type->ConstituentTypes()) { 2983af6ab5fSopenharmony_ci varbinder::Variable *prop = GetPropertyOfType(it, name); 2993af6ab5fSopenharmony_ci 3003af6ab5fSopenharmony_ci if (prop == nullptr) { 3013af6ab5fSopenharmony_ci if (it->IsArrayType()) { 3023af6ab5fSopenharmony_ci collectedTypes.push_back(it->AsArrayType()->ElementType()); 3033af6ab5fSopenharmony_ci continue; 3043af6ab5fSopenharmony_ci } 3053af6ab5fSopenharmony_ci 3063af6ab5fSopenharmony_ci if (!it->IsObjectType() && getPartial) { 3073af6ab5fSopenharmony_ci continue; 3083af6ab5fSopenharmony_ci } 3093af6ab5fSopenharmony_ci if (!it->IsObjectType() && !getPartial) { 3103af6ab5fSopenharmony_ci return nullptr; 3113af6ab5fSopenharmony_ci } 3123af6ab5fSopenharmony_ci 3133af6ab5fSopenharmony_ci ObjectType *objType = it->AsObjectType(); 3143af6ab5fSopenharmony_ci 3153af6ab5fSopenharmony_ci if (objType->StringIndexInfo() == nullptr && getPartial) { 3163af6ab5fSopenharmony_ci continue; 3173af6ab5fSopenharmony_ci } 3183af6ab5fSopenharmony_ci if (objType->StringIndexInfo() == nullptr && !getPartial) { 3193af6ab5fSopenharmony_ci return nullptr; 3203af6ab5fSopenharmony_ci } 3213af6ab5fSopenharmony_ci 3223af6ab5fSopenharmony_ci collectedTypes.push_back(objType->StringIndexInfo()->GetType()); 3233af6ab5fSopenharmony_ci continue; 3243af6ab5fSopenharmony_ci } 3253af6ab5fSopenharmony_ci 3263af6ab5fSopenharmony_ci prop->AddFlag(propagateFlags); 3273af6ab5fSopenharmony_ci 3283af6ab5fSopenharmony_ci if (prop->HasFlag(varbinder::VariableFlags::OPTIONAL)) { 3293af6ab5fSopenharmony_ci flags |= varbinder::VariableFlags::OPTIONAL; 3303af6ab5fSopenharmony_ci } 3313af6ab5fSopenharmony_ci 3323af6ab5fSopenharmony_ci collectedTypes.push_back(GetTypeOfVariable(prop)); 3333af6ab5fSopenharmony_ci } 3343af6ab5fSopenharmony_ci 3353af6ab5fSopenharmony_ci if (collectedTypes.empty()) { 3363af6ab5fSopenharmony_ci return nullptr; 3373af6ab5fSopenharmony_ci } 3383af6ab5fSopenharmony_ci 3393af6ab5fSopenharmony_ci varbinder::Variable *syntheticProp = varbinder::Scope::CreateVar(Allocator(), name, flags, nullptr); 3403af6ab5fSopenharmony_ci syntheticProp->SetTsType(CreateUnionType(std::move(collectedTypes))); 3413af6ab5fSopenharmony_ci type->CachedSyntheticProperties().insert({name, syntheticProp}); 3423af6ab5fSopenharmony_ci return syntheticProp; 3433af6ab5fSopenharmony_ci} 3443af6ab5fSopenharmony_ci 3453af6ab5fSopenharmony_ciType *TSChecker::CheckComputedPropertyName(ir::Expression *key) 3463af6ab5fSopenharmony_ci{ 3473af6ab5fSopenharmony_ci if (key->TsType() != nullptr) { 3483af6ab5fSopenharmony_ci return key->TsType(); 3493af6ab5fSopenharmony_ci } 3503af6ab5fSopenharmony_ci 3513af6ab5fSopenharmony_ci Type *keyType = key->Check(this); 3523af6ab5fSopenharmony_ci 3533af6ab5fSopenharmony_ci if (!keyType->HasTypeFlag(TypeFlag::STRING_LIKE | TypeFlag::NUMBER_LIKE)) { 3543af6ab5fSopenharmony_ci ThrowTypeError( 3553af6ab5fSopenharmony_ci "A computed property name in a type literal must refer to an expression whose type is a literal " 3563af6ab5fSopenharmony_ci "type " 3573af6ab5fSopenharmony_ci "or a 'unique symbol' type", 3583af6ab5fSopenharmony_ci key->Start()); 3593af6ab5fSopenharmony_ci } 3603af6ab5fSopenharmony_ci 3613af6ab5fSopenharmony_ci key->SetTsType(keyType); 3623af6ab5fSopenharmony_ci return keyType; 3633af6ab5fSopenharmony_ci} 3643af6ab5fSopenharmony_ci 3653af6ab5fSopenharmony_ciIndexInfo *TSChecker::GetApplicableIndexInfo(Type *type, Type *indexType) 3663af6ab5fSopenharmony_ci{ 3673af6ab5fSopenharmony_ci ResolveStructuredTypeMembers(type); 3683af6ab5fSopenharmony_ci bool getNumberInfo = indexType->HasTypeFlag(TypeFlag::NUMBER_LIKE); 3693af6ab5fSopenharmony_ci 3703af6ab5fSopenharmony_ci if (type->IsObjectType()) { 3713af6ab5fSopenharmony_ci if (getNumberInfo) { 3723af6ab5fSopenharmony_ci return type->AsObjectType()->NumberIndexInfo(); 3733af6ab5fSopenharmony_ci } 3743af6ab5fSopenharmony_ci 3753af6ab5fSopenharmony_ci return type->AsObjectType()->StringIndexInfo(); 3763af6ab5fSopenharmony_ci } 3773af6ab5fSopenharmony_ci 3783af6ab5fSopenharmony_ci if (type->IsUnionType()) { 3793af6ab5fSopenharmony_ci ASSERT(type->AsUnionType()->MergedObjectType()); 3803af6ab5fSopenharmony_ci 3813af6ab5fSopenharmony_ci if (getNumberInfo) { 3823af6ab5fSopenharmony_ci return type->AsUnionType()->MergedObjectType()->NumberIndexInfo(); 3833af6ab5fSopenharmony_ci } 3843af6ab5fSopenharmony_ci 3853af6ab5fSopenharmony_ci return type->AsUnionType()->MergedObjectType()->StringIndexInfo(); 3863af6ab5fSopenharmony_ci } 3873af6ab5fSopenharmony_ci 3883af6ab5fSopenharmony_ci return nullptr; 3893af6ab5fSopenharmony_ci} 3903af6ab5fSopenharmony_ci 3913af6ab5fSopenharmony_ciType *TSChecker::GetPropertyTypeForIndexType(Type *type, Type *indexType) 3923af6ab5fSopenharmony_ci{ 3933af6ab5fSopenharmony_ci if (type->IsArrayType()) { 3943af6ab5fSopenharmony_ci return type->AsArrayType()->ElementType(); 3953af6ab5fSopenharmony_ci } 3963af6ab5fSopenharmony_ci 3973af6ab5fSopenharmony_ci if (indexType->HasTypeFlag(TypeFlag::STRING_LITERAL | TypeFlag::NUMBER_LITERAL)) { 3983af6ab5fSopenharmony_ci varbinder::Variable *prop = nullptr; 3993af6ab5fSopenharmony_ci 4003af6ab5fSopenharmony_ci if (indexType->IsStringLiteralType()) { 4013af6ab5fSopenharmony_ci prop = GetPropertyOfType(type, indexType->AsStringLiteralType()->Value()); 4023af6ab5fSopenharmony_ci } else { 4033af6ab5fSopenharmony_ci util::StringView propName = 4043af6ab5fSopenharmony_ci util::Helpers::ToStringView(Allocator(), indexType->AsNumberLiteralType()->Value()); 4053af6ab5fSopenharmony_ci prop = GetPropertyOfType(type, propName); 4063af6ab5fSopenharmony_ci } 4073af6ab5fSopenharmony_ci 4083af6ab5fSopenharmony_ci if (prop != nullptr) { 4093af6ab5fSopenharmony_ci Type *propType = GetTypeOfVariable(prop); 4103af6ab5fSopenharmony_ci 4113af6ab5fSopenharmony_ci if (prop->HasFlag(varbinder::VariableFlags::READONLY)) { 4123af6ab5fSopenharmony_ci propType->AddTypeFlag(TypeFlag::READONLY); 4133af6ab5fSopenharmony_ci } 4143af6ab5fSopenharmony_ci 4153af6ab5fSopenharmony_ci return propType; 4163af6ab5fSopenharmony_ci } 4173af6ab5fSopenharmony_ci } 4183af6ab5fSopenharmony_ci 4193af6ab5fSopenharmony_ci if (indexType->HasTypeFlag(TypeFlag::STRING_LIKE | TypeFlag::NUMBER_LIKE)) { 4203af6ab5fSopenharmony_ci IndexInfo *indexInfo = GetApplicableIndexInfo(type, indexType); 4213af6ab5fSopenharmony_ci 4223af6ab5fSopenharmony_ci if (indexInfo != nullptr) { 4233af6ab5fSopenharmony_ci Type *indexInfoType = indexInfo->GetType(); 4243af6ab5fSopenharmony_ci 4253af6ab5fSopenharmony_ci if (indexInfo->Readonly()) { 4263af6ab5fSopenharmony_ci indexInfoType->AddTypeFlag(TypeFlag::READONLY); 4273af6ab5fSopenharmony_ci } 4283af6ab5fSopenharmony_ci 4293af6ab5fSopenharmony_ci return indexInfoType; 4303af6ab5fSopenharmony_ci } 4313af6ab5fSopenharmony_ci } 4323af6ab5fSopenharmony_ci 4333af6ab5fSopenharmony_ci return nullptr; 4343af6ab5fSopenharmony_ci} 4353af6ab5fSopenharmony_ci 4363af6ab5fSopenharmony_ciArenaVector<ObjectType *> TSChecker::GetBaseTypes(InterfaceType *type) 4373af6ab5fSopenharmony_ci{ 4383af6ab5fSopenharmony_ci if (type->HasObjectFlag(ObjectFlags::RESOLVED_BASE_TYPES)) { 4393af6ab5fSopenharmony_ci return type->Bases(); 4403af6ab5fSopenharmony_ci } 4413af6ab5fSopenharmony_ci 4423af6ab5fSopenharmony_ci ASSERT(type->Variable() && type->Variable()->Declaration()->IsInterfaceDecl()); 4433af6ab5fSopenharmony_ci varbinder::InterfaceDecl *decl = type->Variable()->Declaration()->AsInterfaceDecl(); 4443af6ab5fSopenharmony_ci 4453af6ab5fSopenharmony_ci TypeStackElement tse(this, type, {"Type ", type->Name(), " recursively references itself as a base type."}, 4463af6ab5fSopenharmony_ci decl->Node()->AsTSInterfaceDeclaration()->Id()->Start()); 4473af6ab5fSopenharmony_ci if (tse.HasTypeError()) { 4483af6ab5fSopenharmony_ci type->Bases().clear(); 4493af6ab5fSopenharmony_ci return type->Bases(); 4503af6ab5fSopenharmony_ci } 4513af6ab5fSopenharmony_ci 4523af6ab5fSopenharmony_ci for (const auto *declaration : decl->Decls()) { 4533af6ab5fSopenharmony_ci if (declaration->Extends().empty()) { 4543af6ab5fSopenharmony_ci continue; 4553af6ab5fSopenharmony_ci } 4563af6ab5fSopenharmony_ci 4573af6ab5fSopenharmony_ci for (auto *extends : declaration->Extends()) { 4583af6ab5fSopenharmony_ci Type *baseType = extends->Expr()->GetType(this); 4593af6ab5fSopenharmony_ci 4603af6ab5fSopenharmony_ci if (!baseType->HasTypeFlag(TypeFlag::OBJECT | TypeFlag::NON_PRIMITIVE | TypeFlag::ANY)) { 4613af6ab5fSopenharmony_ci ThrowTypeError( 4623af6ab5fSopenharmony_ci "An interface can only extend an object type or intersection of object types with statically " 4633af6ab5fSopenharmony_ci "known " 4643af6ab5fSopenharmony_ci "members", 4653af6ab5fSopenharmony_ci extends->Start()); 4663af6ab5fSopenharmony_ci } 4673af6ab5fSopenharmony_ci 4683af6ab5fSopenharmony_ci if (!baseType->IsObjectType()) { 4693af6ab5fSopenharmony_ci continue; 4703af6ab5fSopenharmony_ci } 4713af6ab5fSopenharmony_ci 4723af6ab5fSopenharmony_ci ObjectType *baseObj = baseType->AsObjectType(); 4733af6ab5fSopenharmony_ci 4743af6ab5fSopenharmony_ci if (baseType == type) { 4753af6ab5fSopenharmony_ci ThrowTypeError({"Type ", type->Name(), " recursively references itself as a base type."}, 4763af6ab5fSopenharmony_ci decl->Node()->AsTSInterfaceDeclaration()->Id()->Start()); 4773af6ab5fSopenharmony_ci } 4783af6ab5fSopenharmony_ci 4793af6ab5fSopenharmony_ci type->AddBase(baseObj); 4803af6ab5fSopenharmony_ci 4813af6ab5fSopenharmony_ci if (!baseObj->IsInterfaceType()) { 4823af6ab5fSopenharmony_ci continue; 4833af6ab5fSopenharmony_ci } 4843af6ab5fSopenharmony_ci 4853af6ab5fSopenharmony_ci CheckExtendsBases(baseObj, type, decl); 4863af6ab5fSopenharmony_ci } 4873af6ab5fSopenharmony_ci } 4883af6ab5fSopenharmony_ci 4893af6ab5fSopenharmony_ci type->AddObjectFlag(ObjectFlags::RESOLVED_BASE_TYPES); 4903af6ab5fSopenharmony_ci return type->Bases(); 4913af6ab5fSopenharmony_ci} 4923af6ab5fSopenharmony_ci 4933af6ab5fSopenharmony_civoid TSChecker::CheckExtendsBases(ObjectType *&baseObj, InterfaceType *&type, varbinder::InterfaceDecl *&decl) 4943af6ab5fSopenharmony_ci{ 4953af6ab5fSopenharmony_ci ArenaVector<ObjectType *> extendsBases = GetBaseTypes(baseObj->AsInterfaceType()); 4963af6ab5fSopenharmony_ci for (auto *extendBase : extendsBases) { 4973af6ab5fSopenharmony_ci if (extendBase == type) { 4983af6ab5fSopenharmony_ci ThrowTypeError({"Type ", type->Name(), " recursively references itself as a base type."}, 4993af6ab5fSopenharmony_ci decl->Node()->AsTSInterfaceDeclaration()->Id()->Start()); 5003af6ab5fSopenharmony_ci } 5013af6ab5fSopenharmony_ci } 5023af6ab5fSopenharmony_ci} 5033af6ab5fSopenharmony_ci 5043af6ab5fSopenharmony_civoid TSChecker::ResolveDeclaredMembers(InterfaceType *type) 5053af6ab5fSopenharmony_ci{ 5063af6ab5fSopenharmony_ci if (type->HasObjectFlag(ObjectFlags::RESOLVED_DECLARED_MEMBERS)) { 5073af6ab5fSopenharmony_ci return; 5083af6ab5fSopenharmony_ci } 5093af6ab5fSopenharmony_ci 5103af6ab5fSopenharmony_ci ASSERT(type->Variable() && type->Variable()->Declaration()->IsInterfaceDecl()); 5113af6ab5fSopenharmony_ci varbinder::InterfaceDecl *decl = type->Variable()->Declaration()->AsInterfaceDecl(); 5123af6ab5fSopenharmony_ci 5133af6ab5fSopenharmony_ci ArenaVector<ir::TSSignatureDeclaration *> signatureDeclarations(Allocator()->Adapter()); 5143af6ab5fSopenharmony_ci ArenaVector<ir::TSIndexSignature *> indexDeclarations(Allocator()->Adapter()); 5153af6ab5fSopenharmony_ci 5163af6ab5fSopenharmony_ci for (const auto *declaration : decl->Decls()) { 5173af6ab5fSopenharmony_ci for (auto *member : declaration->Body()->Body()) { 5183af6ab5fSopenharmony_ci ResolvePropertiesOfObjectType(type, member, signatureDeclarations, indexDeclarations, true); 5193af6ab5fSopenharmony_ci } 5203af6ab5fSopenharmony_ci 5213af6ab5fSopenharmony_ci type->AddObjectFlag(ObjectFlags::RESOLVED_DECLARED_MEMBERS); 5223af6ab5fSopenharmony_ci 5233af6ab5fSopenharmony_ci ResolveSignaturesOfObjectType(type, signatureDeclarations); 5243af6ab5fSopenharmony_ci ResolveIndexInfosOfObjectType(type, indexDeclarations); 5253af6ab5fSopenharmony_ci } 5263af6ab5fSopenharmony_ci} 5273af6ab5fSopenharmony_ci 5283af6ab5fSopenharmony_cibool TSChecker::ValidateInterfaceMemberRedeclaration(ObjectType *type, varbinder::Variable *prop, 5293af6ab5fSopenharmony_ci const lexer::SourcePosition &locInfo) 5303af6ab5fSopenharmony_ci{ 5313af6ab5fSopenharmony_ci if (prop->HasFlag(varbinder::VariableFlags::COMPUTED)) { 5323af6ab5fSopenharmony_ci return true; 5333af6ab5fSopenharmony_ci } 5343af6ab5fSopenharmony_ci 5353af6ab5fSopenharmony_ci varbinder::Variable *found = type->GetProperty(prop->Name(), false); 5363af6ab5fSopenharmony_ci 5373af6ab5fSopenharmony_ci if (found == nullptr) { 5383af6ab5fSopenharmony_ci return true; 5393af6ab5fSopenharmony_ci } 5403af6ab5fSopenharmony_ci 5413af6ab5fSopenharmony_ci Type *targetType = GetTypeOfVariable(prop); 5423af6ab5fSopenharmony_ci Type *sourceType = GetTypeOfVariable(found); 5433af6ab5fSopenharmony_ci IsTypeIdenticalTo(targetType, sourceType, 5443af6ab5fSopenharmony_ci {"Subsequent property declarations must have the same type. Property ", prop->Name(), 5453af6ab5fSopenharmony_ci " must be of type ", sourceType, ", but here has type ", targetType, "."}, 5463af6ab5fSopenharmony_ci locInfo); 5473af6ab5fSopenharmony_ci return false; 5483af6ab5fSopenharmony_ci} 5493af6ab5fSopenharmony_ci} // namespace ark::es2panda::checker 550