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