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 "boxingConverter.h"
173af6ab5fSopenharmony_ci#include "checker/ETSchecker.h"
183af6ab5fSopenharmony_ci#include "checker/ets/typeRelationContext.h"
193af6ab5fSopenharmony_ci#include "checker/types/ets/etsDynamicType.h"
203af6ab5fSopenharmony_ci#include "checker/types/ets/etsObjectType.h"
213af6ab5fSopenharmony_ci#include "checker/types/ets/etsTupleType.h"
223af6ab5fSopenharmony_ci#include "ir/astNode.h"
233af6ab5fSopenharmony_ci#include "ir/typeNode.h"
243af6ab5fSopenharmony_ci#include "ir/base/classDefinition.h"
253af6ab5fSopenharmony_ci#include "ir/base/classElement.h"
263af6ab5fSopenharmony_ci#include "ir/base/classProperty.h"
273af6ab5fSopenharmony_ci#include "ir/base/classStaticBlock.h"
283af6ab5fSopenharmony_ci#include "ir/base/methodDefinition.h"
293af6ab5fSopenharmony_ci#include "ir/base/scriptFunction.h"
303af6ab5fSopenharmony_ci#include "ir/ets/etsNewClassInstanceExpression.h"
313af6ab5fSopenharmony_ci#include "ir/ets/etsTypeReference.h"
323af6ab5fSopenharmony_ci#include "ir/ets/etsTypeReferencePart.h"
333af6ab5fSopenharmony_ci#include "ir/ets/etsUnionType.h"
343af6ab5fSopenharmony_ci#include "ir/expressions/assignmentExpression.h"
353af6ab5fSopenharmony_ci#include "ir/expressions/callExpression.h"
363af6ab5fSopenharmony_ci#include "ir/expressions/functionExpression.h"
373af6ab5fSopenharmony_ci#include "ir/expressions/identifier.h"
383af6ab5fSopenharmony_ci#include "ir/expressions/memberExpression.h"
393af6ab5fSopenharmony_ci#include "ir/statements/blockStatement.h"
403af6ab5fSopenharmony_ci#include "ir/statements/expressionStatement.h"
413af6ab5fSopenharmony_ci#include "ir/statements/variableDeclarator.h"
423af6ab5fSopenharmony_ci#include "ir/ts/tsClassImplements.h"
433af6ab5fSopenharmony_ci#include "ir/ts/tsInterfaceDeclaration.h"
443af6ab5fSopenharmony_ci#include "ir/ts/tsInterfaceHeritage.h"
453af6ab5fSopenharmony_ci#include "ir/ts/tsTypeParameter.h"
463af6ab5fSopenharmony_ci#include "ir/ts/tsTypeParameterDeclaration.h"
473af6ab5fSopenharmony_ci#include "varbinder/declaration.h"
483af6ab5fSopenharmony_ci#include "varbinder/variableFlags.h"
493af6ab5fSopenharmony_ci#include "generated/signatures.h"
503af6ab5fSopenharmony_ci
513af6ab5fSopenharmony_cinamespace ark::es2panda::checker {
523af6ab5fSopenharmony_ciETSObjectType *ETSChecker::GetSuperType(ETSObjectType *type)
533af6ab5fSopenharmony_ci{
543af6ab5fSopenharmony_ci    ComputeSuperType(type);
553af6ab5fSopenharmony_ci    if (type == GlobalETSObjectType()) {
563af6ab5fSopenharmony_ci        return GlobalETSObjectType();
573af6ab5fSopenharmony_ci    }
583af6ab5fSopenharmony_ci    if (type->SuperType() == nullptr) {
593af6ab5fSopenharmony_ci        return nullptr;
603af6ab5fSopenharmony_ci    }
613af6ab5fSopenharmony_ci    return type->SuperType();
623af6ab5fSopenharmony_ci}
633af6ab5fSopenharmony_ci
643af6ab5fSopenharmony_cibool ETSChecker::ComputeSuperType(ETSObjectType *type)
653af6ab5fSopenharmony_ci{
663af6ab5fSopenharmony_ci    if (type->HasObjectFlag(ETSObjectFlags::RESOLVED_SUPER)) {
673af6ab5fSopenharmony_ci        return true;
683af6ab5fSopenharmony_ci    }
693af6ab5fSopenharmony_ci
703af6ab5fSopenharmony_ci    ASSERT(type->Variable() && type->GetDeclNode()->IsClassDefinition());
713af6ab5fSopenharmony_ci    auto *classDef = type->GetDeclNode()->AsClassDefinition();
723af6ab5fSopenharmony_ci
733af6ab5fSopenharmony_ci    if (classDef->Super() == nullptr) {
743af6ab5fSopenharmony_ci        type->AddObjectFlag(ETSObjectFlags::RESOLVED_SUPER);
753af6ab5fSopenharmony_ci        if (type != GlobalETSObjectType()) {
763af6ab5fSopenharmony_ci            type->SetSuperType(GlobalETSObjectType());
773af6ab5fSopenharmony_ci        }
783af6ab5fSopenharmony_ci        return true;
793af6ab5fSopenharmony_ci    }
803af6ab5fSopenharmony_ci
813af6ab5fSopenharmony_ci    TypeStackElement tse(this, type, {"Cyclic inheritance involving ", type->Name(), "."}, classDef->Ident()->Start());
823af6ab5fSopenharmony_ci    if (tse.HasTypeError()) {
833af6ab5fSopenharmony_ci        type->AddObjectFlag(ETSObjectFlags::RESOLVED_SUPER);
843af6ab5fSopenharmony_ci        return false;
853af6ab5fSopenharmony_ci    }
863af6ab5fSopenharmony_ci
873af6ab5fSopenharmony_ci    Type *superType = classDef->Super()->AsTypeNode()->GetType(this);
883af6ab5fSopenharmony_ci    if (superType == nullptr) {
893af6ab5fSopenharmony_ci        return true;
903af6ab5fSopenharmony_ci    }
913af6ab5fSopenharmony_ci    if (!superType->IsETSObjectType() || !superType->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::CLASS)) {
923af6ab5fSopenharmony_ci        LogTypeError({"The super type of '", classDef->Ident()->Name(), "' class is not extensible."},
933af6ab5fSopenharmony_ci                     classDef->Super()->Start());
943af6ab5fSopenharmony_ci        type->SetSuperType(GlobalETSObjectType());
953af6ab5fSopenharmony_ci        return true;
963af6ab5fSopenharmony_ci    }
973af6ab5fSopenharmony_ci
983af6ab5fSopenharmony_ci    ETSObjectType *superObj = superType->AsETSObjectType();
993af6ab5fSopenharmony_ci
1003af6ab5fSopenharmony_ci    // struct node has class definition, too
1013af6ab5fSopenharmony_ci    if (superObj->GetDeclNode()->Parent()->IsETSStructDeclaration()) {
1023af6ab5fSopenharmony_ci        LogTypeError({"struct ", classDef->Ident()->Name(), " is not extensible."}, classDef->Super()->Start());
1033af6ab5fSopenharmony_ci    }
1043af6ab5fSopenharmony_ci
1053af6ab5fSopenharmony_ci    if (superObj->GetDeclNode()->IsFinal()) {
1063af6ab5fSopenharmony_ci        LogTypeError("Cannot inherit with 'final' modifier.", classDef->Super()->Start());
1073af6ab5fSopenharmony_ci        /* It still makes sense to treat superObj as the supertype in future checking */
1083af6ab5fSopenharmony_ci    }
1093af6ab5fSopenharmony_ci    if (GetSuperType(superObj) == nullptr) {
1103af6ab5fSopenharmony_ci        superObj = GlobalETSObjectType();
1113af6ab5fSopenharmony_ci    }
1123af6ab5fSopenharmony_ci    type->SetSuperType(superObj);
1133af6ab5fSopenharmony_ci    type->AddObjectFlag(ETSObjectFlags::RESOLVED_SUPER);
1143af6ab5fSopenharmony_ci    return true;
1153af6ab5fSopenharmony_ci}
1163af6ab5fSopenharmony_ci
1173af6ab5fSopenharmony_civoid ETSChecker::ValidateImplementedInterface(ETSObjectType *type, Type *interface,
1183af6ab5fSopenharmony_ci                                              std::unordered_set<Type *> *extendsSet, const lexer::SourcePosition &pos)
1193af6ab5fSopenharmony_ci{
1203af6ab5fSopenharmony_ci    if (!interface->IsETSObjectType() || !interface->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::INTERFACE)) {
1213af6ab5fSopenharmony_ci        LogTypeError("Interface expected here.", pos);
1223af6ab5fSopenharmony_ci        return;
1233af6ab5fSopenharmony_ci    }
1243af6ab5fSopenharmony_ci
1253af6ab5fSopenharmony_ci    if (!extendsSet->insert(interface).second) {
1263af6ab5fSopenharmony_ci        LogTypeError("Repeated interface.", pos);
1273af6ab5fSopenharmony_ci    }
1283af6ab5fSopenharmony_ci
1293af6ab5fSopenharmony_ci    type->AddInterface(interface->AsETSObjectType());
1303af6ab5fSopenharmony_ci    GetInterfaces(interface->AsETSObjectType());
1313af6ab5fSopenharmony_ci}
1323af6ab5fSopenharmony_ci
1333af6ab5fSopenharmony_civoid ETSChecker::GetInterfacesOfClass(ETSObjectType *type)
1343af6ab5fSopenharmony_ci{
1353af6ab5fSopenharmony_ci    if (type->HasObjectFlag(ETSObjectFlags::RESOLVED_INTERFACES)) {
1363af6ab5fSopenharmony_ci        return;
1373af6ab5fSopenharmony_ci    }
1383af6ab5fSopenharmony_ci
1393af6ab5fSopenharmony_ci    const auto *declNode = type->GetDeclNode()->AsClassDefinition();
1403af6ab5fSopenharmony_ci
1413af6ab5fSopenharmony_ci    std::unordered_set<Type *> extendsSet;
1423af6ab5fSopenharmony_ci    for (auto *it : declNode->Implements()) {
1433af6ab5fSopenharmony_ci        ValidateImplementedInterface(type, it->Expr()->AsTypeNode()->GetType(this), &extendsSet, it->Start());
1443af6ab5fSopenharmony_ci    }
1453af6ab5fSopenharmony_ci    type->AddObjectFlag(ETSObjectFlags::RESOLVED_INTERFACES);
1463af6ab5fSopenharmony_ci}
1473af6ab5fSopenharmony_ci
1483af6ab5fSopenharmony_civoid ETSChecker::GetInterfacesOfInterface(ETSObjectType *type)
1493af6ab5fSopenharmony_ci{
1503af6ab5fSopenharmony_ci    if (type->HasObjectFlag(ETSObjectFlags::RESOLVED_INTERFACES)) {
1513af6ab5fSopenharmony_ci        return;
1523af6ab5fSopenharmony_ci    }
1533af6ab5fSopenharmony_ci
1543af6ab5fSopenharmony_ci    const auto *declNode = type->GetDeclNode()->AsTSInterfaceDeclaration();
1553af6ab5fSopenharmony_ci
1563af6ab5fSopenharmony_ci    TypeStackElement tse(this, type, {"Cyclic inheritance involving ", type->Name(), "."}, declNode->Id()->Start());
1573af6ab5fSopenharmony_ci    if (tse.HasTypeError()) {
1583af6ab5fSopenharmony_ci        type->Interfaces().clear();
1593af6ab5fSopenharmony_ci        return;
1603af6ab5fSopenharmony_ci    }
1613af6ab5fSopenharmony_ci
1623af6ab5fSopenharmony_ci    std::unordered_set<Type *> extendsSet;
1633af6ab5fSopenharmony_ci    for (auto *it : declNode->Extends()) {
1643af6ab5fSopenharmony_ci        ValidateImplementedInterface(type, it->Expr()->AsTypeNode()->GetType(this), &extendsSet, it->Start());
1653af6ab5fSopenharmony_ci    }
1663af6ab5fSopenharmony_ci    type->AddObjectFlag(ETSObjectFlags::RESOLVED_INTERFACES);
1673af6ab5fSopenharmony_ci}
1683af6ab5fSopenharmony_ci
1693af6ab5fSopenharmony_ciArenaVector<ETSObjectType *> ETSChecker::GetInterfaces(ETSObjectType *type)
1703af6ab5fSopenharmony_ci{
1713af6ab5fSopenharmony_ci    ASSERT(type->GetDeclNode()->IsClassDefinition() || type->GetDeclNode()->IsTSInterfaceDeclaration());
1723af6ab5fSopenharmony_ci
1733af6ab5fSopenharmony_ci    if (type->GetDeclNode()->IsClassDefinition()) {
1743af6ab5fSopenharmony_ci        GetInterfacesOfClass(type);
1753af6ab5fSopenharmony_ci    } else {
1763af6ab5fSopenharmony_ci        GetInterfacesOfInterface(type);
1773af6ab5fSopenharmony_ci    }
1783af6ab5fSopenharmony_ci
1793af6ab5fSopenharmony_ci    return type->Interfaces();
1803af6ab5fSopenharmony_ci}
1813af6ab5fSopenharmony_ci
1823af6ab5fSopenharmony_cistd::pair<ArenaVector<Type *>, bool> ETSChecker::CreateUnconstrainedTypeParameters(
1833af6ab5fSopenharmony_ci    ir::TSTypeParameterDeclaration const *typeParams)
1843af6ab5fSopenharmony_ci{
1853af6ab5fSopenharmony_ci    bool ok = true;
1863af6ab5fSopenharmony_ci    ArenaVector<Type *> result {Allocator()->Adapter()};
1873af6ab5fSopenharmony_ci    checker::ScopeContext scopeCtx(this, typeParams->Scope());
1883af6ab5fSopenharmony_ci
1893af6ab5fSopenharmony_ci    // Note: we have to run pure check loop first to avoid endless loop because of possible circular dependencies
1903af6ab5fSopenharmony_ci    Type2TypeMap extends {};
1913af6ab5fSopenharmony_ci    TypeSet typeParameterDecls {};
1923af6ab5fSopenharmony_ci    for (auto *const typeParam : typeParams->Params()) {
1933af6ab5fSopenharmony_ci        ok &= CheckDefaultTypeParameter(typeParam, typeParameterDecls);
1943af6ab5fSopenharmony_ci        if (auto *const constraint = typeParam->Constraint();
1953af6ab5fSopenharmony_ci            constraint != nullptr && constraint->IsETSTypeReference() &&
1963af6ab5fSopenharmony_ci            constraint->AsETSTypeReference()->Part()->Name()->IsIdentifier()) {
1973af6ab5fSopenharmony_ci            ok &= CheckTypeParameterConstraint(typeParam, extends);
1983af6ab5fSopenharmony_ci        }
1993af6ab5fSopenharmony_ci    }
2003af6ab5fSopenharmony_ci
2013af6ab5fSopenharmony_ci    for (auto *const typeParam : typeParams->Params()) {
2023af6ab5fSopenharmony_ci        result.emplace_back(SetUpParameterType(typeParam));
2033af6ab5fSopenharmony_ci    }
2043af6ab5fSopenharmony_ci
2053af6ab5fSopenharmony_ci    return {result, ok};
2063af6ab5fSopenharmony_ci}
2073af6ab5fSopenharmony_ci
2083af6ab5fSopenharmony_civoid ETSChecker::AssignTypeParameterConstraints(ir::TSTypeParameterDeclaration const *typeParams)
2093af6ab5fSopenharmony_ci{
2103af6ab5fSopenharmony_ci    ConstraintCheckScope ctScope(this);
2113af6ab5fSopenharmony_ci    // The type parameter might be used in the constraint, like 'K extend Comparable<K>',
2123af6ab5fSopenharmony_ci    // so we need to create their type first, then set up the constraint
2133af6ab5fSopenharmony_ci    for (auto *const param : typeParams->Params()) {
2143af6ab5fSopenharmony_ci        SetUpTypeParameterConstraint(param);
2153af6ab5fSopenharmony_ci    }
2163af6ab5fSopenharmony_ci    ctScope.TryCheckConstraints();
2173af6ab5fSopenharmony_ci}
2183af6ab5fSopenharmony_ci
2193af6ab5fSopenharmony_cibool ETSChecker::CheckDefaultTypeParameter(const ir::TSTypeParameter *param, TypeSet &typeParameterDecls)
2203af6ab5fSopenharmony_ci{
2213af6ab5fSopenharmony_ci    bool ok = true;
2223af6ab5fSopenharmony_ci    const auto typeParamVar = param->Name()->Variable();
2233af6ab5fSopenharmony_ci    if (typeParameterDecls.count(typeParamVar) != 0U) {
2243af6ab5fSopenharmony_ci        LogTypeError({"Duplicate type parameter '", param->Name()->Name().Utf8(), "'."}, param->Start());
2253af6ab5fSopenharmony_ci        return false;
2263af6ab5fSopenharmony_ci    }
2273af6ab5fSopenharmony_ci
2283af6ab5fSopenharmony_ci    std::function<void(ir::AstNode *)> checkDefault = [&typeParameterDecls, this, &checkDefault,
2293af6ab5fSopenharmony_ci                                                       &ok](ir::AstNode *node) {
2303af6ab5fSopenharmony_ci        if (node->IsETSTypeReferencePart()) {
2313af6ab5fSopenharmony_ci            ir::ETSTypeReferencePart *defaultTypePart = node->AsETSTypeReferencePart();
2323af6ab5fSopenharmony_ci            if (defaultTypePart->Name()->Variable()->TsType() == nullptr &&
2333af6ab5fSopenharmony_ci                (defaultTypePart->Name()->Variable()->Flags() & varbinder::VariableFlags::TYPE_PARAMETER) != 0U &&
2343af6ab5fSopenharmony_ci                typeParameterDecls.count(defaultTypePart->Name()->Variable()) == 0U) {
2353af6ab5fSopenharmony_ci                LogTypeError({"Type Parameter ", defaultTypePart->Name()->AsIdentifier()->Name().Utf8(),
2363af6ab5fSopenharmony_ci                              " should be defined before use."},
2373af6ab5fSopenharmony_ci                             node->Start());
2383af6ab5fSopenharmony_ci                ok = false;
2393af6ab5fSopenharmony_ci            }
2403af6ab5fSopenharmony_ci        }
2413af6ab5fSopenharmony_ci        node->Iterate(checkDefault);
2423af6ab5fSopenharmony_ci    };
2433af6ab5fSopenharmony_ci
2443af6ab5fSopenharmony_ci    if (param->DefaultType() != nullptr) {
2453af6ab5fSopenharmony_ci        param->DefaultType()->Iterate(checkDefault);
2463af6ab5fSopenharmony_ci    }
2473af6ab5fSopenharmony_ci
2483af6ab5fSopenharmony_ci    typeParameterDecls.emplace(typeParamVar);
2493af6ab5fSopenharmony_ci    return ok;
2503af6ab5fSopenharmony_ci}
2513af6ab5fSopenharmony_ci
2523af6ab5fSopenharmony_cibool ETSChecker::CheckTypeParameterConstraint(ir::TSTypeParameter *param, Type2TypeMap &extends)
2533af6ab5fSopenharmony_ci{
2543af6ab5fSopenharmony_ci    const auto typeParamVar = param->Name()->Variable();
2553af6ab5fSopenharmony_ci    const auto constraintVar = param->Constraint()->AsETSTypeReference()->Part()->Name()->Variable();
2563af6ab5fSopenharmony_ci    extends.emplace(typeParamVar, constraintVar);
2573af6ab5fSopenharmony_ci    auto it = extends.find(constraintVar);
2583af6ab5fSopenharmony_ci    while (it != extends.cend()) {
2593af6ab5fSopenharmony_ci        if (it->second == typeParamVar) {
2603af6ab5fSopenharmony_ci            LogTypeError({"Type parameter '", param->Name()->Name().Utf8(), "' has circular constraint dependency."},
2613af6ab5fSopenharmony_ci                         param->Constraint()->Start());
2623af6ab5fSopenharmony_ci            return false;
2633af6ab5fSopenharmony_ci        }
2643af6ab5fSopenharmony_ci        it = extends.find(it->second);
2653af6ab5fSopenharmony_ci    }
2663af6ab5fSopenharmony_ci
2673af6ab5fSopenharmony_ci    return true;
2683af6ab5fSopenharmony_ci}
2693af6ab5fSopenharmony_ci
2703af6ab5fSopenharmony_civoid ETSChecker::SetUpTypeParameterConstraint(ir::TSTypeParameter *const param)
2713af6ab5fSopenharmony_ci{
2723af6ab5fSopenharmony_ci    ETSTypeParameter *const paramType = param->Name()->Variable()->TsType()->AsETSTypeParameter();
2733af6ab5fSopenharmony_ci    auto const traverseReferenced =
2743af6ab5fSopenharmony_ci        [this, scope = param->Parent()->AsTSTypeParameterDeclaration()->Scope()](ir::TypeNode *typeNode) {
2753af6ab5fSopenharmony_ci            if (!typeNode->IsETSTypeReference()) {
2763af6ab5fSopenharmony_ci                return;
2773af6ab5fSopenharmony_ci            }
2783af6ab5fSopenharmony_ci            const auto typeName = typeNode->AsETSTypeReference()->Part()->Name()->AsIdentifier()->Name();
2793af6ab5fSopenharmony_ci            auto *const found = scope->FindLocal(typeName, varbinder::ResolveBindingOptions::BINDINGS);
2803af6ab5fSopenharmony_ci            if (found != nullptr) {
2813af6ab5fSopenharmony_ci                SetUpTypeParameterConstraint(found->Declaration()->Node()->AsTSTypeParameter());
2823af6ab5fSopenharmony_ci            }
2833af6ab5fSopenharmony_ci        };
2843af6ab5fSopenharmony_ci
2853af6ab5fSopenharmony_ci    if (param->Constraint() != nullptr) {
2863af6ab5fSopenharmony_ci        traverseReferenced(param->Constraint());
2873af6ab5fSopenharmony_ci        auto *const constraint = param->Constraint()->GetType(this);
2883af6ab5fSopenharmony_ci        // invalid: T extends int[]
2893af6ab5fSopenharmony_ci        if (!constraint->IsETSObjectType() && !constraint->IsETSTypeParameter() && !constraint->IsETSUnionType()) {
2903af6ab5fSopenharmony_ci            LogTypeError("Extends constraint must be an object", param->Constraint()->Start());
2913af6ab5fSopenharmony_ci        }
2923af6ab5fSopenharmony_ci        paramType->SetConstraintType(constraint);
2933af6ab5fSopenharmony_ci    } else {
2943af6ab5fSopenharmony_ci        paramType->SetConstraintType(GlobalETSNullishObjectType());
2953af6ab5fSopenharmony_ci    }
2963af6ab5fSopenharmony_ci
2973af6ab5fSopenharmony_ci    if (param->DefaultType() != nullptr) {
2983af6ab5fSopenharmony_ci        traverseReferenced(param->DefaultType());
2993af6ab5fSopenharmony_ci        // NOTE: #14993 ensure default matches constraint
3003af6ab5fSopenharmony_ci        paramType->SetDefaultType(MaybePromotedBuiltinType(param->DefaultType()->GetType(this)));
3013af6ab5fSopenharmony_ci    }
3023af6ab5fSopenharmony_ci}
3033af6ab5fSopenharmony_ci
3043af6ab5fSopenharmony_ciETSTypeParameter *ETSChecker::SetUpParameterType(ir::TSTypeParameter *const param)
3053af6ab5fSopenharmony_ci{
3063af6ab5fSopenharmony_ci    if (param->Name()->Variable() != nullptr && param->Name()->Variable()->TsType() != nullptr) {
3073af6ab5fSopenharmony_ci        ASSERT(param->Name()->Variable()->TsType()->IsETSTypeParameter());
3083af6ab5fSopenharmony_ci        return param->Name()->Variable()->TsType()->AsETSTypeParameter();
3093af6ab5fSopenharmony_ci    }
3103af6ab5fSopenharmony_ci
3113af6ab5fSopenharmony_ci    auto *const paramType = CreateTypeParameter();
3123af6ab5fSopenharmony_ci
3133af6ab5fSopenharmony_ci    paramType->AddTypeFlag(TypeFlag::GENERIC);
3143af6ab5fSopenharmony_ci    paramType->SetDeclNode(param);
3153af6ab5fSopenharmony_ci    paramType->SetVariable(param->Variable());
3163af6ab5fSopenharmony_ci    // NOTE: #15026 recursive type parameter workaround
3173af6ab5fSopenharmony_ci    paramType->SetConstraintType(GlobalETSNullishObjectType());
3183af6ab5fSopenharmony_ci
3193af6ab5fSopenharmony_ci    param->Name()->Variable()->SetTsType(paramType);
3203af6ab5fSopenharmony_ci    return paramType;
3213af6ab5fSopenharmony_ci}
3223af6ab5fSopenharmony_ci
3233af6ab5fSopenharmony_civoid ETSChecker::CreateTypeForClassOrInterfaceTypeParameters(ETSObjectType *type)
3243af6ab5fSopenharmony_ci{
3253af6ab5fSopenharmony_ci    if (type->HasObjectFlag(ETSObjectFlags::RESOLVED_TYPE_PARAMS)) {
3263af6ab5fSopenharmony_ci        return;
3273af6ab5fSopenharmony_ci    }
3283af6ab5fSopenharmony_ci
3293af6ab5fSopenharmony_ci    ir::TSTypeParameterDeclaration *typeParams = type->GetDeclNode()->IsClassDefinition()
3303af6ab5fSopenharmony_ci                                                     ? type->GetDeclNode()->AsClassDefinition()->TypeParams()
3313af6ab5fSopenharmony_ci                                                     : type->GetDeclNode()->AsTSInterfaceDeclaration()->TypeParams();
3323af6ab5fSopenharmony_ci    auto [typeParamTypes, ok] = CreateUnconstrainedTypeParameters(typeParams);
3333af6ab5fSopenharmony_ci    type->SetTypeArguments(std::move(typeParamTypes));
3343af6ab5fSopenharmony_ci    if (ok) {
3353af6ab5fSopenharmony_ci        AssignTypeParameterConstraints(typeParams);
3363af6ab5fSopenharmony_ci    }
3373af6ab5fSopenharmony_ci    type->AddObjectFlag(ETSObjectFlags::RESOLVED_TYPE_PARAMS);
3383af6ab5fSopenharmony_ci    type->AddObjectFlag(ETSObjectFlags::INCOMPLETE_INSTANTIATION);
3393af6ab5fSopenharmony_ci}
3403af6ab5fSopenharmony_ci
3413af6ab5fSopenharmony_ciETSObjectType *ETSChecker::BuildBasicInterfaceProperties(ir::TSInterfaceDeclaration *interfaceDecl)
3423af6ab5fSopenharmony_ci{
3433af6ab5fSopenharmony_ci    auto *var = interfaceDecl->Id()->Variable();
3443af6ab5fSopenharmony_ci    ASSERT(var);
3453af6ab5fSopenharmony_ci
3463af6ab5fSopenharmony_ci    checker::ETSObjectType *interfaceType {};
3473af6ab5fSopenharmony_ci    if (var->TsType() == nullptr) {
3483af6ab5fSopenharmony_ci        interfaceType = CreateETSObjectType(var->Name(), interfaceDecl, checker::ETSObjectFlags::INTERFACE);
3493af6ab5fSopenharmony_ci        interfaceType->SetVariable(var);
3503af6ab5fSopenharmony_ci        var->SetTsType(interfaceType);
3513af6ab5fSopenharmony_ci    } else {
3523af6ab5fSopenharmony_ci        interfaceType = var->TsType()->AsETSObjectType();
3533af6ab5fSopenharmony_ci    }
3543af6ab5fSopenharmony_ci
3553af6ab5fSopenharmony_ci    ConstraintCheckScope ctScope(this);
3563af6ab5fSopenharmony_ci    if (interfaceDecl->TypeParams() != nullptr) {
3573af6ab5fSopenharmony_ci        interfaceType->AddTypeFlag(TypeFlag::GENERIC);
3583af6ab5fSopenharmony_ci        CreateTypeForClassOrInterfaceTypeParameters(interfaceType);
3593af6ab5fSopenharmony_ci    }
3603af6ab5fSopenharmony_ci
3613af6ab5fSopenharmony_ci    GetInterfaces(interfaceType);
3623af6ab5fSopenharmony_ci    interfaceType->SetSuperType(GlobalETSObjectType());
3633af6ab5fSopenharmony_ci    ctScope.TryCheckConstraints();
3643af6ab5fSopenharmony_ci    return interfaceType;
3653af6ab5fSopenharmony_ci}
3663af6ab5fSopenharmony_ci
3673af6ab5fSopenharmony_ciETSObjectType *ETSChecker::BuildBasicClassProperties(ir::ClassDefinition *classDef)
3683af6ab5fSopenharmony_ci{
3693af6ab5fSopenharmony_ci    if (classDef->IsFinal() && classDef->IsAbstract()) {
3703af6ab5fSopenharmony_ci        LogTypeError("Cannot use both 'final' and 'abstract' modifiers.", classDef->Start());
3713af6ab5fSopenharmony_ci    }
3723af6ab5fSopenharmony_ci
3733af6ab5fSopenharmony_ci    auto *var = classDef->Ident()->Variable();
3743af6ab5fSopenharmony_ci    ASSERT(var);
3753af6ab5fSopenharmony_ci
3763af6ab5fSopenharmony_ci    const util::StringView &className = classDef->Ident()->Name();
3773af6ab5fSopenharmony_ci
3783af6ab5fSopenharmony_ci    checker::ETSObjectType *classType {};
3793af6ab5fSopenharmony_ci    if (var->TsType() == nullptr) {
3803af6ab5fSopenharmony_ci        classType = CreateETSObjectType(className, classDef, checker::ETSObjectFlags::CLASS);
3813af6ab5fSopenharmony_ci        classType->SetVariable(var);
3823af6ab5fSopenharmony_ci        var->SetTsType(classType);
3833af6ab5fSopenharmony_ci        if (classDef->IsAbstract()) {
3843af6ab5fSopenharmony_ci            classType->AddObjectFlag(checker::ETSObjectFlags::ABSTRACT);
3853af6ab5fSopenharmony_ci        }
3863af6ab5fSopenharmony_ci    } else {
3873af6ab5fSopenharmony_ci        classType = var->TsType()->AsETSObjectType();
3883af6ab5fSopenharmony_ci    }
3893af6ab5fSopenharmony_ci
3903af6ab5fSopenharmony_ci    classDef->SetTsType(classType);
3913af6ab5fSopenharmony_ci
3923af6ab5fSopenharmony_ci    ConstraintCheckScope ctScope(this);
3933af6ab5fSopenharmony_ci    if (classDef->TypeParams() != nullptr) {
3943af6ab5fSopenharmony_ci        classType->AddTypeFlag(TypeFlag::GENERIC);
3953af6ab5fSopenharmony_ci        CreateTypeForClassOrInterfaceTypeParameters(classType);
3963af6ab5fSopenharmony_ci    }
3973af6ab5fSopenharmony_ci
3983af6ab5fSopenharmony_ci    auto *enclosingClass = Context().ContainingClass();
3993af6ab5fSopenharmony_ci    classType->SetEnclosingType(enclosingClass);
4003af6ab5fSopenharmony_ci    CheckerStatus newStatus = CheckerStatus::IN_CLASS;
4013af6ab5fSopenharmony_ci
4023af6ab5fSopenharmony_ci    if (classDef->IsInner()) {
4033af6ab5fSopenharmony_ci        newStatus |= CheckerStatus::INNER_CLASS;
4043af6ab5fSopenharmony_ci        classType->AddObjectFlag(checker::ETSObjectFlags::INNER);
4053af6ab5fSopenharmony_ci    }
4063af6ab5fSopenharmony_ci
4073af6ab5fSopenharmony_ci    auto savedContext = checker::SavedCheckerContext(this, newStatus, classType);
4083af6ab5fSopenharmony_ci
4093af6ab5fSopenharmony_ci    if (!classType->HasObjectFlag(ETSObjectFlags::RESOLVED_SUPER)) {
4103af6ab5fSopenharmony_ci        GetSuperType(classType);
4113af6ab5fSopenharmony_ci        GetInterfaces(classType);
4123af6ab5fSopenharmony_ci    }
4133af6ab5fSopenharmony_ci    ctScope.TryCheckConstraints();
4143af6ab5fSopenharmony_ci    return classType;
4153af6ab5fSopenharmony_ci}
4163af6ab5fSopenharmony_ci
4173af6ab5fSopenharmony_ciETSObjectType *ETSChecker::BuildAnonymousClassProperties(ir::ClassDefinition *classDef, ETSObjectType *superType)
4183af6ab5fSopenharmony_ci{
4193af6ab5fSopenharmony_ci    auto classType = CreateETSObjectType(classDef->Ident()->Name(), classDef, checker::ETSObjectFlags::CLASS);
4203af6ab5fSopenharmony_ci    classDef->SetTsType(classType);
4213af6ab5fSopenharmony_ci    classType->SetSuperType(superType);
4223af6ab5fSopenharmony_ci    classType->AddObjectFlag(checker::ETSObjectFlags::RESOLVED_SUPER);
4233af6ab5fSopenharmony_ci
4243af6ab5fSopenharmony_ci    return classType;
4253af6ab5fSopenharmony_ci}
4263af6ab5fSopenharmony_ci
4273af6ab5fSopenharmony_cistatic void ResolveDeclaredFieldsOfObject(ETSChecker *checker, const ETSObjectType *type, varbinder::ClassScope *scope)
4283af6ab5fSopenharmony_ci{
4293af6ab5fSopenharmony_ci    for (auto &[_, it] : scope->InstanceFieldScope()->Bindings()) {
4303af6ab5fSopenharmony_ci        (void)_;
4313af6ab5fSopenharmony_ci        ASSERT(it->Declaration()->Node()->IsClassProperty());
4323af6ab5fSopenharmony_ci        auto *classProp = it->Declaration()->Node()->AsClassProperty();
4333af6ab5fSopenharmony_ci        it->AddFlag(checker->GetAccessFlagFromNode(classProp));
4343af6ab5fSopenharmony_ci        type->AddProperty<PropertyType::INSTANCE_FIELD>(it->AsLocalVariable());
4353af6ab5fSopenharmony_ci    }
4363af6ab5fSopenharmony_ci
4373af6ab5fSopenharmony_ci    for (auto &[_, it] : scope->StaticFieldScope()->Bindings()) {
4383af6ab5fSopenharmony_ci        (void)_;
4393af6ab5fSopenharmony_ci        ASSERT(it->Declaration()->Node()->IsClassProperty());
4403af6ab5fSopenharmony_ci        auto *classProp = it->Declaration()->Node()->AsClassProperty();
4413af6ab5fSopenharmony_ci        it->AddFlag(checker->GetAccessFlagFromNode(classProp));
4423af6ab5fSopenharmony_ci        type->AddProperty<PropertyType::STATIC_FIELD>(it->AsLocalVariable());
4433af6ab5fSopenharmony_ci    }
4443af6ab5fSopenharmony_ci}
4453af6ab5fSopenharmony_ci
4463af6ab5fSopenharmony_cistatic void ResolveDeclaredMethodsOfObject(ETSChecker *checker, const ETSObjectType *type, varbinder::ClassScope *scope)
4473af6ab5fSopenharmony_ci{
4483af6ab5fSopenharmony_ci    for (auto &[_, it] : scope->InstanceMethodScope()->Bindings()) {
4493af6ab5fSopenharmony_ci        (void)_;
4503af6ab5fSopenharmony_ci        auto *method = it->Declaration()->Node()->AsMethodDefinition();
4513af6ab5fSopenharmony_ci        auto *function = method->Function();
4523af6ab5fSopenharmony_ci
4533af6ab5fSopenharmony_ci        if (function->IsProxy()) {
4543af6ab5fSopenharmony_ci            continue;
4553af6ab5fSopenharmony_ci        }
4563af6ab5fSopenharmony_ci
4573af6ab5fSopenharmony_ci        it->AddFlag(checker->GetAccessFlagFromNode(method));
4583af6ab5fSopenharmony_ci        auto *funcType = checker->BuildMethodSignature(method);
4593af6ab5fSopenharmony_ci        it->SetTsType(funcType);
4603af6ab5fSopenharmony_ci        funcType->SetVariable(it);
4613af6ab5fSopenharmony_ci        method->SetTsType(funcType);
4623af6ab5fSopenharmony_ci        type->AddProperty<PropertyType::INSTANCE_METHOD>(it->AsLocalVariable());
4633af6ab5fSopenharmony_ci    }
4643af6ab5fSopenharmony_ci
4653af6ab5fSopenharmony_ci    for (auto &[_, it] : scope->StaticMethodScope()->Bindings()) {
4663af6ab5fSopenharmony_ci        (void)_;
4673af6ab5fSopenharmony_ci        if (!it->Declaration()->Node()->IsMethodDefinition()) {
4683af6ab5fSopenharmony_ci            continue;
4693af6ab5fSopenharmony_ci        }
4703af6ab5fSopenharmony_ci
4713af6ab5fSopenharmony_ci        auto *method = it->Declaration()->Node()->AsMethodDefinition();
4723af6ab5fSopenharmony_ci        auto *function = method->Function();
4733af6ab5fSopenharmony_ci
4743af6ab5fSopenharmony_ci        if (function->IsProxy()) {
4753af6ab5fSopenharmony_ci            continue;
4763af6ab5fSopenharmony_ci        }
4773af6ab5fSopenharmony_ci
4783af6ab5fSopenharmony_ci        it->AddFlag(checker->GetAccessFlagFromNode(method));
4793af6ab5fSopenharmony_ci        auto *funcType = checker->BuildMethodSignature(method);
4803af6ab5fSopenharmony_ci        it->SetTsType(funcType);
4813af6ab5fSopenharmony_ci        funcType->SetVariable(it);
4823af6ab5fSopenharmony_ci        method->SetTsType(funcType);
4833af6ab5fSopenharmony_ci
4843af6ab5fSopenharmony_ci        if (method->IsConstructor()) {
4853af6ab5fSopenharmony_ci            type->AddConstructSignature(funcType->CallSignatures());
4863af6ab5fSopenharmony_ci            continue;
4873af6ab5fSopenharmony_ci        }
4883af6ab5fSopenharmony_ci
4893af6ab5fSopenharmony_ci        type->AddProperty<PropertyType::STATIC_METHOD>(it->AsLocalVariable());
4903af6ab5fSopenharmony_ci    }
4913af6ab5fSopenharmony_ci}
4923af6ab5fSopenharmony_ci
4933af6ab5fSopenharmony_cistatic void ResolveDeclaredDeclsOfObject(ETSChecker *checker, const ETSObjectType *type, varbinder::ClassScope *scope)
4943af6ab5fSopenharmony_ci{
4953af6ab5fSopenharmony_ci    for (auto &[_, it] : scope->InstanceDeclScope()->Bindings()) {
4963af6ab5fSopenharmony_ci        (void)_;
4973af6ab5fSopenharmony_ci        it->AddFlag(checker->GetAccessFlagFromNode(it->Declaration()->Node()));
4983af6ab5fSopenharmony_ci        type->AddProperty<PropertyType::INSTANCE_DECL>(it->AsLocalVariable());
4993af6ab5fSopenharmony_ci    }
5003af6ab5fSopenharmony_ci
5013af6ab5fSopenharmony_ci    for (auto &[_, it] : scope->StaticDeclScope()->Bindings()) {
5023af6ab5fSopenharmony_ci        (void)_;
5033af6ab5fSopenharmony_ci        it->AddFlag(checker->GetAccessFlagFromNode(it->Declaration()->Node()));
5043af6ab5fSopenharmony_ci        type->AddProperty<PropertyType::STATIC_DECL>(it->AsLocalVariable());
5053af6ab5fSopenharmony_ci    }
5063af6ab5fSopenharmony_ci}
5073af6ab5fSopenharmony_ci
5083af6ab5fSopenharmony_civoid ETSChecker::ResolveDeclaredMembersOfObject(const ETSObjectType *type)
5093af6ab5fSopenharmony_ci{
5103af6ab5fSopenharmony_ci    if (type->IsPropertiesInstantiated()) {
5113af6ab5fSopenharmony_ci        return;
5123af6ab5fSopenharmony_ci    }
5133af6ab5fSopenharmony_ci
5143af6ab5fSopenharmony_ci    auto *declNode = type->GetDeclNode();
5153af6ab5fSopenharmony_ci
5163af6ab5fSopenharmony_ci    if (declNode == nullptr || !(declNode->IsClassDefinition() || declNode->IsTSInterfaceDeclaration())) {
5173af6ab5fSopenharmony_ci        return;
5183af6ab5fSopenharmony_ci    }
5193af6ab5fSopenharmony_ci
5203af6ab5fSopenharmony_ci    if (type->IsGeneric() && type != type->GetOriginalBaseType()) {
5213af6ab5fSopenharmony_ci        const auto *baseType = type->GetOriginalBaseType();
5223af6ab5fSopenharmony_ci        auto *baseDeclNode = baseType->GetDeclNode();
5233af6ab5fSopenharmony_ci        checker::CheckerStatus baseStatus = baseDeclNode->IsTSInterfaceDeclaration()
5243af6ab5fSopenharmony_ci                                                ? checker::CheckerStatus::IN_INTERFACE
5253af6ab5fSopenharmony_ci                                                : checker::CheckerStatus::IN_CLASS;
5263af6ab5fSopenharmony_ci        auto baseScope = baseDeclNode->IsTSInterfaceDeclaration() ? baseDeclNode->AsTSInterfaceDeclaration()->Scope()
5273af6ab5fSopenharmony_ci                                                                  : baseDeclNode->AsClassDefinition()->Scope();
5283af6ab5fSopenharmony_ci        auto savedContext = checker::SavedCheckerContext(this, baseStatus, baseType);
5293af6ab5fSopenharmony_ci        checker::ScopeContext scopeCtx(this, baseScope);
5303af6ab5fSopenharmony_ci        ResolveDeclaredMembersOfObject(baseType);
5313af6ab5fSopenharmony_ci        return;
5323af6ab5fSopenharmony_ci    }
5333af6ab5fSopenharmony_ci
5343af6ab5fSopenharmony_ci    checker::CheckerStatus status =
5353af6ab5fSopenharmony_ci        declNode->IsTSInterfaceDeclaration() ? checker::CheckerStatus::IN_INTERFACE : checker::CheckerStatus::IN_CLASS;
5363af6ab5fSopenharmony_ci    auto *scope = declNode->IsTSInterfaceDeclaration() ? declNode->AsTSInterfaceDeclaration()->Scope()
5373af6ab5fSopenharmony_ci                                                       : declNode->AsClassDefinition()->Scope();
5383af6ab5fSopenharmony_ci    auto savedContext = checker::SavedCheckerContext(this, status, type);
5393af6ab5fSopenharmony_ci    checker::ScopeContext scopeCtx(this, scope);
5403af6ab5fSopenharmony_ci
5413af6ab5fSopenharmony_ci    ResolveDeclaredFieldsOfObject(this, type, scope->AsClassScope());
5423af6ab5fSopenharmony_ci    ResolveDeclaredMethodsOfObject(this, type, scope->AsClassScope());
5433af6ab5fSopenharmony_ci    ResolveDeclaredDeclsOfObject(this, type, scope->AsClassScope());
5443af6ab5fSopenharmony_ci}
5453af6ab5fSopenharmony_ci
5463af6ab5fSopenharmony_cibool ETSChecker::HasETSFunctionType(ir::TypeNode *typeAnnotation)
5473af6ab5fSopenharmony_ci{
5483af6ab5fSopenharmony_ci    if (typeAnnotation->IsETSFunctionType()) {
5493af6ab5fSopenharmony_ci        return true;
5503af6ab5fSopenharmony_ci    }
5513af6ab5fSopenharmony_ci    std::unordered_set<ir::TypeNode *> childrenSet;
5523af6ab5fSopenharmony_ci
5533af6ab5fSopenharmony_ci    if (!typeAnnotation->IsETSTypeReference()) {
5543af6ab5fSopenharmony_ci        return false;
5553af6ab5fSopenharmony_ci    }
5563af6ab5fSopenharmony_ci
5573af6ab5fSopenharmony_ci    auto const addTypeAlias = [&childrenSet, &typeAnnotation](varbinder::Decl *typeDecl) {
5583af6ab5fSopenharmony_ci        typeAnnotation = typeDecl->Node()->AsTSTypeAliasDeclaration()->TypeAnnotation();
5593af6ab5fSopenharmony_ci        if (!typeAnnotation->IsETSUnionType()) {
5603af6ab5fSopenharmony_ci            childrenSet.insert(typeAnnotation);
5613af6ab5fSopenharmony_ci            return;
5623af6ab5fSopenharmony_ci        }
5633af6ab5fSopenharmony_ci        for (auto *type : typeAnnotation->AsETSUnionType()->Types()) {
5643af6ab5fSopenharmony_ci            if (type->IsETSTypeReference()) {
5653af6ab5fSopenharmony_ci                childrenSet.insert(type);
5663af6ab5fSopenharmony_ci            }
5673af6ab5fSopenharmony_ci        }
5683af6ab5fSopenharmony_ci    };
5693af6ab5fSopenharmony_ci
5703af6ab5fSopenharmony_ci    auto *typeDecl = typeAnnotation->AsETSTypeReference()->Part()->Name()->AsIdentifier()->Variable()->Declaration();
5713af6ab5fSopenharmony_ci    if (typeDecl != nullptr && typeDecl->IsTypeAliasDecl()) {
5723af6ab5fSopenharmony_ci        addTypeAlias(typeDecl);
5733af6ab5fSopenharmony_ci    }
5743af6ab5fSopenharmony_ci
5753af6ab5fSopenharmony_ci    for (auto *child : childrenSet) {
5763af6ab5fSopenharmony_ci        if (HasETSFunctionType(child)) {
5773af6ab5fSopenharmony_ci            return true;
5783af6ab5fSopenharmony_ci        }
5793af6ab5fSopenharmony_ci    }
5803af6ab5fSopenharmony_ci    return false;
5813af6ab5fSopenharmony_ci}
5823af6ab5fSopenharmony_ci
5833af6ab5fSopenharmony_cistd::vector<Signature *> ETSChecker::CollectAbstractSignaturesFromObject(const ETSObjectType *objType)
5843af6ab5fSopenharmony_ci{
5853af6ab5fSopenharmony_ci    std::vector<Signature *> abstracts;
5863af6ab5fSopenharmony_ci    for (const auto &prop : objType->Methods()) {
5873af6ab5fSopenharmony_ci        GetTypeOfVariable(prop);
5883af6ab5fSopenharmony_ci
5893af6ab5fSopenharmony_ci        if (!prop->TsType()->IsETSFunctionType()) {
5903af6ab5fSopenharmony_ci            continue;
5913af6ab5fSopenharmony_ci        }
5923af6ab5fSopenharmony_ci
5933af6ab5fSopenharmony_ci        for (auto *sig : prop->TsType()->AsETSFunctionType()->CallSignatures()) {
5943af6ab5fSopenharmony_ci            if (sig->HasSignatureFlag(SignatureFlags::ABSTRACT) && !sig->HasSignatureFlag(SignatureFlags::PRIVATE)) {
5953af6ab5fSopenharmony_ci                abstracts.push_back(sig);
5963af6ab5fSopenharmony_ci            }
5973af6ab5fSopenharmony_ci        }
5983af6ab5fSopenharmony_ci    }
5993af6ab5fSopenharmony_ci
6003af6ab5fSopenharmony_ci    return abstracts;
6013af6ab5fSopenharmony_ci}
6023af6ab5fSopenharmony_ci
6033af6ab5fSopenharmony_civoid ETSChecker::CreateFunctionTypesFromAbstracts(const std::vector<Signature *> &abstracts,
6043af6ab5fSopenharmony_ci                                                  ArenaVector<ETSFunctionType *> *target)
6053af6ab5fSopenharmony_ci{
6063af6ab5fSopenharmony_ci    for (auto *it : abstracts) {
6073af6ab5fSopenharmony_ci        auto name = it->Function()->Id()->Name();
6083af6ab5fSopenharmony_ci        auto *found = FindFunctionInVectorGivenByName(name, *target);
6093af6ab5fSopenharmony_ci        if (found != nullptr) {
6103af6ab5fSopenharmony_ci            found->AddCallSignature(it);
6113af6ab5fSopenharmony_ci            continue;
6123af6ab5fSopenharmony_ci        }
6133af6ab5fSopenharmony_ci
6143af6ab5fSopenharmony_ci        auto *created = CreateETSFunctionType(it);
6153af6ab5fSopenharmony_ci        target->push_back(created);
6163af6ab5fSopenharmony_ci    }
6173af6ab5fSopenharmony_ci}
6183af6ab5fSopenharmony_ci
6193af6ab5fSopenharmony_civoid ETSChecker::ComputeAbstractsFromInterface(ETSObjectType *interfaceType)
6203af6ab5fSopenharmony_ci{
6213af6ab5fSopenharmony_ci    auto cached = cachedComputedAbstracts_.find(interfaceType);
6223af6ab5fSopenharmony_ci    if (cached != cachedComputedAbstracts_.end()) {
6233af6ab5fSopenharmony_ci        return;
6243af6ab5fSopenharmony_ci    }
6253af6ab5fSopenharmony_ci
6263af6ab5fSopenharmony_ci    for (auto *it : interfaceType->Interfaces()) {
6273af6ab5fSopenharmony_ci        ComputeAbstractsFromInterface(it);
6283af6ab5fSopenharmony_ci    }
6293af6ab5fSopenharmony_ci
6303af6ab5fSopenharmony_ci    ArenaVector<ETSFunctionType *> merged(Allocator()->Adapter());
6313af6ab5fSopenharmony_ci    CreateFunctionTypesFromAbstracts(CollectAbstractSignaturesFromObject(interfaceType), &merged);
6323af6ab5fSopenharmony_ci    std::unordered_set<ETSObjectType *> abstractInheritanceTarget;
6333af6ab5fSopenharmony_ci
6343af6ab5fSopenharmony_ci    for (auto *interface : interfaceType->Interfaces()) {
6353af6ab5fSopenharmony_ci        auto found = cachedComputedAbstracts_.find(interface);
6363af6ab5fSopenharmony_ci        ASSERT(found != cachedComputedAbstracts_.end());
6373af6ab5fSopenharmony_ci
6383af6ab5fSopenharmony_ci        if (!abstractInheritanceTarget.insert(found->first).second) {
6393af6ab5fSopenharmony_ci            continue;
6403af6ab5fSopenharmony_ci        }
6413af6ab5fSopenharmony_ci
6423af6ab5fSopenharmony_ci        MergeComputedAbstracts(merged, found->second.first);
6433af6ab5fSopenharmony_ci
6443af6ab5fSopenharmony_ci        for (auto *base : found->second.second) {
6453af6ab5fSopenharmony_ci            abstractInheritanceTarget.insert(base);
6463af6ab5fSopenharmony_ci        }
6473af6ab5fSopenharmony_ci    }
6483af6ab5fSopenharmony_ci
6493af6ab5fSopenharmony_ci    cachedComputedAbstracts_.insert({interfaceType, {merged, abstractInheritanceTarget}});
6503af6ab5fSopenharmony_ci}
6513af6ab5fSopenharmony_ci
6523af6ab5fSopenharmony_ciArenaVector<ETSFunctionType *> &ETSChecker::GetAbstractsForClass(ETSObjectType *classType)
6533af6ab5fSopenharmony_ci{
6543af6ab5fSopenharmony_ci    ArenaVector<ETSFunctionType *> merged(Allocator()->Adapter());
6553af6ab5fSopenharmony_ci    CreateFunctionTypesFromAbstracts(CollectAbstractSignaturesFromObject(classType), &merged);
6563af6ab5fSopenharmony_ci
6573af6ab5fSopenharmony_ci    std::unordered_set<ETSObjectType *> abstractInheritanceTarget;
6583af6ab5fSopenharmony_ci    if (classType->SuperType() != nullptr) {
6593af6ab5fSopenharmony_ci        auto base = cachedComputedAbstracts_.find(classType->SuperType());
6603af6ab5fSopenharmony_ci        ASSERT(base != cachedComputedAbstracts_.end());
6613af6ab5fSopenharmony_ci        MergeComputedAbstracts(merged, base->second.first);
6623af6ab5fSopenharmony_ci
6633af6ab5fSopenharmony_ci        abstractInheritanceTarget.insert(base->first);
6643af6ab5fSopenharmony_ci        for (auto *it : base->second.second) {
6653af6ab5fSopenharmony_ci            abstractInheritanceTarget.insert(it);
6663af6ab5fSopenharmony_ci        }
6673af6ab5fSopenharmony_ci    }
6683af6ab5fSopenharmony_ci
6693af6ab5fSopenharmony_ci    for (auto *it : classType->Interfaces()) {
6703af6ab5fSopenharmony_ci        ComputeAbstractsFromInterface(it);
6713af6ab5fSopenharmony_ci        auto found = cachedComputedAbstracts_.find(it);
6723af6ab5fSopenharmony_ci        ASSERT(found != cachedComputedAbstracts_.end());
6733af6ab5fSopenharmony_ci
6743af6ab5fSopenharmony_ci        if (!abstractInheritanceTarget.insert(found->first).second) {
6753af6ab5fSopenharmony_ci            continue;
6763af6ab5fSopenharmony_ci        }
6773af6ab5fSopenharmony_ci
6783af6ab5fSopenharmony_ci        MergeComputedAbstracts(merged, found->second.first);
6793af6ab5fSopenharmony_ci
6803af6ab5fSopenharmony_ci        for (auto *interface : found->second.second) {
6813af6ab5fSopenharmony_ci            abstractInheritanceTarget.insert(interface);
6823af6ab5fSopenharmony_ci        }
6833af6ab5fSopenharmony_ci    }
6843af6ab5fSopenharmony_ci
6853af6ab5fSopenharmony_ci    return cachedComputedAbstracts_.insert({classType, {merged, abstractInheritanceTarget}}).first->second.first;
6863af6ab5fSopenharmony_ci}
6873af6ab5fSopenharmony_ci
6883af6ab5fSopenharmony_cistatic bool DoObjectImplementInterface(const ETSObjectType *interfaceType, const ETSObjectType *target)
6893af6ab5fSopenharmony_ci{
6903af6ab5fSopenharmony_ci    return std::any_of(interfaceType->Interfaces().begin(), interfaceType->Interfaces().end(),
6913af6ab5fSopenharmony_ci                       [&target](auto *it) { return it == target || DoObjectImplementInterface(it, target); });
6923af6ab5fSopenharmony_ci}
6933af6ab5fSopenharmony_ci
6943af6ab5fSopenharmony_cistatic bool CheckIfInterfaceCanBeFoundOnDifferentPaths(const ETSObjectType *classType,
6953af6ab5fSopenharmony_ci                                                       const ETSObjectType *interfaceType)
6963af6ab5fSopenharmony_ci{
6973af6ab5fSopenharmony_ci    return std::count_if(classType->Interfaces().begin(), classType->Interfaces().end(),
6983af6ab5fSopenharmony_ci                         [&interfaceType](auto *it) { return DoObjectImplementInterface(it, interfaceType); }) == 1;
6993af6ab5fSopenharmony_ci}
7003af6ab5fSopenharmony_ci
7013af6ab5fSopenharmony_cistatic void GetInterfacesOfClass(ETSObjectType *type, ArenaVector<ETSObjectType *> &interfaces)
7023af6ab5fSopenharmony_ci{
7033af6ab5fSopenharmony_ci    for (auto &classInterface : type->Interfaces()) {
7043af6ab5fSopenharmony_ci        if (std::find(interfaces.begin(), interfaces.end(), classInterface) == interfaces.end()) {
7053af6ab5fSopenharmony_ci            interfaces.emplace_back(classInterface);
7063af6ab5fSopenharmony_ci            GetInterfacesOfClass(classInterface, interfaces);
7073af6ab5fSopenharmony_ci        }
7083af6ab5fSopenharmony_ci    }
7093af6ab5fSopenharmony_ci}
7103af6ab5fSopenharmony_ci
7113af6ab5fSopenharmony_civoid ETSChecker::CheckIfOverrideIsValidInInterface(const ETSObjectType *classType, Signature *sig,
7123af6ab5fSopenharmony_ci                                                   ir::ScriptFunction *func)
7133af6ab5fSopenharmony_ci{
7143af6ab5fSopenharmony_ci    if (AreOverrideEquivalent(func->Signature(), sig) && func->IsStatic() == sig->Function()->IsStatic()) {
7153af6ab5fSopenharmony_ci        if (CheckIfInterfaceCanBeFoundOnDifferentPaths(classType, func->Signature()->Owner()) &&
7163af6ab5fSopenharmony_ci            (Relation()->IsSupertypeOf(func->Signature()->Owner(), sig->Owner()) ||
7173af6ab5fSopenharmony_ci             Relation()->IsSupertypeOf(sig->Owner(), func->Signature()->Owner()))) {
7183af6ab5fSopenharmony_ci            return;
7193af6ab5fSopenharmony_ci        }
7203af6ab5fSopenharmony_ci
7213af6ab5fSopenharmony_ci        LogTypeError({"Method '", sig->Function()->Id()->Name(), "' is declared in ", sig->Owner()->Name(), " and ",
7223af6ab5fSopenharmony_ci                      func->Signature()->Owner()->Name(), " interfaces."},
7233af6ab5fSopenharmony_ci                     classType->GetDeclNode()->Start());
7243af6ab5fSopenharmony_ci    }
7253af6ab5fSopenharmony_ci}
7263af6ab5fSopenharmony_ci
7273af6ab5fSopenharmony_civoid ETSChecker::CheckFunctionRedeclarationInInterface(const ETSObjectType *classType,
7283af6ab5fSopenharmony_ci                                                       ArenaVector<Signature *> &similarSignatures,
7293af6ab5fSopenharmony_ci                                                       ir::ScriptFunction *func)
7303af6ab5fSopenharmony_ci{
7313af6ab5fSopenharmony_ci    for (auto *const sig : similarSignatures) {
7323af6ab5fSopenharmony_ci        if (sig != func->Signature() && func->HasBody()) {
7333af6ab5fSopenharmony_ci            if (classType == sig->Owner()) {
7343af6ab5fSopenharmony_ci                return;
7353af6ab5fSopenharmony_ci            }
7363af6ab5fSopenharmony_ci
7373af6ab5fSopenharmony_ci            CheckIfOverrideIsValidInInterface(classType, sig, func);
7383af6ab5fSopenharmony_ci        }
7393af6ab5fSopenharmony_ci    }
7403af6ab5fSopenharmony_ci
7413af6ab5fSopenharmony_ci    similarSignatures.push_back(func->Signature());
7423af6ab5fSopenharmony_ci}
7433af6ab5fSopenharmony_ci
7443af6ab5fSopenharmony_civoid ETSChecker::CheckInterfaceFunctions(ETSObjectType *classType)
7453af6ab5fSopenharmony_ci{
7463af6ab5fSopenharmony_ci    ArenaVector<ETSObjectType *> interfaces(Allocator()->Adapter());
7473af6ab5fSopenharmony_ci    ArenaVector<Signature *> similarSignatures(Allocator()->Adapter());
7483af6ab5fSopenharmony_ci    interfaces.emplace_back(classType);
7493af6ab5fSopenharmony_ci    checker::GetInterfacesOfClass(classType, interfaces);
7503af6ab5fSopenharmony_ci
7513af6ab5fSopenharmony_ci    for (auto *const &interface : interfaces) {
7523af6ab5fSopenharmony_ci        for (auto *const &prop : interface->Methods()) {
7533af6ab5fSopenharmony_ci            if (auto *const func = prop->Declaration()->Node()->AsMethodDefinition()->Function();
7543af6ab5fSopenharmony_ci                func->Body() != nullptr) {
7553af6ab5fSopenharmony_ci                CheckFunctionRedeclarationInInterface(classType, similarSignatures, func);
7563af6ab5fSopenharmony_ci            }
7573af6ab5fSopenharmony_ci        }
7583af6ab5fSopenharmony_ci    }
7593af6ab5fSopenharmony_ci}
7603af6ab5fSopenharmony_ci
7613af6ab5fSopenharmony_ci/// Traverse the interface inheritance tree and collects implemented methods
7623af6ab5fSopenharmony_civoid ETSChecker::CollectImplementedMethodsFromInterfaces(ETSObjectType *classType,
7633af6ab5fSopenharmony_ci                                                         std::vector<Signature *> *implementedSignatures,
7643af6ab5fSopenharmony_ci                                                         const ArenaVector<ETSFunctionType *> &abstractsToBeImplemented)
7653af6ab5fSopenharmony_ci{
7663af6ab5fSopenharmony_ci    std::vector<ETSObjectType *> collectedInterfaces;
7673af6ab5fSopenharmony_ci
7683af6ab5fSopenharmony_ci    for (auto &classInterface : classType->Interfaces()) {
7693af6ab5fSopenharmony_ci        collectedInterfaces.emplace_back(classInterface);
7703af6ab5fSopenharmony_ci    }
7713af6ab5fSopenharmony_ci
7723af6ab5fSopenharmony_ci    size_t index = 0;
7733af6ab5fSopenharmony_ci
7743af6ab5fSopenharmony_ci    while (index < collectedInterfaces.size()) {
7753af6ab5fSopenharmony_ci        for (auto &it : abstractsToBeImplemented) {
7763af6ab5fSopenharmony_ci            for (const auto &prop : collectedInterfaces[index]->Methods()) {
7773af6ab5fSopenharmony_ci                GetTypeOfVariable(prop);
7783af6ab5fSopenharmony_ci                AddImplementedSignature(implementedSignatures, prop, it);
7793af6ab5fSopenharmony_ci            }
7803af6ab5fSopenharmony_ci        }
7813af6ab5fSopenharmony_ci
7823af6ab5fSopenharmony_ci        for (auto &currentInterfaceChild : collectedInterfaces[index]->Interfaces()) {
7833af6ab5fSopenharmony_ci            collectedInterfaces.emplace_back(currentInterfaceChild);
7843af6ab5fSopenharmony_ci        }
7853af6ab5fSopenharmony_ci
7863af6ab5fSopenharmony_ci        index++;
7873af6ab5fSopenharmony_ci    }
7883af6ab5fSopenharmony_ci}
7893af6ab5fSopenharmony_ci
7903af6ab5fSopenharmony_civoid ETSChecker::ValidateAbstractSignature(ArenaVector<ETSFunctionType *>::iterator &it,
7913af6ab5fSopenharmony_ci                                           ArenaVector<ETSFunctionType *> &abstractsToBeImplemented,
7923af6ab5fSopenharmony_ci                                           const std::vector<Signature *> &implementedSignatures,
7933af6ab5fSopenharmony_ci                                           bool &functionOverridden, Accessor &isGetSetExternal)
7943af6ab5fSopenharmony_ci{
7953af6ab5fSopenharmony_ci    for (auto abstractSignature = (*it)->CallSignatures().begin();
7963af6ab5fSopenharmony_ci         abstractSignature != (*it)->CallSignatures().end();) {
7973af6ab5fSopenharmony_ci        bool foundSignature = false;
7983af6ab5fSopenharmony_ci        isGetSetExternal.isGetter = (*abstractSignature)->HasSignatureFlag(SignatureFlags::GETTER);
7993af6ab5fSopenharmony_ci        isGetSetExternal.isSetter = (*abstractSignature)->HasSignatureFlag(SignatureFlags::SETTER);
8003af6ab5fSopenharmony_ci        isGetSetExternal.isExternal = (*abstractSignature)->Function()->IsExternal();
8013af6ab5fSopenharmony_ci        for (auto *const implemented : implementedSignatures) {
8023af6ab5fSopenharmony_ci            if (implemented->HasSignatureFlag(SignatureFlags::NEED_RETURN_TYPE)) {
8033af6ab5fSopenharmony_ci                implemented->OwnerVar()->Declaration()->Node()->Check(this);
8043af6ab5fSopenharmony_ci            }
8053af6ab5fSopenharmony_ci            Signature *substImplemented = AdjustForTypeParameters(*abstractSignature, implemented);
8063af6ab5fSopenharmony_ci
8073af6ab5fSopenharmony_ci            if (substImplemented == nullptr) {
8083af6ab5fSopenharmony_ci                continue;
8093af6ab5fSopenharmony_ci            }
8103af6ab5fSopenharmony_ci
8113af6ab5fSopenharmony_ci            if (!AreOverrideEquivalent(*abstractSignature, substImplemented) ||
8123af6ab5fSopenharmony_ci                !IsReturnTypeSubstitutable(substImplemented, *abstractSignature)) {
8133af6ab5fSopenharmony_ci                continue;
8143af6ab5fSopenharmony_ci            }
8153af6ab5fSopenharmony_ci
8163af6ab5fSopenharmony_ci            if ((*it)->CallSignatures().size() > 1) {
8173af6ab5fSopenharmony_ci                abstractSignature = (*it)->CallSignatures().erase(abstractSignature);
8183af6ab5fSopenharmony_ci                foundSignature = true;
8193af6ab5fSopenharmony_ci            } else {
8203af6ab5fSopenharmony_ci                it = abstractsToBeImplemented.erase(it);
8213af6ab5fSopenharmony_ci                functionOverridden = true;
8223af6ab5fSopenharmony_ci            }
8233af6ab5fSopenharmony_ci
8243af6ab5fSopenharmony_ci            break;
8253af6ab5fSopenharmony_ci        }
8263af6ab5fSopenharmony_ci
8273af6ab5fSopenharmony_ci        if (functionOverridden) {
8283af6ab5fSopenharmony_ci            break;
8293af6ab5fSopenharmony_ci        }
8303af6ab5fSopenharmony_ci
8313af6ab5fSopenharmony_ci        if (!foundSignature) {
8323af6ab5fSopenharmony_ci            ++abstractSignature;
8333af6ab5fSopenharmony_ci        }
8343af6ab5fSopenharmony_ci    }
8353af6ab5fSopenharmony_ci}
8363af6ab5fSopenharmony_ci
8373af6ab5fSopenharmony_civoid ETSChecker::ValidateNonOverriddenFunction(ETSObjectType *classType, ArenaVector<ETSFunctionType *>::iterator &it,
8383af6ab5fSopenharmony_ci                                               ArenaVector<ETSFunctionType *> &abstractsToBeImplemented,
8393af6ab5fSopenharmony_ci                                               bool &functionOverridden, const Accessor &isGetSet)
8403af6ab5fSopenharmony_ci{
8413af6ab5fSopenharmony_ci    auto superClassType = classType->SuperType();
8423af6ab5fSopenharmony_ci    while (!functionOverridden && superClassType != nullptr) {
8433af6ab5fSopenharmony_ci        for (auto *field : superClassType->Fields()) {
8443af6ab5fSopenharmony_ci            if (field->Name() == (*it)->Name()) {
8453af6ab5fSopenharmony_ci                auto *newProp =
8463af6ab5fSopenharmony_ci                    field->Declaration()->Node()->Clone(Allocator(), classType->GetDeclNode())->AsClassProperty();
8473af6ab5fSopenharmony_ci                newProp->AddModifier(ir::ModifierFlags::SUPER_OWNER);
8483af6ab5fSopenharmony_ci                newProp->AddModifier(isGetSet.isGetter && isGetSet.isSetter ? ir::ModifierFlags::GETTER_SETTER
8493af6ab5fSopenharmony_ci                                     : isGetSet.isGetter                    ? ir::ModifierFlags::GETTER
8503af6ab5fSopenharmony_ci                                                                            : ir::ModifierFlags::SETTER);
8513af6ab5fSopenharmony_ci                auto *newFieldDecl = Allocator()->New<varbinder::LetDecl>(newProp->Key()->AsIdentifier()->Name());
8523af6ab5fSopenharmony_ci                newFieldDecl->BindNode(newProp);
8533af6ab5fSopenharmony_ci
8543af6ab5fSopenharmony_ci                auto newFieldVar = classType->GetDeclNode()
8553af6ab5fSopenharmony_ci                                       ->Scope()
8563af6ab5fSopenharmony_ci                                       ->AsClassScope()
8573af6ab5fSopenharmony_ci                                       ->InstanceFieldScope()
8583af6ab5fSopenharmony_ci                                       ->AddDecl(Allocator(), newFieldDecl, ScriptExtension::ETS)
8593af6ab5fSopenharmony_ci                                       ->AsLocalVariable();
8603af6ab5fSopenharmony_ci                newFieldVar->AddFlag(varbinder::VariableFlags::PROPERTY);
8613af6ab5fSopenharmony_ci                newFieldVar->AddFlag(varbinder::VariableFlags::PUBLIC);
8623af6ab5fSopenharmony_ci                classType->AddProperty<PropertyType::INSTANCE_FIELD>(newFieldVar);
8633af6ab5fSopenharmony_ci                it = abstractsToBeImplemented.erase(it);
8643af6ab5fSopenharmony_ci                functionOverridden = true;
8653af6ab5fSopenharmony_ci                break;
8663af6ab5fSopenharmony_ci            }
8673af6ab5fSopenharmony_ci        }
8683af6ab5fSopenharmony_ci
8693af6ab5fSopenharmony_ci        superClassType = superClassType->SuperType();
8703af6ab5fSopenharmony_ci    }
8713af6ab5fSopenharmony_ci}
8723af6ab5fSopenharmony_ci
8733af6ab5fSopenharmony_civoid ETSChecker::ApplyModifiersAndRemoveImplementedAbstracts(ArenaVector<ETSFunctionType *>::iterator &it,
8743af6ab5fSopenharmony_ci                                                             ArenaVector<ETSFunctionType *> &abstractsToBeImplemented,
8753af6ab5fSopenharmony_ci                                                             ETSObjectType *classType, bool &functionOverridden,
8763af6ab5fSopenharmony_ci                                                             const Accessor &isGetSetExternal)
8773af6ab5fSopenharmony_ci{
8783af6ab5fSopenharmony_ci    for (auto *field : classType->Fields()) {
8793af6ab5fSopenharmony_ci        if (field->Name() == (*it)->Name()) {
8803af6ab5fSopenharmony_ci            field->Declaration()->Node()->AddModifier(isGetSetExternal.isGetter && isGetSetExternal.isSetter
8813af6ab5fSopenharmony_ci                                                          ? ir::ModifierFlags::GETTER_SETTER
8823af6ab5fSopenharmony_ci                                                      : isGetSetExternal.isGetter ? ir::ModifierFlags::GETTER
8833af6ab5fSopenharmony_ci                                                                                  : ir::ModifierFlags::SETTER);
8843af6ab5fSopenharmony_ci            it = abstractsToBeImplemented.erase(it);
8853af6ab5fSopenharmony_ci            functionOverridden = true;
8863af6ab5fSopenharmony_ci            break;
8873af6ab5fSopenharmony_ci        }
8883af6ab5fSopenharmony_ci    }
8893af6ab5fSopenharmony_ci}
8903af6ab5fSopenharmony_ci
8913af6ab5fSopenharmony_civoid ETSChecker::ValidateAbstractMethodsToBeImplemented(ArenaVector<ETSFunctionType *> &abstractsToBeImplemented,
8923af6ab5fSopenharmony_ci                                                        ETSObjectType *classType,
8933af6ab5fSopenharmony_ci                                                        const std::vector<Signature *> &implementedSignatures)
8943af6ab5fSopenharmony_ci{
8953af6ab5fSopenharmony_ci    SavedTypeRelationFlagsContext savedFlagsCtx(Relation(), TypeRelationFlag::NO_RETURN_TYPE_CHECK);
8963af6ab5fSopenharmony_ci    for (auto it = abstractsToBeImplemented.begin(); it != abstractsToBeImplemented.end();) {
8973af6ab5fSopenharmony_ci        bool functionOverridden = false;
8983af6ab5fSopenharmony_ci        Accessor isGetSetExternal;
8993af6ab5fSopenharmony_ci
9003af6ab5fSopenharmony_ci        ValidateAbstractSignature(it, abstractsToBeImplemented, implementedSignatures, functionOverridden,
9013af6ab5fSopenharmony_ci                                  isGetSetExternal);
9023af6ab5fSopenharmony_ci
9033af6ab5fSopenharmony_ci        if (functionOverridden) {
9043af6ab5fSopenharmony_ci            continue;
9053af6ab5fSopenharmony_ci        }
9063af6ab5fSopenharmony_ci
9073af6ab5fSopenharmony_ci        if (!isGetSetExternal.isGetter && !isGetSetExternal.isSetter) {
9083af6ab5fSopenharmony_ci            it++;
9093af6ab5fSopenharmony_ci            continue;
9103af6ab5fSopenharmony_ci        }
9113af6ab5fSopenharmony_ci
9123af6ab5fSopenharmony_ci        ApplyModifiersAndRemoveImplementedAbstracts(it, abstractsToBeImplemented, classType, functionOverridden,
9133af6ab5fSopenharmony_ci                                                    isGetSetExternal);
9143af6ab5fSopenharmony_ci
9153af6ab5fSopenharmony_ci        if (functionOverridden) {
9163af6ab5fSopenharmony_ci            continue;
9173af6ab5fSopenharmony_ci        }
9183af6ab5fSopenharmony_ci
9193af6ab5fSopenharmony_ci        ValidateNonOverriddenFunction(classType, it, abstractsToBeImplemented, functionOverridden, isGetSetExternal);
9203af6ab5fSopenharmony_ci
9213af6ab5fSopenharmony_ci        if (!functionOverridden) {
9223af6ab5fSopenharmony_ci            it++;
9233af6ab5fSopenharmony_ci        }
9243af6ab5fSopenharmony_ci    }
9253af6ab5fSopenharmony_ci}
9263af6ab5fSopenharmony_ci
9273af6ab5fSopenharmony_civoid ETSChecker::MaybeReportErrorsForOverridingValidation(ArenaVector<ETSFunctionType *> &abstractsToBeImplemented,
9283af6ab5fSopenharmony_ci                                                          ETSObjectType *classType, const lexer::SourcePosition &pos,
9293af6ab5fSopenharmony_ci                                                          bool reportError)
9303af6ab5fSopenharmony_ci{
9313af6ab5fSopenharmony_ci    if (!abstractsToBeImplemented.empty() && reportError) {
9323af6ab5fSopenharmony_ci        auto unimplementedSignature = abstractsToBeImplemented.front()->CallSignatures().front();
9333af6ab5fSopenharmony_ci        auto containingObjectName = GetContainingObjectNameFromSignature(unimplementedSignature);
9343af6ab5fSopenharmony_ci        if (unimplementedSignature->HasSignatureFlag(SignatureFlags::GETTER)) {
9353af6ab5fSopenharmony_ci            LogTypeError({classType->Name(), " is not abstract and does not implement getter for ",
9363af6ab5fSopenharmony_ci                          unimplementedSignature->Function()->Id()->Name(), " property in ", containingObjectName},
9373af6ab5fSopenharmony_ci                         pos);
9383af6ab5fSopenharmony_ci            return;
9393af6ab5fSopenharmony_ci        }
9403af6ab5fSopenharmony_ci        if (unimplementedSignature->HasSignatureFlag(SignatureFlags::SETTER)) {
9413af6ab5fSopenharmony_ci            LogTypeError({classType->Name(), " is not abstract and does not implement setter for ",
9423af6ab5fSopenharmony_ci                          unimplementedSignature->Function()->Id()->Name(), " property in ", containingObjectName},
9433af6ab5fSopenharmony_ci                         pos);
9443af6ab5fSopenharmony_ci            return;
9453af6ab5fSopenharmony_ci        }
9463af6ab5fSopenharmony_ci        LogTypeError({classType->Name(), " is not abstract and does not override abstract method ",
9473af6ab5fSopenharmony_ci                      unimplementedSignature->Function()->Id()->Name(), unimplementedSignature, " in ",
9483af6ab5fSopenharmony_ci                      containingObjectName},
9493af6ab5fSopenharmony_ci                     pos);
9503af6ab5fSopenharmony_ci    }
9513af6ab5fSopenharmony_ci}
9523af6ab5fSopenharmony_ci
9533af6ab5fSopenharmony_civoid ETSChecker::ValidateOverriding(ETSObjectType *classType, const lexer::SourcePosition &pos)
9543af6ab5fSopenharmony_ci{
9553af6ab5fSopenharmony_ci    if (classType->HasObjectFlag(ETSObjectFlags::CHECKED_COMPATIBLE_ABSTRACTS)) {
9563af6ab5fSopenharmony_ci        return;
9573af6ab5fSopenharmony_ci    }
9583af6ab5fSopenharmony_ci
9593af6ab5fSopenharmony_ci    bool throwError = true;
9603af6ab5fSopenharmony_ci    if (classType->HasObjectFlag(ETSObjectFlags::ABSTRACT)) {
9613af6ab5fSopenharmony_ci        throwError = false;
9623af6ab5fSopenharmony_ci    }
9633af6ab5fSopenharmony_ci
9643af6ab5fSopenharmony_ci    if (classType->SuperType() != nullptr) {
9653af6ab5fSopenharmony_ci        ValidateOverriding(classType->SuperType(), classType->SuperType()->GetDeclNode()->Start());
9663af6ab5fSopenharmony_ci    }
9673af6ab5fSopenharmony_ci
9683af6ab5fSopenharmony_ci    auto &abstractsToBeImplemented = GetAbstractsForClass(classType);
9693af6ab5fSopenharmony_ci    std::vector<Signature *> implementedSignatures;
9703af6ab5fSopenharmony_ci
9713af6ab5fSopenharmony_ci    // Since interfaces can define function bodies we have to collect the implemented ones first
9723af6ab5fSopenharmony_ci    CollectImplementedMethodsFromInterfaces(classType, &implementedSignatures, abstractsToBeImplemented);
9733af6ab5fSopenharmony_ci    CheckInterfaceFunctions(classType);
9743af6ab5fSopenharmony_ci
9753af6ab5fSopenharmony_ci    auto *superIter = classType;
9763af6ab5fSopenharmony_ci    do {
9773af6ab5fSopenharmony_ci        for (auto &it : abstractsToBeImplemented) {
9783af6ab5fSopenharmony_ci            for (const auto &prop : superIter->Methods()) {
9793af6ab5fSopenharmony_ci                GetTypeOfVariable(prop);
9803af6ab5fSopenharmony_ci                AddImplementedSignature(&implementedSignatures, prop, it);
9813af6ab5fSopenharmony_ci            }
9823af6ab5fSopenharmony_ci        }
9833af6ab5fSopenharmony_ci        superIter = superIter->SuperType();
9843af6ab5fSopenharmony_ci    } while (superIter != nullptr);
9853af6ab5fSopenharmony_ci    ValidateAbstractMethodsToBeImplemented(abstractsToBeImplemented, classType, implementedSignatures);
9863af6ab5fSopenharmony_ci    MaybeReportErrorsForOverridingValidation(abstractsToBeImplemented, classType, pos, throwError);
9873af6ab5fSopenharmony_ci
9883af6ab5fSopenharmony_ci    classType->AddObjectFlag(ETSObjectFlags::CHECKED_COMPATIBLE_ABSTRACTS);
9893af6ab5fSopenharmony_ci}
9903af6ab5fSopenharmony_ci
9913af6ab5fSopenharmony_civoid ETSChecker::AddImplementedSignature(std::vector<Signature *> *implementedSignatures,
9923af6ab5fSopenharmony_ci                                         varbinder::LocalVariable *function, ETSFunctionType *it)
9933af6ab5fSopenharmony_ci{
9943af6ab5fSopenharmony_ci    if (!function->TsType()->IsETSFunctionType()) {
9953af6ab5fSopenharmony_ci        return;
9963af6ab5fSopenharmony_ci    }
9973af6ab5fSopenharmony_ci
9983af6ab5fSopenharmony_ci    for (auto signature : function->TsType()->AsETSFunctionType()->CallSignatures()) {
9993af6ab5fSopenharmony_ci        if (signature->Function()->IsAbstract() || signature->Function()->IsStatic()) {
10003af6ab5fSopenharmony_ci            continue;
10013af6ab5fSopenharmony_ci        }
10023af6ab5fSopenharmony_ci
10033af6ab5fSopenharmony_ci        if (signature->Function()->Id()->Name() == it->Name()) {
10043af6ab5fSopenharmony_ci            implementedSignatures->emplace_back(signature);
10053af6ab5fSopenharmony_ci        }
10063af6ab5fSopenharmony_ci    }
10073af6ab5fSopenharmony_ci}
10083af6ab5fSopenharmony_ci
10093af6ab5fSopenharmony_civoid ETSChecker::CheckLocalClass(ir::ClassDefinition *classDef, CheckerStatus &checkerStatus)
10103af6ab5fSopenharmony_ci{
10113af6ab5fSopenharmony_ci    if (classDef->IsLocal()) {
10123af6ab5fSopenharmony_ci        checkerStatus |= CheckerStatus::IN_LOCAL_CLASS;
10133af6ab5fSopenharmony_ci        if (!classDef->Parent()->Parent()->IsBlockStatement()) {
10143af6ab5fSopenharmony_ci            LogTypeError("Local classes must be defined between balanced braces", classDef->Start());
10153af6ab5fSopenharmony_ci        }
10163af6ab5fSopenharmony_ci    }
10173af6ab5fSopenharmony_ci}
10183af6ab5fSopenharmony_ci
10193af6ab5fSopenharmony_civoid ETSChecker::CheckClassDefinition(ir::ClassDefinition *classDef)
10203af6ab5fSopenharmony_ci{
10213af6ab5fSopenharmony_ci    classDef->SetClassDefinitionChecked();
10223af6ab5fSopenharmony_ci    auto *classType = classDef->TsTypeOrError()->AsETSObjectType();
10233af6ab5fSopenharmony_ci    if (classType->SuperType() != nullptr) {
10243af6ab5fSopenharmony_ci        classType->SuperType()->GetDeclNode()->Check(this);
10253af6ab5fSopenharmony_ci    }
10263af6ab5fSopenharmony_ci
10273af6ab5fSopenharmony_ci    auto newStatus = checker::CheckerStatus::IN_CLASS;
10283af6ab5fSopenharmony_ci    if (Context().ContainingClass() != classType) {
10293af6ab5fSopenharmony_ci        classType->SetEnclosingType(Context().ContainingClass());
10303af6ab5fSopenharmony_ci    }
10313af6ab5fSopenharmony_ci
10323af6ab5fSopenharmony_ci    if (classDef->IsInner()) {
10333af6ab5fSopenharmony_ci        newStatus |= CheckerStatus::INNER_CLASS;
10343af6ab5fSopenharmony_ci        classType->AddObjectFlag(checker::ETSObjectFlags::INNER);
10353af6ab5fSopenharmony_ci    }
10363af6ab5fSopenharmony_ci
10373af6ab5fSopenharmony_ci    classDef->IsGlobal() ? classType->AddObjectFlag(checker::ETSObjectFlags::GLOBAL)
10383af6ab5fSopenharmony_ci                         : CheckLocalClass(classDef, newStatus);
10393af6ab5fSopenharmony_ci
10403af6ab5fSopenharmony_ci    checker::ScopeContext scopeCtx(this, classDef->Scope());
10413af6ab5fSopenharmony_ci    auto savedContext = SavedCheckerContext(this, newStatus, classType);
10423af6ab5fSopenharmony_ci
10433af6ab5fSopenharmony_ci    ResolveDeclaredMembersOfObject(classType);
10443af6ab5fSopenharmony_ci
10453af6ab5fSopenharmony_ci    if (classDef->IsAbstract()) {
10463af6ab5fSopenharmony_ci        AddStatus(checker::CheckerStatus::IN_ABSTRACT);
10473af6ab5fSopenharmony_ci        classType->AddObjectFlag(checker::ETSObjectFlags::ABSTRACT);
10483af6ab5fSopenharmony_ci    }
10493af6ab5fSopenharmony_ci
10503af6ab5fSopenharmony_ci    if (classDef->IsStatic() && !Context().ContainingClass()->HasObjectFlag(ETSObjectFlags::GLOBAL)) {
10513af6ab5fSopenharmony_ci        AddStatus(checker::CheckerStatus::IN_STATIC_CONTEXT);
10523af6ab5fSopenharmony_ci    }
10533af6ab5fSopenharmony_ci
10543af6ab5fSopenharmony_ci    // NOTE(gogabr): temporary, until we have proper bridges, see #16485
10553af6ab5fSopenharmony_ci    // Don't check overriding for synthetic functional classes.
10563af6ab5fSopenharmony_ci    if ((static_cast<ir::AstNode *>(classDef)->Modifiers() & ir::ModifierFlags::FUNCTIONAL) == 0) {
10573af6ab5fSopenharmony_ci        ValidateOverriding(classType, classDef->Start());
10583af6ab5fSopenharmony_ci    }
10593af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
10603af6ab5fSopenharmony_ci    TransformProperties(classType);
10613af6ab5fSopenharmony_ci
10623af6ab5fSopenharmony_ci    for (auto *it : classDef->Body()) {
10633af6ab5fSopenharmony_ci        if (it->IsClassProperty()) {
10643af6ab5fSopenharmony_ci            it->Check(this);
10653af6ab5fSopenharmony_ci        }
10663af6ab5fSopenharmony_ci    }
10673af6ab5fSopenharmony_ci
10683af6ab5fSopenharmony_ci    for (auto *it : classDef->Body()) {
10693af6ab5fSopenharmony_ci        if (!it->IsClassProperty()) {
10703af6ab5fSopenharmony_ci            it->Check(this);
10713af6ab5fSopenharmony_ci        }
10723af6ab5fSopenharmony_ci    }
10733af6ab5fSopenharmony_ci
10743af6ab5fSopenharmony_ci    if (classDef->IsGlobal() || classType->SuperType() == nullptr) {
10753af6ab5fSopenharmony_ci        return;
10763af6ab5fSopenharmony_ci    }
10773af6ab5fSopenharmony_ci
10783af6ab5fSopenharmony_ci    CheckConstructors(classDef, classType);
10793af6ab5fSopenharmony_ci    CheckValidInheritance(classType, classDef);
10803af6ab5fSopenharmony_ci    CheckConstFields(classType);
10813af6ab5fSopenharmony_ci    CheckGetterSetterProperties(classType);
10823af6ab5fSopenharmony_ci    CheckInvokeMethodsLegitimacy(classType);
10833af6ab5fSopenharmony_ci}
10843af6ab5fSopenharmony_ci
10853af6ab5fSopenharmony_civoid ETSChecker::CheckConstructors(ir::ClassDefinition *classDef, ETSObjectType *classType)
10863af6ab5fSopenharmony_ci{
10873af6ab5fSopenharmony_ci    if (!classDef->IsDeclare()) {
10883af6ab5fSopenharmony_ci        for (auto *it : classType->ConstructSignatures()) {
10893af6ab5fSopenharmony_ci            CheckCyclicConstructorCall(it);
10903af6ab5fSopenharmony_ci            CheckImplicitSuper(classType, it);
10913af6ab5fSopenharmony_ci            CheckThisOrSuperCallInConstructor(classType, it);
10923af6ab5fSopenharmony_ci        }
10933af6ab5fSopenharmony_ci    }
10943af6ab5fSopenharmony_ci}
10953af6ab5fSopenharmony_ci
10963af6ab5fSopenharmony_cibool IsAsyncMethod(ir::AstNode *node)
10973af6ab5fSopenharmony_ci{
10983af6ab5fSopenharmony_ci    if (!node->IsMethodDefinition()) {
10993af6ab5fSopenharmony_ci        return false;
11003af6ab5fSopenharmony_ci    }
11013af6ab5fSopenharmony_ci    auto *method = node->AsMethodDefinition();
11023af6ab5fSopenharmony_ci    return method->Function()->IsAsyncFunc() && !method->Function()->IsProxy();
11033af6ab5fSopenharmony_ci}
11043af6ab5fSopenharmony_ci
11053af6ab5fSopenharmony_civoid ETSChecker::CreateAsyncProxyMethods(ir::ClassDefinition *classDef)
11063af6ab5fSopenharmony_ci{
11073af6ab5fSopenharmony_ci    ArenaVector<ir::MethodDefinition *> asyncImpls(Allocator()->Adapter());
11083af6ab5fSopenharmony_ci
11093af6ab5fSopenharmony_ci    for (auto *it : classDef->Body()) {
11103af6ab5fSopenharmony_ci        if (!IsAsyncMethod(it)) {
11113af6ab5fSopenharmony_ci            continue;
11123af6ab5fSopenharmony_ci        }
11133af6ab5fSopenharmony_ci
11143af6ab5fSopenharmony_ci        auto *asyncMethod = it->AsMethodDefinition();
11153af6ab5fSopenharmony_ci        auto *proxy = CreateAsyncProxy(asyncMethod, classDef);
11163af6ab5fSopenharmony_ci        asyncImpls.push_back(proxy);
11173af6ab5fSopenharmony_ci
11183af6ab5fSopenharmony_ci        for (auto *overload : asyncMethod->Overloads()) {
11193af6ab5fSopenharmony_ci            if (!IsAsyncMethod(overload)) {
11203af6ab5fSopenharmony_ci                continue;
11213af6ab5fSopenharmony_ci            }
11223af6ab5fSopenharmony_ci
11233af6ab5fSopenharmony_ci            auto *impl = CreateAsyncProxy(overload, classDef, false);
11243af6ab5fSopenharmony_ci            impl->Function()->Id()->SetVariable(proxy->Function()->Id()->Variable());
11253af6ab5fSopenharmony_ci            proxy->AddOverload(impl);
11263af6ab5fSopenharmony_ci        }
11273af6ab5fSopenharmony_ci    }
11283af6ab5fSopenharmony_ci
11293af6ab5fSopenharmony_ci    for (auto *it : asyncImpls) {
11303af6ab5fSopenharmony_ci        it->SetParent(classDef);
11313af6ab5fSopenharmony_ci        it->Check(this);
11323af6ab5fSopenharmony_ci        classDef->Body().push_back(it);
11333af6ab5fSopenharmony_ci    }
11343af6ab5fSopenharmony_ci}
11353af6ab5fSopenharmony_ci
11363af6ab5fSopenharmony_civoid ETSChecker::CheckImplicitSuper(ETSObjectType *classType, Signature *ctorSig)
11373af6ab5fSopenharmony_ci{
11383af6ab5fSopenharmony_ci    if (classType == GlobalETSObjectType()) {
11393af6ab5fSopenharmony_ci        return;
11403af6ab5fSopenharmony_ci    }
11413af6ab5fSopenharmony_ci
11423af6ab5fSopenharmony_ci    auto &stmts = ctorSig->Function()->Body()->AsBlockStatement()->Statements();
11433af6ab5fSopenharmony_ci    const auto thisCall = std::find_if(stmts.begin(), stmts.end(), [](const ir::Statement *stmt) {
11443af6ab5fSopenharmony_ci        return stmt->IsExpressionStatement() && stmt->AsExpressionStatement()->GetExpression()->IsCallExpression() &&
11453af6ab5fSopenharmony_ci               stmt->AsExpressionStatement()->GetExpression()->AsCallExpression()->Callee()->IsThisExpression();
11463af6ab5fSopenharmony_ci    });
11473af6ab5fSopenharmony_ci    // There is an alternate constructor invocation, no need for super constructor invocation
11483af6ab5fSopenharmony_ci    if (thisCall != stmts.end()) {
11493af6ab5fSopenharmony_ci        return;
11503af6ab5fSopenharmony_ci    }
11513af6ab5fSopenharmony_ci
11523af6ab5fSopenharmony_ci    const auto superExpr = std::find_if(stmts.begin(), stmts.end(), [](const ir::Statement *stmt) {
11533af6ab5fSopenharmony_ci        return stmt->IsExpressionStatement() && stmt->AsExpressionStatement()->GetExpression()->IsCallExpression() &&
11543af6ab5fSopenharmony_ci               stmt->AsExpressionStatement()->GetExpression()->AsCallExpression()->Callee()->IsSuperExpression();
11553af6ab5fSopenharmony_ci    });
11563af6ab5fSopenharmony_ci    // There is no super expression
11573af6ab5fSopenharmony_ci    if (superExpr == stmts.end()) {
11583af6ab5fSopenharmony_ci        const auto superTypeCtorSigs = classType->SuperType()->ConstructSignatures();
11593af6ab5fSopenharmony_ci        const auto superTypeCtorSig = std::find_if(superTypeCtorSigs.begin(), superTypeCtorSigs.end(),
11603af6ab5fSopenharmony_ci                                                   [](const Signature *sig) { return sig->Params().empty(); });
11613af6ab5fSopenharmony_ci        // Super type has no parameterless ctor
11623af6ab5fSopenharmony_ci        if (superTypeCtorSig == superTypeCtorSigs.end()) {
11633af6ab5fSopenharmony_ci            LogTypeError("Must call super constructor", ctorSig->Function()->Start());
11643af6ab5fSopenharmony_ci        }
11653af6ab5fSopenharmony_ci
11663af6ab5fSopenharmony_ci        ctorSig->Function()->AddFlag(ir::ScriptFunctionFlags::IMPLICIT_SUPER_CALL_NEEDED);
11673af6ab5fSopenharmony_ci    }
11683af6ab5fSopenharmony_ci}
11693af6ab5fSopenharmony_ci
11703af6ab5fSopenharmony_civoid ETSChecker::CheckThisOrSuperCallInConstructor(ETSObjectType *classType, Signature *ctorSig)
11713af6ab5fSopenharmony_ci{
11723af6ab5fSopenharmony_ci    if (classType == GlobalETSObjectType()) {
11733af6ab5fSopenharmony_ci        return;
11743af6ab5fSopenharmony_ci    }
11753af6ab5fSopenharmony_ci
11763af6ab5fSopenharmony_ci    for (auto it : ctorSig->Function()->Body()->AsBlockStatement()->Statements()) {
11773af6ab5fSopenharmony_ci        if (it->IsExpressionStatement() && it->AsExpressionStatement()->GetExpression()->IsCallExpression() &&
11783af6ab5fSopenharmony_ci            (it->AsExpressionStatement()->GetExpression()->AsCallExpression()->Callee()->IsThisExpression() ||
11793af6ab5fSopenharmony_ci             it->AsExpressionStatement()->GetExpression()->AsCallExpression()->Callee()->IsSuperExpression())) {
11803af6ab5fSopenharmony_ci            ArenaVector<const ir::Expression *> expressions =
11813af6ab5fSopenharmony_ci                ArenaVector<const ir::Expression *>(Allocator()->Adapter());
11823af6ab5fSopenharmony_ci            expressions.insert(expressions.end(),
11833af6ab5fSopenharmony_ci                               it->AsExpressionStatement()->GetExpression()->AsCallExpression()->Arguments().begin(),
11843af6ab5fSopenharmony_ci                               it->AsExpressionStatement()->GetExpression()->AsCallExpression()->Arguments().end());
11853af6ab5fSopenharmony_ci            CheckExpressionsInConstructor(expressions);
11863af6ab5fSopenharmony_ci        }
11873af6ab5fSopenharmony_ci    }
11883af6ab5fSopenharmony_ci}
11893af6ab5fSopenharmony_ci
11903af6ab5fSopenharmony_civoid ETSChecker::CheckExpressionsInConstructor(const ArenaVector<const ir::Expression *> &arguments)
11913af6ab5fSopenharmony_ci{
11923af6ab5fSopenharmony_ci    for (auto *arg : arguments) {
11933af6ab5fSopenharmony_ci        auto expressions = CheckMemberOrCallOrObjectExpressionInConstructor(arg);
11943af6ab5fSopenharmony_ci
11953af6ab5fSopenharmony_ci        if (arg->IsETSNewClassInstanceExpression()) {
11963af6ab5fSopenharmony_ci            expressions.insert(expressions.end(), arg->AsETSNewClassInstanceExpression()->GetArguments().begin(),
11973af6ab5fSopenharmony_ci                               arg->AsETSNewClassInstanceExpression()->GetArguments().end());
11983af6ab5fSopenharmony_ci        } else if (arg->IsArrayExpression()) {
11993af6ab5fSopenharmony_ci            expressions.insert(expressions.end(), arg->AsArrayExpression()->Elements().begin(),
12003af6ab5fSopenharmony_ci                               arg->AsArrayExpression()->Elements().end());
12013af6ab5fSopenharmony_ci        } else if (arg->IsBinaryExpression()) {
12023af6ab5fSopenharmony_ci            expressions.push_back(arg->AsBinaryExpression()->Left());
12033af6ab5fSopenharmony_ci            expressions.push_back(arg->AsBinaryExpression()->Right());
12043af6ab5fSopenharmony_ci        } else if (arg->IsAssignmentExpression()) {
12053af6ab5fSopenharmony_ci            expressions.push_back(arg->AsAssignmentExpression()->Left());
12063af6ab5fSopenharmony_ci            expressions.push_back(arg->AsAssignmentExpression()->Right());
12073af6ab5fSopenharmony_ci        } else if (arg->IsTSAsExpression()) {
12083af6ab5fSopenharmony_ci            expressions.push_back(arg->AsTSAsExpression()->Expr());
12093af6ab5fSopenharmony_ci        } else if (arg->IsConditionalExpression()) {
12103af6ab5fSopenharmony_ci            expressions.push_back(arg->AsConditionalExpression()->Test());
12113af6ab5fSopenharmony_ci            expressions.push_back(arg->AsConditionalExpression()->Consequent());
12123af6ab5fSopenharmony_ci            expressions.push_back(arg->AsConditionalExpression()->Alternate());
12133af6ab5fSopenharmony_ci        } else if (arg->IsTypeofExpression()) {
12143af6ab5fSopenharmony_ci            expressions.push_back(arg->AsTypeofExpression()->Argument());
12153af6ab5fSopenharmony_ci        } else if (arg->IsTSNonNullExpression()) {
12163af6ab5fSopenharmony_ci            expressions.push_back(arg->AsTSNonNullExpression()->Expr());
12173af6ab5fSopenharmony_ci        } else if (arg->IsUnaryExpression()) {
12183af6ab5fSopenharmony_ci            expressions.push_back(arg->AsUnaryExpression()->Argument());
12193af6ab5fSopenharmony_ci        } else if (arg->IsUpdateExpression()) {
12203af6ab5fSopenharmony_ci            expressions.push_back(arg->AsUpdateExpression()->Argument());
12213af6ab5fSopenharmony_ci        }
12223af6ab5fSopenharmony_ci
12233af6ab5fSopenharmony_ci        if (!expressions.empty()) {
12243af6ab5fSopenharmony_ci            CheckExpressionsInConstructor(expressions);
12253af6ab5fSopenharmony_ci        }
12263af6ab5fSopenharmony_ci    }
12273af6ab5fSopenharmony_ci}
12283af6ab5fSopenharmony_ci
12293af6ab5fSopenharmony_ciArenaVector<const ir::Expression *> ETSChecker::CheckMemberOrCallOrObjectExpressionInConstructor(
12303af6ab5fSopenharmony_ci    const ir::Expression *arg)
12313af6ab5fSopenharmony_ci{
12323af6ab5fSopenharmony_ci    ArenaVector<const ir::Expression *> expressions = ArenaVector<const ir::Expression *>(Allocator()->Adapter());
12333af6ab5fSopenharmony_ci
12343af6ab5fSopenharmony_ci    if (arg->IsMemberExpression()) {
12353af6ab5fSopenharmony_ci        if ((arg->AsMemberExpression()->Object()->IsSuperExpression() ||
12363af6ab5fSopenharmony_ci             arg->AsMemberExpression()->Object()->IsThisExpression())) {
12373af6ab5fSopenharmony_ci            std::stringstream ss;
12383af6ab5fSopenharmony_ci            ss << "Using " << (arg->AsMemberExpression()->Object()->IsSuperExpression() ? "super" : "this")
12393af6ab5fSopenharmony_ci               << " is not allowed in constructor";
12403af6ab5fSopenharmony_ci            LogTypeError(ss.str(), arg->Start());
12413af6ab5fSopenharmony_ci        }
12423af6ab5fSopenharmony_ci
12433af6ab5fSopenharmony_ci        expressions.push_back(arg->AsMemberExpression()->Property());
12443af6ab5fSopenharmony_ci        expressions.push_back(arg->AsMemberExpression()->Object());
12453af6ab5fSopenharmony_ci    } else if (arg->IsCallExpression()) {
12463af6ab5fSopenharmony_ci        expressions.insert(expressions.end(), arg->AsCallExpression()->Arguments().begin(),
12473af6ab5fSopenharmony_ci                           arg->AsCallExpression()->Arguments().end());
12483af6ab5fSopenharmony_ci
12493af6ab5fSopenharmony_ci        if (arg->AsCallExpression()->Callee()->IsMemberExpression() &&
12503af6ab5fSopenharmony_ci            (arg->AsCallExpression()->Callee()->AsMemberExpression()->Object()->IsSuperExpression() ||
12513af6ab5fSopenharmony_ci             arg->AsCallExpression()->Callee()->AsMemberExpression()->Object()->IsThisExpression()) &&
12523af6ab5fSopenharmony_ci            !arg->AsCallExpression()->Callee()->AsMemberExpression()->Property()->IsStatic()) {
12533af6ab5fSopenharmony_ci            std::stringstream ss;
12543af6ab5fSopenharmony_ci            ss << "Using "
12553af6ab5fSopenharmony_ci               << (arg->AsCallExpression()->Callee()->AsMemberExpression()->IsSuperExpression() ? "super" : "this")
12563af6ab5fSopenharmony_ci               << " is not allowed in constructor";
12573af6ab5fSopenharmony_ci            LogTypeError(ss.str(), arg->Start());
12583af6ab5fSopenharmony_ci        }
12593af6ab5fSopenharmony_ci    } else if (arg->IsObjectExpression()) {
12603af6ab5fSopenharmony_ci        for (auto *prop : arg->AsObjectExpression()->Properties()) {
12613af6ab5fSopenharmony_ci            expressions.push_back(prop->AsProperty()->Value());
12623af6ab5fSopenharmony_ci        }
12633af6ab5fSopenharmony_ci    }
12643af6ab5fSopenharmony_ci
12653af6ab5fSopenharmony_ci    return expressions;
12663af6ab5fSopenharmony_ci}
12673af6ab5fSopenharmony_ci
12683af6ab5fSopenharmony_civoid ETSChecker::CheckConstFields(const ETSObjectType *classType)
12693af6ab5fSopenharmony_ci{
12703af6ab5fSopenharmony_ci    for (const auto &prop : classType->Fields()) {
12713af6ab5fSopenharmony_ci        if (!(prop->Declaration()->IsConstDecl() || prop->Declaration()->IsReadonlyDecl()) ||
12723af6ab5fSopenharmony_ci            !prop->HasFlag(varbinder::VariableFlags::EXPLICIT_INIT_REQUIRED)) {
12733af6ab5fSopenharmony_ci            continue;
12743af6ab5fSopenharmony_ci        }
12753af6ab5fSopenharmony_ci        CheckConstFieldInitialized(classType, prop);
12763af6ab5fSopenharmony_ci    }
12773af6ab5fSopenharmony_ci}
12783af6ab5fSopenharmony_ci
12793af6ab5fSopenharmony_civoid ETSChecker::CheckConstFieldInitialized(const ETSObjectType *classType, varbinder::LocalVariable *classVar)
12803af6ab5fSopenharmony_ci{
12813af6ab5fSopenharmony_ci    const bool classVarStatic = classVar->Declaration()->Node()->AsClassProperty()->IsStatic();
12823af6ab5fSopenharmony_ci    for (const auto &prop : classType->Methods()) {
12833af6ab5fSopenharmony_ci        if (!prop->TsType()->IsETSFunctionType()) {
12843af6ab5fSopenharmony_ci            continue;
12853af6ab5fSopenharmony_ci        }
12863af6ab5fSopenharmony_ci
12873af6ab5fSopenharmony_ci        const auto &callSigs = prop->TsType()->AsETSFunctionType()->CallSignatures();
12883af6ab5fSopenharmony_ci        for (const auto *signature : callSigs) {
12893af6ab5fSopenharmony_ci            if ((signature->Function()->IsConstructor() && !classVarStatic) ||
12903af6ab5fSopenharmony_ci                (signature->Function()->IsStaticBlock() && classVarStatic)) {
12913af6ab5fSopenharmony_ci                CheckConstFieldInitialized(signature, classVar);
12923af6ab5fSopenharmony_ci            }
12933af6ab5fSopenharmony_ci        }
12943af6ab5fSopenharmony_ci    }
12953af6ab5fSopenharmony_ci}
12963af6ab5fSopenharmony_ci
12973af6ab5fSopenharmony_civoid ETSChecker::FindAssignment(const ir::AstNode *node, const varbinder::LocalVariable *classVar, bool &initialized)
12983af6ab5fSopenharmony_ci{
12993af6ab5fSopenharmony_ci    if (node->IsAssignmentExpression() && node->AsAssignmentExpression()->Target() == classVar) {
13003af6ab5fSopenharmony_ci        if (initialized) {
13013af6ab5fSopenharmony_ci            LogTypeError({"Variable '", classVar->Declaration()->Name(), "' might already have been initialized"},
13023af6ab5fSopenharmony_ci                         node->Start());
13033af6ab5fSopenharmony_ci        }
13043af6ab5fSopenharmony_ci
13053af6ab5fSopenharmony_ci        initialized = true;
13063af6ab5fSopenharmony_ci        return;
13073af6ab5fSopenharmony_ci    }
13083af6ab5fSopenharmony_ci
13093af6ab5fSopenharmony_ci    FindAssignments(node, classVar, initialized);
13103af6ab5fSopenharmony_ci}
13113af6ab5fSopenharmony_ci
13123af6ab5fSopenharmony_civoid ETSChecker::FindAssignments(const ir::AstNode *node, const varbinder::LocalVariable *classVar, bool &initialized)
13133af6ab5fSopenharmony_ci{
13143af6ab5fSopenharmony_ci    node->Iterate(
13153af6ab5fSopenharmony_ci        [this, classVar, &initialized](ir::AstNode *childNode) { FindAssignment(childNode, classVar, initialized); });
13163af6ab5fSopenharmony_ci}
13173af6ab5fSopenharmony_ci
13183af6ab5fSopenharmony_civoid ETSChecker::CheckConstFieldInitialized(const Signature *signature, varbinder::LocalVariable *classVar)
13193af6ab5fSopenharmony_ci{
13203af6ab5fSopenharmony_ci    bool initialized = false;
13213af6ab5fSopenharmony_ci    const auto &stmts = signature->Function()->Body()->AsBlockStatement()->Statements();
13223af6ab5fSopenharmony_ci    const auto it = stmts.begin();
13233af6ab5fSopenharmony_ci    if (it != stmts.end()) {
13243af6ab5fSopenharmony_ci        if (const auto *first = *it;
13253af6ab5fSopenharmony_ci            first->IsExpressionStatement() && first->AsExpressionStatement()->GetExpression()->IsCallExpression() &&
13263af6ab5fSopenharmony_ci            first->AsExpressionStatement()->GetExpression()->AsCallExpression()->Callee()->IsThisExpression()) {
13273af6ab5fSopenharmony_ci            initialized = true;
13283af6ab5fSopenharmony_ci        }
13293af6ab5fSopenharmony_ci    }
13303af6ab5fSopenharmony_ci
13313af6ab5fSopenharmony_ci    // NOTE: szd. control flow
13323af6ab5fSopenharmony_ci    FindAssignments(signature->Function()->Body(), classVar, initialized);
13333af6ab5fSopenharmony_ci    if (!initialized) {
13343af6ab5fSopenharmony_ci        LogTypeError({"Variable '", classVar->Declaration()->Name(), "' might not have been initialized"},
13353af6ab5fSopenharmony_ci                     signature->Function()->End());
13363af6ab5fSopenharmony_ci    }
13373af6ab5fSopenharmony_ci
13383af6ab5fSopenharmony_ci    classVar->RemoveFlag(varbinder::VariableFlags::EXPLICIT_INIT_REQUIRED);
13393af6ab5fSopenharmony_ci}
13403af6ab5fSopenharmony_ci
13413af6ab5fSopenharmony_civoid ETSChecker::CheckInnerClassMembers(const ETSObjectType *classType)
13423af6ab5fSopenharmony_ci{
13433af6ab5fSopenharmony_ci    for (const auto &[_, it] : classType->StaticMethods()) {
13443af6ab5fSopenharmony_ci        (void)_;
13453af6ab5fSopenharmony_ci        LogTypeError("Inner class cannot have static methods", it->Declaration()->Node()->Start());
13463af6ab5fSopenharmony_ci    }
13473af6ab5fSopenharmony_ci
13483af6ab5fSopenharmony_ci    for (const auto &[_, it] : classType->StaticFields()) {
13493af6ab5fSopenharmony_ci        (void)_;
13503af6ab5fSopenharmony_ci        if (!it->Declaration()->IsReadonlyDecl()) {
13513af6ab5fSopenharmony_ci            LogTypeError("Inner class cannot have non-readonly static properties", it->Declaration()->Node()->Start());
13523af6ab5fSopenharmony_ci        }
13533af6ab5fSopenharmony_ci    }
13543af6ab5fSopenharmony_ci}
13553af6ab5fSopenharmony_ci
13563af6ab5fSopenharmony_cibool ETSChecker::ValidateArrayIndex(ir::Expression *const expr, bool relaxed)
13573af6ab5fSopenharmony_ci{
13583af6ab5fSopenharmony_ci    auto *const expressionType = expr->Check(this);
13593af6ab5fSopenharmony_ci    auto const *const unboxedExpressionType = ETSBuiltinTypeAsPrimitiveType(expressionType);
13603af6ab5fSopenharmony_ci
13613af6ab5fSopenharmony_ci    Type const *const indexType = ApplyUnaryOperatorPromotion(expressionType);
13623af6ab5fSopenharmony_ci
13633af6ab5fSopenharmony_ci    if (expressionType->IsETSObjectType() && (unboxedExpressionType != nullptr)) {
13643af6ab5fSopenharmony_ci        expr->AddBoxingUnboxingFlags(GetUnboxingFlag(unboxedExpressionType));
13653af6ab5fSopenharmony_ci    }
13663af6ab5fSopenharmony_ci
13673af6ab5fSopenharmony_ci    if (relaxed && indexType != nullptr && indexType->HasTypeFlag(TypeFlag::ETS_FLOATING_POINT)) {
13683af6ab5fSopenharmony_ci        if (!expr->IsNumberLiteral()) {
13693af6ab5fSopenharmony_ci            return true;
13703af6ab5fSopenharmony_ci        }
13713af6ab5fSopenharmony_ci
13723af6ab5fSopenharmony_ci        auto num = expr->AsNumberLiteral()->Number();
13733af6ab5fSopenharmony_ci        ASSERT(num.IsReal());
13743af6ab5fSopenharmony_ci        double value = num.GetDouble();
13753af6ab5fSopenharmony_ci        double intpart;
13763af6ab5fSopenharmony_ci        if (std::modf(value, &intpart) != 0.0) {
13773af6ab5fSopenharmony_ci            LogTypeError("Index fractional part should be zero.", expr->Start());
13783af6ab5fSopenharmony_ci            return false;
13793af6ab5fSopenharmony_ci        }
13803af6ab5fSopenharmony_ci        return true;
13813af6ab5fSopenharmony_ci    }
13823af6ab5fSopenharmony_ci
13833af6ab5fSopenharmony_ci    if (indexType == nullptr || !indexType->HasTypeFlag(TypeFlag::ETS_ARRAY_INDEX)) {
13843af6ab5fSopenharmony_ci        std::stringstream message("");
13853af6ab5fSopenharmony_ci        if (expressionType->IsNonPrimitiveType()) {
13863af6ab5fSopenharmony_ci            message << expressionType->Variable()->Name();
13873af6ab5fSopenharmony_ci        } else {
13883af6ab5fSopenharmony_ci            expressionType->ToString(message);
13893af6ab5fSopenharmony_ci        }
13903af6ab5fSopenharmony_ci
13913af6ab5fSopenharmony_ci        LogTypeError(
13923af6ab5fSopenharmony_ci            "Type '" + message.str() +
13933af6ab5fSopenharmony_ci                "' cannot be used as an index type. Only primitive or unboxable integral types can be used as index.",
13943af6ab5fSopenharmony_ci            expr->Start());
13953af6ab5fSopenharmony_ci        return false;
13963af6ab5fSopenharmony_ci    }
13973af6ab5fSopenharmony_ci
13983af6ab5fSopenharmony_ci    return true;
13993af6ab5fSopenharmony_ci}
14003af6ab5fSopenharmony_ci
14013af6ab5fSopenharmony_cistd::optional<int32_t> ETSChecker::GetTupleElementAccessValue(const Type *const type, const lexer::SourcePosition &pos)
14023af6ab5fSopenharmony_ci{
14033af6ab5fSopenharmony_ci    ASSERT(type->HasTypeFlag(TypeFlag::CONSTANT | TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC));
14043af6ab5fSopenharmony_ci
14053af6ab5fSopenharmony_ci    switch (ETSType(type)) {
14063af6ab5fSopenharmony_ci        case TypeFlag::BYTE: {
14073af6ab5fSopenharmony_ci            return type->AsByteType()->GetValue();
14083af6ab5fSopenharmony_ci        }
14093af6ab5fSopenharmony_ci        case TypeFlag::SHORT: {
14103af6ab5fSopenharmony_ci            return type->AsShortType()->GetValue();
14113af6ab5fSopenharmony_ci        }
14123af6ab5fSopenharmony_ci        case TypeFlag::INT: {
14133af6ab5fSopenharmony_ci            return type->AsIntType()->GetValue();
14143af6ab5fSopenharmony_ci        }
14153af6ab5fSopenharmony_ci        case TypeFlag::LONG: {
14163af6ab5fSopenharmony_ci            if (auto val = type->AsLongType()->GetValue();
14173af6ab5fSopenharmony_ci                val <= std::numeric_limits<int32_t>::max() && val >= std::numeric_limits<int32_t>::min()) {
14183af6ab5fSopenharmony_ci                return static_cast<int32_t>(val);
14193af6ab5fSopenharmony_ci            }
14203af6ab5fSopenharmony_ci
14213af6ab5fSopenharmony_ci            LogTypeError("Element accessor value is out of tuple size bounds.", pos);
14223af6ab5fSopenharmony_ci            return std::nullopt;
14233af6ab5fSopenharmony_ci        }
14243af6ab5fSopenharmony_ci        default: {
14253af6ab5fSopenharmony_ci            UNREACHABLE();
14263af6ab5fSopenharmony_ci        }
14273af6ab5fSopenharmony_ci    }
14283af6ab5fSopenharmony_ci}
14293af6ab5fSopenharmony_ci
14303af6ab5fSopenharmony_cibool ETSChecker::ValidateTupleIndex(const ETSTupleType *const tuple, ir::MemberExpression *const expr)
14313af6ab5fSopenharmony_ci{
14323af6ab5fSopenharmony_ci    auto *const expressionType = expr->Property()->Check(this);
14333af6ab5fSopenharmony_ci    auto const *const unboxedExpressionType = ETSBuiltinTypeAsPrimitiveType(expressionType);
14343af6ab5fSopenharmony_ci
14353af6ab5fSopenharmony_ci    if (expressionType->IsETSObjectType() && (unboxedExpressionType != nullptr)) {
14363af6ab5fSopenharmony_ci        expr->AddBoxingUnboxingFlags(GetUnboxingFlag(unboxedExpressionType));
14373af6ab5fSopenharmony_ci    }
14383af6ab5fSopenharmony_ci
14393af6ab5fSopenharmony_ci    const auto *const exprType = expr->Property()->TsType();
14403af6ab5fSopenharmony_ci    ASSERT(exprType != nullptr);
14413af6ab5fSopenharmony_ci
14423af6ab5fSopenharmony_ci    if (!exprType->HasTypeFlag(TypeFlag::CONSTANT) && !tuple->HasSpreadType()) {
14433af6ab5fSopenharmony_ci        LogTypeError("Only constant expression allowed for element access on tuples.", expr->Property()->Start());
14443af6ab5fSopenharmony_ci        return false;
14453af6ab5fSopenharmony_ci    }
14463af6ab5fSopenharmony_ci
14473af6ab5fSopenharmony_ci    if (!exprType->HasTypeFlag(TypeFlag::ETS_ARRAY_INDEX | TypeFlag::LONG)) {
14483af6ab5fSopenharmony_ci        LogTypeError("Only integer type allowed for element access on tuples.", expr->Property()->Start());
14493af6ab5fSopenharmony_ci        return false;
14503af6ab5fSopenharmony_ci    }
14513af6ab5fSopenharmony_ci
14523af6ab5fSopenharmony_ci    auto exprValue = GetTupleElementAccessValue(exprType, expr->Property()->Start());
14533af6ab5fSopenharmony_ci    if (!exprValue.has_value()) {
14543af6ab5fSopenharmony_ci        return false;  // spread the error
14553af6ab5fSopenharmony_ci    }
14563af6ab5fSopenharmony_ci    if (((*exprValue >= tuple->GetTupleSize()) && !tuple->HasSpreadType()) || (*exprValue < 0)) {
14573af6ab5fSopenharmony_ci        LogTypeError("Element accessor value is out of tuple size bounds.", expr->Property()->Start());
14583af6ab5fSopenharmony_ci        return false;
14593af6ab5fSopenharmony_ci    }
14603af6ab5fSopenharmony_ci
14613af6ab5fSopenharmony_ci    return true;
14623af6ab5fSopenharmony_ci}
14633af6ab5fSopenharmony_ci
14643af6ab5fSopenharmony_ciETSObjectType *ETSChecker::CheckThisOrSuperAccess(ir::Expression *node, ETSObjectType *classType, std::string_view msg)
14653af6ab5fSopenharmony_ci{
14663af6ab5fSopenharmony_ci    if ((Context().Status() & CheckerStatus::IGNORE_VISIBILITY) != 0U) {
14673af6ab5fSopenharmony_ci        return classType;
14683af6ab5fSopenharmony_ci    }
14693af6ab5fSopenharmony_ci
14703af6ab5fSopenharmony_ci    if (node->Parent()->IsCallExpression() && (node->Parent()->AsCallExpression()->Callee() == node)) {
14713af6ab5fSopenharmony_ci        if (Context().ContainingSignature() == nullptr) {
14723af6ab5fSopenharmony_ci            LogTypeError({"Call to '", msg, "' must be first statement in constructor"}, node->Start());
14733af6ab5fSopenharmony_ci            return classType;
14743af6ab5fSopenharmony_ci        }
14753af6ab5fSopenharmony_ci
14763af6ab5fSopenharmony_ci        auto *sig = Context().ContainingSignature();
14773af6ab5fSopenharmony_ci        ASSERT(sig->Function()->Body() && sig->Function()->Body()->IsBlockStatement());
14783af6ab5fSopenharmony_ci
14793af6ab5fSopenharmony_ci        if (!sig->HasSignatureFlag(checker::SignatureFlags::CONSTRUCT)) {
14803af6ab5fSopenharmony_ci            LogTypeError({"Call to '", msg, "' must be first statement in constructor"}, node->Start());
14813af6ab5fSopenharmony_ci            return classType;
14823af6ab5fSopenharmony_ci        }
14833af6ab5fSopenharmony_ci
14843af6ab5fSopenharmony_ci        if (sig->Function()->Body()->AsBlockStatement()->Statements().front() != node->Parent()->Parent()) {
14853af6ab5fSopenharmony_ci            LogTypeError({"Call to '", msg, "' must be first statement in constructor"}, node->Start());
14863af6ab5fSopenharmony_ci            return classType;
14873af6ab5fSopenharmony_ci        }
14883af6ab5fSopenharmony_ci    }
14893af6ab5fSopenharmony_ci
14903af6ab5fSopenharmony_ci    if (HasStatus(checker::CheckerStatus::IN_STATIC_CONTEXT)) {
14913af6ab5fSopenharmony_ci        LogTypeError({"'", msg, "' cannot be referenced from a static context"}, node->Start());
14923af6ab5fSopenharmony_ci        return classType;
14933af6ab5fSopenharmony_ci    }
14943af6ab5fSopenharmony_ci
14953af6ab5fSopenharmony_ci    if (classType->GetDeclNode()->IsClassDefinition() && classType->GetDeclNode()->AsClassDefinition()->IsGlobal()) {
14963af6ab5fSopenharmony_ci        LogTypeError({"Cannot reference '", msg, "' in this context."}, node->Start());
14973af6ab5fSopenharmony_ci        return classType;
14983af6ab5fSopenharmony_ci    }
14993af6ab5fSopenharmony_ci
15003af6ab5fSopenharmony_ci    return classType;
15013af6ab5fSopenharmony_ci}
15023af6ab5fSopenharmony_ci
15033af6ab5fSopenharmony_civoid ETSChecker::CheckCyclicConstructorCall(Signature *signature)
15043af6ab5fSopenharmony_ci{
15053af6ab5fSopenharmony_ci    ASSERT(signature->Function());
15063af6ab5fSopenharmony_ci
15073af6ab5fSopenharmony_ci    if (signature->Function()->Body() == nullptr || signature->Function()->IsExternal()) {
15083af6ab5fSopenharmony_ci        return;
15093af6ab5fSopenharmony_ci    }
15103af6ab5fSopenharmony_ci
15113af6ab5fSopenharmony_ci    auto *funcBody = signature->Function()->Body()->AsBlockStatement();
15123af6ab5fSopenharmony_ci
15133af6ab5fSopenharmony_ci    TypeStackElement tse(this, signature, "Recursive constructor invocation", signature->Function()->Start());
15143af6ab5fSopenharmony_ci    if (tse.HasTypeError()) {
15153af6ab5fSopenharmony_ci        return;
15163af6ab5fSopenharmony_ci    }
15173af6ab5fSopenharmony_ci
15183af6ab5fSopenharmony_ci    if (!funcBody->Statements().empty() && funcBody->Statements()[0]->IsExpressionStatement() &&
15193af6ab5fSopenharmony_ci        funcBody->Statements()[0]->AsExpressionStatement()->GetExpression()->IsCallExpression() &&
15203af6ab5fSopenharmony_ci        funcBody->Statements()[0]
15213af6ab5fSopenharmony_ci            ->AsExpressionStatement()
15223af6ab5fSopenharmony_ci            ->GetExpression()
15233af6ab5fSopenharmony_ci            ->AsCallExpression()
15243af6ab5fSopenharmony_ci            ->Callee()
15253af6ab5fSopenharmony_ci            ->IsThisExpression()) {
15263af6ab5fSopenharmony_ci        auto *constructorCall = funcBody->Statements()[0]->AsExpressionStatement()->GetExpression()->AsCallExpression();
15273af6ab5fSopenharmony_ci        ASSERT(constructorCall->Signature());
15283af6ab5fSopenharmony_ci        CheckCyclicConstructorCall(constructorCall->Signature());
15293af6ab5fSopenharmony_ci    }
15303af6ab5fSopenharmony_ci}
15313af6ab5fSopenharmony_ci
15323af6ab5fSopenharmony_ciETSObjectType *ETSChecker::CheckExceptionOrErrorType(checker::Type *type, const lexer::SourcePosition pos)
15333af6ab5fSopenharmony_ci{
15343af6ab5fSopenharmony_ci    if (!type->IsETSObjectType() || (!Relation()->IsAssignableTo(type, GlobalBuiltinExceptionType()) &&
15353af6ab5fSopenharmony_ci                                     !Relation()->IsAssignableTo(type, GlobalBuiltinErrorType()))) {
15363af6ab5fSopenharmony_ci        LogTypeError({"Argument must be an instance of '", compiler::Signatures::BUILTIN_EXCEPTION_CLASS, "' or '",
15373af6ab5fSopenharmony_ci                      compiler::Signatures::BUILTIN_ERROR_CLASS, "'"},
15383af6ab5fSopenharmony_ci                     pos);
15393af6ab5fSopenharmony_ci        return GlobalETSObjectType();
15403af6ab5fSopenharmony_ci    }
15413af6ab5fSopenharmony_ci
15423af6ab5fSopenharmony_ci    return type->AsETSObjectType();
15433af6ab5fSopenharmony_ci}
15443af6ab5fSopenharmony_ci
15453af6ab5fSopenharmony_ciType *ETSChecker::TryToInstantiate(Type *const type, ArenaAllocator *const allocator, TypeRelation *const relation,
15463af6ab5fSopenharmony_ci                                   GlobalTypesHolder *const globalTypes)
15473af6ab5fSopenharmony_ci{
15483af6ab5fSopenharmony_ci    // NOTE: Handle generic functions
15493af6ab5fSopenharmony_ci    auto *returnType = type;
15503af6ab5fSopenharmony_ci    const bool isIncomplete =
15513af6ab5fSopenharmony_ci        type->IsETSObjectType() && type->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::INCOMPLETE_INSTANTIATION);
15523af6ab5fSopenharmony_ci    if (const bool isFunctionType = type->IsETSFunctionType(); isFunctionType || isIncomplete) {
15533af6ab5fSopenharmony_ci        returnType = type->Instantiate(allocator, relation, globalTypes);
15543af6ab5fSopenharmony_ci    }
15553af6ab5fSopenharmony_ci
15563af6ab5fSopenharmony_ci    return returnType;
15573af6ab5fSopenharmony_ci}
15583af6ab5fSopenharmony_ci
15593af6ab5fSopenharmony_civoid ETSChecker::ValidateResolvedProperty(varbinder::LocalVariable **property, const ETSObjectType *const target,
15603af6ab5fSopenharmony_ci                                          const ir::Identifier *const ident, const PropertySearchFlags flags)
15613af6ab5fSopenharmony_ci{
15623af6ab5fSopenharmony_ci    if (*property != nullptr) {
15633af6ab5fSopenharmony_ci        return;
15643af6ab5fSopenharmony_ci    }
15653af6ab5fSopenharmony_ci
15663af6ab5fSopenharmony_ci    using Utype = std::underlying_type_t<PropertySearchFlags>;
15673af6ab5fSopenharmony_ci    static constexpr uint32_t CORRECT_PROPERTY_SEARCH_ORDER_INSTANCE = 7U;
15683af6ab5fSopenharmony_ci    static_assert(static_cast<Utype>(PropertySearchFlags::SEARCH_INSTANCE) == CORRECT_PROPERTY_SEARCH_ORDER_INSTANCE,
15693af6ab5fSopenharmony_ci                  "PropertySearchFlags order changed");
15703af6ab5fSopenharmony_ci    static constexpr uint32_t CORRECT_PROPERTY_SEARCH_ORDER_STATIC = 56U;
15713af6ab5fSopenharmony_ci    static_assert(static_cast<Utype>(PropertySearchFlags::SEARCH_STATIC) == CORRECT_PROPERTY_SEARCH_ORDER_STATIC,
15723af6ab5fSopenharmony_ci                  "PropertySearchFlags order changed");
15733af6ab5fSopenharmony_ci    const auto flagsNum = static_cast<Utype>(flags);
15743af6ab5fSopenharmony_ci    // This algorithm swaps the first 3 bits of a number with it's consecutive 3 bits, example: 0b110001 -> 0b001110
15753af6ab5fSopenharmony_ci    // Effectively it changes PropertySearchFlags to search for the appropriate declarations
15763af6ab5fSopenharmony_ci    const Utype x = (flagsNum ^ (flagsNum >> 3U)) & 7U;
15773af6ab5fSopenharmony_ci    const auto newFlags = PropertySearchFlags {flagsNum ^ (x | (x << 3U))};
15783af6ab5fSopenharmony_ci
15793af6ab5fSopenharmony_ci    auto *const newProp = target->GetProperty(ident->Name(), newFlags);
15803af6ab5fSopenharmony_ci    if (newProp == nullptr) {
15813af6ab5fSopenharmony_ci        LogTypeError({"Property '", ident->Name(), "' does not exist on type '", target->Name(), "'"}, ident->Start());
15823af6ab5fSopenharmony_ci        return;
15833af6ab5fSopenharmony_ci    }
15843af6ab5fSopenharmony_ci
15853af6ab5fSopenharmony_ci    *property = newProp;  // trying to recover as much as possible; log the error but treat the property as legal
15863af6ab5fSopenharmony_ci
15873af6ab5fSopenharmony_ci    if (IsVariableStatic(newProp)) {
15883af6ab5fSopenharmony_ci        LogTypeError({"'", ident->Name(), "' is a static property of '", target->Name(), "'"}, ident->Start());
15893af6ab5fSopenharmony_ci        return;
15903af6ab5fSopenharmony_ci    }
15913af6ab5fSopenharmony_ci
15923af6ab5fSopenharmony_ci    LogTypeError({"'", ident->Name(), "' is an instance property of '", target->Name(), "'"}, ident->Start());
15933af6ab5fSopenharmony_ci}
15943af6ab5fSopenharmony_ci
15953af6ab5fSopenharmony_civarbinder::Variable *ETSChecker::ResolveInstanceExtension(const ir::MemberExpression *const memberExpr)
15963af6ab5fSopenharmony_ci{
15973af6ab5fSopenharmony_ci    // clang-format off
15983af6ab5fSopenharmony_ci    auto *globalFunctionVar = Scope()
15993af6ab5fSopenharmony_ci                                ->FindInGlobal(memberExpr->Property()->AsIdentifier()->Name(),
16003af6ab5fSopenharmony_ci                                                varbinder::ResolveBindingOptions::STATIC_METHODS)
16013af6ab5fSopenharmony_ci                                .variable;
16023af6ab5fSopenharmony_ci    // clang-format on
16033af6ab5fSopenharmony_ci
16043af6ab5fSopenharmony_ci    if (globalFunctionVar == nullptr || !ExtensionETSFunctionType(this->GetTypeOfVariable(globalFunctionVar))) {
16053af6ab5fSopenharmony_ci        return nullptr;
16063af6ab5fSopenharmony_ci    }
16073af6ab5fSopenharmony_ci
16083af6ab5fSopenharmony_ci    return globalFunctionVar;
16093af6ab5fSopenharmony_ci}
16103af6ab5fSopenharmony_ci
16113af6ab5fSopenharmony_ciPropertySearchFlags ETSChecker::GetInitialSearchFlags(const ir::MemberExpression *const memberExpr)
16123af6ab5fSopenharmony_ci{
16133af6ab5fSopenharmony_ci    constexpr auto FUNCTIONAL_FLAGS =
16143af6ab5fSopenharmony_ci        PropertySearchFlags::SEARCH_METHOD | PropertySearchFlags::IS_FUNCTIONAL | PropertySearchFlags::SEARCH_FIELD;
16153af6ab5fSopenharmony_ci    constexpr auto GETTER_FLAGS = PropertySearchFlags::SEARCH_METHOD | PropertySearchFlags::IS_GETTER;
16163af6ab5fSopenharmony_ci    constexpr auto SETTER_FLAGS = PropertySearchFlags::SEARCH_METHOD | PropertySearchFlags::IS_SETTER;
16173af6ab5fSopenharmony_ci
16183af6ab5fSopenharmony_ci    switch (memberExpr->Parent()->Type()) {
16193af6ab5fSopenharmony_ci        case ir::AstNodeType::CALL_EXPRESSION: {
16203af6ab5fSopenharmony_ci            if (memberExpr->Parent()->AsCallExpression()->Callee() == memberExpr) {
16213af6ab5fSopenharmony_ci                return FUNCTIONAL_FLAGS;
16223af6ab5fSopenharmony_ci            }
16233af6ab5fSopenharmony_ci
16243af6ab5fSopenharmony_ci            break;
16253af6ab5fSopenharmony_ci        }
16263af6ab5fSopenharmony_ci        case ir::AstNodeType::ETS_NEW_CLASS_INSTANCE_EXPRESSION: {
16273af6ab5fSopenharmony_ci            if (memberExpr->Parent()->AsETSNewClassInstanceExpression()->GetTypeRef() == memberExpr) {
16283af6ab5fSopenharmony_ci                return PropertySearchFlags::SEARCH_DECL;
16293af6ab5fSopenharmony_ci            }
16303af6ab5fSopenharmony_ci            break;
16313af6ab5fSopenharmony_ci        }
16323af6ab5fSopenharmony_ci        case ir::AstNodeType::MEMBER_EXPRESSION: {
16333af6ab5fSopenharmony_ci            return PropertySearchFlags::SEARCH_FIELD | PropertySearchFlags::SEARCH_DECL | GETTER_FLAGS;
16343af6ab5fSopenharmony_ci        }
16353af6ab5fSopenharmony_ci        case ir::AstNodeType::UPDATE_EXPRESSION:
16363af6ab5fSopenharmony_ci        case ir::AstNodeType::UNARY_EXPRESSION:
16373af6ab5fSopenharmony_ci        case ir::AstNodeType::BINARY_EXPRESSION: {
16383af6ab5fSopenharmony_ci            return PropertySearchFlags::SEARCH_FIELD | GETTER_FLAGS;
16393af6ab5fSopenharmony_ci        }
16403af6ab5fSopenharmony_ci        case ir::AstNodeType::ASSIGNMENT_EXPRESSION: {
16413af6ab5fSopenharmony_ci            const auto *const assignmentExpr = memberExpr->Parent()->AsAssignmentExpression();
16423af6ab5fSopenharmony_ci
16433af6ab5fSopenharmony_ci            if (assignmentExpr->Left() == memberExpr) {
16443af6ab5fSopenharmony_ci                if (assignmentExpr->OperatorType() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
16453af6ab5fSopenharmony_ci                    return PropertySearchFlags::SEARCH_FIELD | SETTER_FLAGS;
16463af6ab5fSopenharmony_ci                }
16473af6ab5fSopenharmony_ci                return PropertySearchFlags::SEARCH_FIELD | GETTER_FLAGS | SETTER_FLAGS;
16483af6ab5fSopenharmony_ci            }
16493af6ab5fSopenharmony_ci
16503af6ab5fSopenharmony_ci            auto const *targetType = assignmentExpr->Left()->TsTypeOrError();
16513af6ab5fSopenharmony_ci            if (targetType->IsETSObjectType() &&
16523af6ab5fSopenharmony_ci                targetType->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::FUNCTIONAL)) {
16533af6ab5fSopenharmony_ci                return FUNCTIONAL_FLAGS;
16543af6ab5fSopenharmony_ci            }
16553af6ab5fSopenharmony_ci
16563af6ab5fSopenharmony_ci            return PropertySearchFlags::SEARCH_FIELD | GETTER_FLAGS;
16573af6ab5fSopenharmony_ci        }
16583af6ab5fSopenharmony_ci        default: {
16593af6ab5fSopenharmony_ci            break;
16603af6ab5fSopenharmony_ci        }
16613af6ab5fSopenharmony_ci    }
16623af6ab5fSopenharmony_ci
16633af6ab5fSopenharmony_ci    return PropertySearchFlags::SEARCH_FIELD | FUNCTIONAL_FLAGS | GETTER_FLAGS;
16643af6ab5fSopenharmony_ci}
16653af6ab5fSopenharmony_ci
16663af6ab5fSopenharmony_ciPropertySearchFlags ETSChecker::GetSearchFlags(const ir::MemberExpression *const memberExpr,
16673af6ab5fSopenharmony_ci                                               const varbinder::Variable *targetRef)
16683af6ab5fSopenharmony_ci{
16693af6ab5fSopenharmony_ci    auto searchFlag = GetInitialSearchFlags(memberExpr);
16703af6ab5fSopenharmony_ci    searchFlag |= PropertySearchFlags::SEARCH_IN_BASE | PropertySearchFlags::SEARCH_IN_INTERFACES;
16713af6ab5fSopenharmony_ci    if (targetRef != nullptr &&
16723af6ab5fSopenharmony_ci        (targetRef->HasFlag(varbinder::VariableFlags::CLASS_OR_INTERFACE) ||
16733af6ab5fSopenharmony_ci         (targetRef->HasFlag(varbinder::VariableFlags::TYPE_ALIAS) &&
16743af6ab5fSopenharmony_ci          targetRef->TsType()->Variable()->HasFlag(varbinder::VariableFlags::CLASS_OR_INTERFACE)))) {
16753af6ab5fSopenharmony_ci        searchFlag &= ~PropertySearchFlags::SEARCH_INSTANCE;
16763af6ab5fSopenharmony_ci    } else if (memberExpr->Object()->IsThisExpression() ||
16773af6ab5fSopenharmony_ci               (targetRef != nullptr && targetRef->Declaration() != nullptr &&
16783af6ab5fSopenharmony_ci                targetRef->Declaration()->IsLetOrConstDecl()) ||
16793af6ab5fSopenharmony_ci               (memberExpr->Object()->IsIdentifier() && memberExpr->ObjType()->GetDeclNode() != nullptr &&
16803af6ab5fSopenharmony_ci                memberExpr->ObjType()->GetDeclNode()->IsTSInterfaceDeclaration())) {
16813af6ab5fSopenharmony_ci        searchFlag &= ~PropertySearchFlags::SEARCH_STATIC;
16823af6ab5fSopenharmony_ci    }
16833af6ab5fSopenharmony_ci    return searchFlag;
16843af6ab5fSopenharmony_ci}
16853af6ab5fSopenharmony_ci
16863af6ab5fSopenharmony_ciconst varbinder::Variable *ETSChecker::GetTargetRef(const ir::MemberExpression *const memberExpr)
16873af6ab5fSopenharmony_ci{
16883af6ab5fSopenharmony_ci    if (memberExpr->Object()->IsIdentifier()) {
16893af6ab5fSopenharmony_ci        return memberExpr->Object()->AsIdentifier()->Variable();
16903af6ab5fSopenharmony_ci    }
16913af6ab5fSopenharmony_ci    if (memberExpr->Object()->IsMemberExpression()) {
16923af6ab5fSopenharmony_ci        return memberExpr->Object()->AsMemberExpression()->PropVar();
16933af6ab5fSopenharmony_ci    }
16943af6ab5fSopenharmony_ci    return nullptr;
16953af6ab5fSopenharmony_ci}
16963af6ab5fSopenharmony_ci
16973af6ab5fSopenharmony_civoid ETSChecker::ValidateReadonlyProperty(const ir::MemberExpression *const memberExpr, const ETSFunctionType *propType,
16983af6ab5fSopenharmony_ci                                          const lexer::SourcePosition sourcePos)
16993af6ab5fSopenharmony_ci{
17003af6ab5fSopenharmony_ci    ir::ClassProperty *classProp = nullptr;
17013af6ab5fSopenharmony_ci    ETSObjectType *currentObj = memberExpr->ObjType();
17023af6ab5fSopenharmony_ci    bool foundInThis = false;
17033af6ab5fSopenharmony_ci    while (classProp == nullptr && currentObj != nullptr) {
17043af6ab5fSopenharmony_ci        classProp = FindClassProperty(currentObj, propType);
17053af6ab5fSopenharmony_ci        if (classProp != nullptr && currentObj == memberExpr->ObjType()) {
17063af6ab5fSopenharmony_ci            foundInThis = true;
17073af6ab5fSopenharmony_ci        }
17083af6ab5fSopenharmony_ci
17093af6ab5fSopenharmony_ci        currentObj = currentObj->SuperType();
17103af6ab5fSopenharmony_ci    }
17113af6ab5fSopenharmony_ci
17123af6ab5fSopenharmony_ci    if (classProp != nullptr && this->Context().ContainingSignature() != nullptr && classProp->IsReadonly()) {
17133af6ab5fSopenharmony_ci        if (!foundInThis || (!this->Context().ContainingSignature()->Function()->IsConstructor())) {
17143af6ab5fSopenharmony_ci            LogTypeError("Cannot assign to this property because it is readonly.", sourcePos);
17153af6ab5fSopenharmony_ci            return;
17163af6ab5fSopenharmony_ci        }
17173af6ab5fSopenharmony_ci
17183af6ab5fSopenharmony_ci        if (IsInitializedProperty(memberExpr->ObjType()->GetDeclNode()->AsClassDefinition(), classProp)) {
17193af6ab5fSopenharmony_ci            LogTypeError("Readonly field already initialized at declaration.", sourcePos);
17203af6ab5fSopenharmony_ci        }
17213af6ab5fSopenharmony_ci    }
17223af6ab5fSopenharmony_ci}
17233af6ab5fSopenharmony_ci
17243af6ab5fSopenharmony_civoid ETSChecker::ValidateGetterSetter(const ir::MemberExpression *const memberExpr,
17253af6ab5fSopenharmony_ci                                      const varbinder::LocalVariable *const prop, PropertySearchFlags searchFlag)
17263af6ab5fSopenharmony_ci{
17273af6ab5fSopenharmony_ci    auto *propType = prop->TsType()->AsETSFunctionType();
17283af6ab5fSopenharmony_ci    ASSERT((propType->FindGetter() != nullptr) == propType->HasTypeFlag(TypeFlag::GETTER));
17293af6ab5fSopenharmony_ci    ASSERT((propType->FindSetter() != nullptr) == propType->HasTypeFlag(TypeFlag::SETTER));
17303af6ab5fSopenharmony_ci
17313af6ab5fSopenharmony_ci    auto const &sourcePos = memberExpr->Property()->Start();
17323af6ab5fSopenharmony_ci    auto callExpr = memberExpr->Parent()->IsCallExpression() ? memberExpr->Parent()->AsCallExpression() : nullptr;
17333af6ab5fSopenharmony_ci
17343af6ab5fSopenharmony_ci    if ((searchFlag & PropertySearchFlags::IS_GETTER) != 0) {
17353af6ab5fSopenharmony_ci        if (!propType->HasTypeFlag(TypeFlag::GETTER)) {
17363af6ab5fSopenharmony_ci            LogTypeError("Cannot read from this property because it is writeonly.", sourcePos);
17373af6ab5fSopenharmony_ci            return;
17383af6ab5fSopenharmony_ci        }
17393af6ab5fSopenharmony_ci        ValidateSignatureAccessibility(memberExpr->ObjType(), callExpr, propType->FindGetter(), sourcePos);
17403af6ab5fSopenharmony_ci    }
17413af6ab5fSopenharmony_ci
17423af6ab5fSopenharmony_ci    if ((searchFlag & PropertySearchFlags::IS_SETTER) != 0) {
17433af6ab5fSopenharmony_ci        ValidateReadonlyProperty(memberExpr, propType, sourcePos);
17443af6ab5fSopenharmony_ci        ValidateSignatureAccessibility(memberExpr->ObjType(), callExpr, propType->FindSetter(), sourcePos);
17453af6ab5fSopenharmony_ci    }
17463af6ab5fSopenharmony_ci}
17473af6ab5fSopenharmony_ci
17483af6ab5fSopenharmony_ciir::ClassProperty *ETSChecker::FindClassProperty(const ETSObjectType *const objectType, const ETSFunctionType *propType)
17493af6ab5fSopenharmony_ci{
17503af6ab5fSopenharmony_ci    auto propName =
17513af6ab5fSopenharmony_ci        util::UString(std::string(compiler::Signatures::PROPERTY) + propType->Name().Mutf8(), Allocator()).View();
17523af6ab5fSopenharmony_ci
17533af6ab5fSopenharmony_ci    ir::ClassProperty *classProp = nullptr;
17543af6ab5fSopenharmony_ci    if (objectType->GetDeclNode()->IsClassDefinition()) {
17553af6ab5fSopenharmony_ci        auto body = objectType->GetDeclNode()->AsClassDefinition()->Body();
17563af6ab5fSopenharmony_ci        auto foundValue = std::find_if(body.begin(), body.end(), [propName](ir::AstNode *node) {
17573af6ab5fSopenharmony_ci            return node->IsClassProperty() && node->AsClassProperty()->Key()->AsIdentifier()->Name() == propName;
17583af6ab5fSopenharmony_ci        });
17593af6ab5fSopenharmony_ci        if (foundValue != body.end()) {
17603af6ab5fSopenharmony_ci            classProp = (*foundValue)->AsClassProperty();
17613af6ab5fSopenharmony_ci        }
17623af6ab5fSopenharmony_ci    }
17633af6ab5fSopenharmony_ci
17643af6ab5fSopenharmony_ci    return classProp;
17653af6ab5fSopenharmony_ci}
17663af6ab5fSopenharmony_ci
17673af6ab5fSopenharmony_cibool ETSChecker::IsInitializedProperty(const ir::ClassDefinition *classDefinition, const ir::ClassProperty *prop)
17683af6ab5fSopenharmony_ci{
17693af6ab5fSopenharmony_ci    std::string targetName = prop->Key()->AsIdentifier()->Name().Mutf8();
17703af6ab5fSopenharmony_ci    if (targetName.find(compiler::Signatures::PROPERTY) == 0) {
17713af6ab5fSopenharmony_ci        targetName = targetName.substr(compiler::Signatures::PROPERTY.size());
17723af6ab5fSopenharmony_ci    }
17733af6ab5fSopenharmony_ci
17743af6ab5fSopenharmony_ci    for (auto *it : classDefinition->Body()) {
17753af6ab5fSopenharmony_ci        if (it->IsClassProperty() && it->AsClassProperty()->Value() != nullptr) {
17763af6ab5fSopenharmony_ci            return FindPropertyInAssignment(it, targetName);
17773af6ab5fSopenharmony_ci        }
17783af6ab5fSopenharmony_ci    }
17793af6ab5fSopenharmony_ci
17803af6ab5fSopenharmony_ci    return false;
17813af6ab5fSopenharmony_ci}
17823af6ab5fSopenharmony_ci
17833af6ab5fSopenharmony_cibool ETSChecker::FindPropertyInAssignment(const ir::AstNode *it, const std::string &targetName)
17843af6ab5fSopenharmony_ci{
17853af6ab5fSopenharmony_ci    return it->AsClassProperty()->Value()->FindChild([&targetName](ir::AstNode *node) {
17863af6ab5fSopenharmony_ci        return node->IsIdentifier() && node->AsIdentifier()->Name().Is(targetName) && node->Parent() != nullptr &&
17873af6ab5fSopenharmony_ci               node->Parent()->IsMemberExpression();
17883af6ab5fSopenharmony_ci    }) != nullptr;
17893af6ab5fSopenharmony_ci}
17903af6ab5fSopenharmony_ci
17913af6ab5fSopenharmony_civoid ETSChecker::ValidateVarDeclaratorOrClassProperty(const ir::MemberExpression *const memberExpr,
17923af6ab5fSopenharmony_ci                                                      varbinder::LocalVariable *const prop)
17933af6ab5fSopenharmony_ci{
17943af6ab5fSopenharmony_ci    const auto [target_ident,
17953af6ab5fSopenharmony_ci                type_annotation] = [memberExpr]() -> std::pair<const ir::Identifier *, const ir::TypeNode *> {
17963af6ab5fSopenharmony_ci        if (memberExpr->Parent()->IsVariableDeclarator()) {
17973af6ab5fSopenharmony_ci            const auto *const ident = memberExpr->Parent()->AsVariableDeclarator()->Id()->AsIdentifier();
17983af6ab5fSopenharmony_ci            return {ident, ident->TypeAnnotation()};
17993af6ab5fSopenharmony_ci        }
18003af6ab5fSopenharmony_ci        return {memberExpr->Parent()->AsClassProperty()->Key()->AsIdentifier(),
18013af6ab5fSopenharmony_ci                memberExpr->Parent()->AsClassProperty()->TypeAnnotation()};
18023af6ab5fSopenharmony_ci    }();
18033af6ab5fSopenharmony_ci
18043af6ab5fSopenharmony_ci    GetTypeOfVariable(prop);
18053af6ab5fSopenharmony_ci
18063af6ab5fSopenharmony_ci    if (prop->TsType()->IsETSFunctionType() && !IsVariableGetterSetter(prop)) {
18073af6ab5fSopenharmony_ci        if (type_annotation == nullptr) {
18083af6ab5fSopenharmony_ci            LogTypeError({"Cannot infer type for ", target_ident->Name(),
18093af6ab5fSopenharmony_ci                          " because method reference needs an explicit target type"},
18103af6ab5fSopenharmony_ci                         target_ident->Start());
18113af6ab5fSopenharmony_ci            return;
18123af6ab5fSopenharmony_ci        }
18133af6ab5fSopenharmony_ci
18143af6ab5fSopenharmony_ci        auto *targetType = GetTypeOfVariable(target_ident->Variable());
18153af6ab5fSopenharmony_ci        ASSERT(targetType != nullptr);
18163af6ab5fSopenharmony_ci
18173af6ab5fSopenharmony_ci        if (!targetType->IsETSObjectType() ||
18183af6ab5fSopenharmony_ci            !targetType->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::FUNCTIONAL)) {
18193af6ab5fSopenharmony_ci            LogTypeError({"Method ", memberExpr->Property()->AsIdentifier()->Name(), " does not exist on this type."},
18203af6ab5fSopenharmony_ci                         memberExpr->Property()->Start());
18213af6ab5fSopenharmony_ci        }
18223af6ab5fSopenharmony_ci    }
18233af6ab5fSopenharmony_ci}
18243af6ab5fSopenharmony_ci
18253af6ab5fSopenharmony_ci// NOLINTNEXTLINE(readability-function-size)
18263af6ab5fSopenharmony_cistd::vector<ResolveResult *> ETSChecker::ResolveMemberReference(const ir::MemberExpression *const memberExpr,
18273af6ab5fSopenharmony_ci                                                                const ETSObjectType *const target)
18283af6ab5fSopenharmony_ci{
18293af6ab5fSopenharmony_ci    std::vector<ResolveResult *> resolveRes {};
18303af6ab5fSopenharmony_ci
18313af6ab5fSopenharmony_ci    if (target->IsETSDynamicType() && !target->AsETSDynamicType()->HasDecl()) {
18323af6ab5fSopenharmony_ci        auto propName = memberExpr->Property()->AsIdentifier()->Name();
18333af6ab5fSopenharmony_ci        varbinder::LocalVariable *propVar = target->AsETSDynamicType()->GetPropertyDynamic(propName, this);
18343af6ab5fSopenharmony_ci        resolveRes.emplace_back(Allocator()->New<ResolveResult>(propVar, ResolvedKind::PROPERTY));
18353af6ab5fSopenharmony_ci        return resolveRes;
18363af6ab5fSopenharmony_ci    }
18373af6ab5fSopenharmony_ci
18383af6ab5fSopenharmony_ci    varbinder::Variable *globalFunctionVar = nullptr;
18393af6ab5fSopenharmony_ci
18403af6ab5fSopenharmony_ci    if (memberExpr->Parent()->IsCallExpression() && memberExpr->Parent()->AsCallExpression()->Callee() == memberExpr) {
18413af6ab5fSopenharmony_ci        globalFunctionVar = ResolveInstanceExtension(memberExpr);
18423af6ab5fSopenharmony_ci    } else if (target->GetDeclNode() != nullptr && target->GetDeclNode()->IsClassDefinition() &&
18433af6ab5fSopenharmony_ci               !target->GetDeclNode()->AsClassDefinition()->IsClassDefinitionChecked()) {
18443af6ab5fSopenharmony_ci        this->CheckClassDefinition(target->GetDeclNode()->AsClassDefinition());
18453af6ab5fSopenharmony_ci    }
18463af6ab5fSopenharmony_ci    const auto *const targetRef = GetTargetRef(memberExpr);
18473af6ab5fSopenharmony_ci    auto searchFlag = GetSearchFlags(memberExpr, targetRef);
18483af6ab5fSopenharmony_ci    if (target->HasTypeFlag(TypeFlag::GENERIC) && (searchFlag & PropertySearchFlags::SEARCH_STATIC) != 0) {
18493af6ab5fSopenharmony_ci        searchFlag |= PropertySearchFlags::SEARCH_ALL;
18503af6ab5fSopenharmony_ci    }
18513af6ab5fSopenharmony_ci
18523af6ab5fSopenharmony_ci    auto searchName = target->GetReExportAliasValue(memberExpr->Property()->AsIdentifier()->Name());
18533af6ab5fSopenharmony_ci    auto *prop = target->GetProperty(searchName, searchFlag);
18543af6ab5fSopenharmony_ci
18553af6ab5fSopenharmony_ci    if (memberExpr->Parent()->IsCallExpression() && memberExpr->Parent()->AsCallExpression()->Callee() == memberExpr) {
18563af6ab5fSopenharmony_ci        globalFunctionVar = ResolveInstanceExtension(memberExpr);
18573af6ab5fSopenharmony_ci    }
18583af6ab5fSopenharmony_ci
18593af6ab5fSopenharmony_ci    if (globalFunctionVar == nullptr ||
18603af6ab5fSopenharmony_ci        (targetRef != nullptr && targetRef->HasFlag(varbinder::VariableFlags::CLASS_OR_INTERFACE))) {
18613af6ab5fSopenharmony_ci        /*
18623af6ab5fSopenharmony_ci            Instance extension function can only be called by class instance, if a property is accessed by
18633af6ab5fSopenharmony_ci            CLASS or INTERFACE type, it couldn't be an instance extension function call
18643af6ab5fSopenharmony_ci
18653af6ab5fSopenharmony_ci            Example code:
18663af6ab5fSopenharmony_ci                class A {}
18673af6ab5fSopenharmony_ci                static function A.xxx() {}
18683af6ab5fSopenharmony_ci                function main() {
18693af6ab5fSopenharmony_ci                    A.xxx()
18703af6ab5fSopenharmony_ci                }
18713af6ab5fSopenharmony_ci
18723af6ab5fSopenharmony_ci            !NB: When supporting static extension function, the above code case would be supported
18733af6ab5fSopenharmony_ci        */
18743af6ab5fSopenharmony_ci        ValidateResolvedProperty(&prop, target, memberExpr->Property()->AsIdentifier(), searchFlag);
18753af6ab5fSopenharmony_ci        if (prop == nullptr) {
18763af6ab5fSopenharmony_ci            return resolveRes;
18773af6ab5fSopenharmony_ci        }
18783af6ab5fSopenharmony_ci    } else {
18793af6ab5fSopenharmony_ci        resolveRes.emplace_back(
18803af6ab5fSopenharmony_ci            Allocator()->New<ResolveResult>(globalFunctionVar, ResolvedKind::INSTANCE_EXTENSION_FUNCTION));
18813af6ab5fSopenharmony_ci
18823af6ab5fSopenharmony_ci        if (prop == nullptr) {
18833af6ab5fSopenharmony_ci            // No matched property, but have possible matched global extension function
18843af6ab5fSopenharmony_ci            return resolveRes;
18853af6ab5fSopenharmony_ci        }
18863af6ab5fSopenharmony_ci    }
18873af6ab5fSopenharmony_ci
18883af6ab5fSopenharmony_ci    resolveRes.emplace_back(Allocator()->New<ResolveResult>(prop, ResolvedKind::PROPERTY));
18893af6ab5fSopenharmony_ci
18903af6ab5fSopenharmony_ci    ResolveMemberReferenceValidate(prop, searchFlag, memberExpr);
18913af6ab5fSopenharmony_ci
18923af6ab5fSopenharmony_ci    return resolveRes;
18933af6ab5fSopenharmony_ci}
18943af6ab5fSopenharmony_ci
18953af6ab5fSopenharmony_civoid ETSChecker::ResolveMemberReferenceValidate(varbinder::LocalVariable *const prop,
18963af6ab5fSopenharmony_ci                                                PropertySearchFlags const searchFlag,
18973af6ab5fSopenharmony_ci                                                const ir::MemberExpression *const memberExpr)
18983af6ab5fSopenharmony_ci{
18993af6ab5fSopenharmony_ci    if (prop->HasFlag(varbinder::VariableFlags::METHOD) && !IsVariableGetterSetter(prop) &&
19003af6ab5fSopenharmony_ci        (searchFlag & PropertySearchFlags::IS_FUNCTIONAL) == 0) {
19013af6ab5fSopenharmony_ci        LogTypeError("Method used in wrong context", memberExpr->Property()->Start());
19023af6ab5fSopenharmony_ci        return;
19033af6ab5fSopenharmony_ci    }
19043af6ab5fSopenharmony_ci
19053af6ab5fSopenharmony_ci    if (IsVariableGetterSetter(prop)) {
19063af6ab5fSopenharmony_ci        ValidateGetterSetter(memberExpr, prop, searchFlag);
19073af6ab5fSopenharmony_ci    }
19083af6ab5fSopenharmony_ci
19093af6ab5fSopenharmony_ci    // Before returning the computed property variable, we have to validate the special case where we are in a variable
19103af6ab5fSopenharmony_ci    // declaration, and the properties type is a function type but the currently declared variable doesn't have a type
19113af6ab5fSopenharmony_ci    // annotation
19123af6ab5fSopenharmony_ci    if (memberExpr->Parent()->IsVariableDeclarator() || memberExpr->Parent()->IsClassProperty()) {
19133af6ab5fSopenharmony_ci        ValidateVarDeclaratorOrClassProperty(memberExpr, prop);
19143af6ab5fSopenharmony_ci    }
19153af6ab5fSopenharmony_ci}
19163af6ab5fSopenharmony_ci
19173af6ab5fSopenharmony_civoid ETSChecker::CheckValidInheritance(ETSObjectType *classType, ir::ClassDefinition *classDef)
19183af6ab5fSopenharmony_ci{
19193af6ab5fSopenharmony_ci    if (classType->SuperType() == nullptr) {
19203af6ab5fSopenharmony_ci        return;
19213af6ab5fSopenharmony_ci    }
19223af6ab5fSopenharmony_ci
19233af6ab5fSopenharmony_ci    if (classDef->TypeParams() != nullptr &&
19243af6ab5fSopenharmony_ci        (Relation()->IsAssignableTo(classType->SuperType(), GlobalBuiltinExceptionType()) ||
19253af6ab5fSopenharmony_ci         Relation()->IsAssignableTo(classType->SuperType(), GlobalBuiltinErrorType()))) {
19263af6ab5fSopenharmony_ci        LogTypeError({"Generics are not allowed as '", compiler::Signatures::BUILTIN_EXCEPTION_CLASS, "' or '",
19273af6ab5fSopenharmony_ci                      compiler::Signatures::BUILTIN_ERROR_CLASS, "' subclasses."},
19283af6ab5fSopenharmony_ci                     classDef->TypeParams()->Start());
19293af6ab5fSopenharmony_ci    }
19303af6ab5fSopenharmony_ci
19313af6ab5fSopenharmony_ci    const auto &allProps = classType->GetAllProperties();
19323af6ab5fSopenharmony_ci
19333af6ab5fSopenharmony_ci    for (auto *it : allProps) {
19343af6ab5fSopenharmony_ci        const auto searchFlag = PropertySearchFlags::SEARCH_ALL | PropertySearchFlags::SEARCH_IN_BASE |
19353af6ab5fSopenharmony_ci                                PropertySearchFlags::SEARCH_IN_INTERFACES |
19363af6ab5fSopenharmony_ci                                PropertySearchFlags::DISALLOW_SYNTHETIC_METHOD_CREATION;
19373af6ab5fSopenharmony_ci        auto *foundInSuper = classType->SuperType()->GetProperty(it->Name(), searchFlag);
19383af6ab5fSopenharmony_ci
19393af6ab5fSopenharmony_ci        ETSObjectType *interfaceFound = nullptr;
19403af6ab5fSopenharmony_ci        if (foundInSuper != nullptr) {
19413af6ab5fSopenharmony_ci            CheckProperties(classType, classDef, it, foundInSuper, interfaceFound);
19423af6ab5fSopenharmony_ci        }
19433af6ab5fSopenharmony_ci
19443af6ab5fSopenharmony_ci        auto interfaceList = GetInterfaces(classType);
19453af6ab5fSopenharmony_ci        varbinder::LocalVariable *foundInInterface = nullptr;
19463af6ab5fSopenharmony_ci        for (auto *interface : interfaceList) {
19473af6ab5fSopenharmony_ci            auto *propertyFound = interface->GetProperty(it->Name(), searchFlag);
19483af6ab5fSopenharmony_ci            if (propertyFound == nullptr) {
19493af6ab5fSopenharmony_ci                continue;
19503af6ab5fSopenharmony_ci            }
19513af6ab5fSopenharmony_ci            foundInInterface = propertyFound;
19523af6ab5fSopenharmony_ci            interfaceFound = interface;
19533af6ab5fSopenharmony_ci            break;
19543af6ab5fSopenharmony_ci        }
19553af6ab5fSopenharmony_ci        if (foundInInterface == nullptr) {
19563af6ab5fSopenharmony_ci            continue;
19573af6ab5fSopenharmony_ci        }
19583af6ab5fSopenharmony_ci
19593af6ab5fSopenharmony_ci        CheckProperties(classType, classDef, it, foundInInterface, interfaceFound);
19603af6ab5fSopenharmony_ci    }
19613af6ab5fSopenharmony_ci}
19623af6ab5fSopenharmony_ci
19633af6ab5fSopenharmony_civoid ETSChecker::CheckProperties(ETSObjectType *classType, ir::ClassDefinition *classDef, varbinder::LocalVariable *it,
19643af6ab5fSopenharmony_ci                                 varbinder::LocalVariable *found, ETSObjectType *interfaceFound)
19653af6ab5fSopenharmony_ci{
19663af6ab5fSopenharmony_ci    if (found->TsType() == nullptr) {
19673af6ab5fSopenharmony_ci        GetTypeOfVariable(found);
19683af6ab5fSopenharmony_ci    }
19693af6ab5fSopenharmony_ci
19703af6ab5fSopenharmony_ci    if (!IsSameDeclarationType(it, found)) {
19713af6ab5fSopenharmony_ci        if (IsVariableStatic(it) != IsVariableStatic(found)) {
19723af6ab5fSopenharmony_ci            return;
19733af6ab5fSopenharmony_ci        }
19743af6ab5fSopenharmony_ci
19753af6ab5fSopenharmony_ci        if (it->TsType()->IsETSFunctionType()) {
19763af6ab5fSopenharmony_ci            auto getter = it->TsType()->AsETSFunctionType()->FindGetter();
19773af6ab5fSopenharmony_ci            if (getter != nullptr && getter->ReturnType() == found->TsType()) {
19783af6ab5fSopenharmony_ci                return;
19793af6ab5fSopenharmony_ci            }
19803af6ab5fSopenharmony_ci            auto setter = it->TsType()->AsETSFunctionType()->FindSetter();
19813af6ab5fSopenharmony_ci            if (setter != nullptr && setter->Params().front()->TsType() == found->TsType()) {
19823af6ab5fSopenharmony_ci                return;
19833af6ab5fSopenharmony_ci            }
19843af6ab5fSopenharmony_ci        }
19853af6ab5fSopenharmony_ci
19863af6ab5fSopenharmony_ci        const char *targetType {};
19873af6ab5fSopenharmony_ci
19883af6ab5fSopenharmony_ci        if (it->HasFlag(varbinder::VariableFlags::PROPERTY)) {
19893af6ab5fSopenharmony_ci            targetType = "field";
19903af6ab5fSopenharmony_ci        } else if (it->HasFlag(varbinder::VariableFlags::METHOD)) {
19913af6ab5fSopenharmony_ci            targetType = "method";
19923af6ab5fSopenharmony_ci        } else if (it->HasFlag(varbinder::VariableFlags::CLASS)) {
19933af6ab5fSopenharmony_ci            targetType = "class";
19943af6ab5fSopenharmony_ci        } else if (it->HasFlag(varbinder::VariableFlags::INTERFACE)) {
19953af6ab5fSopenharmony_ci            targetType = "interface";
19963af6ab5fSopenharmony_ci        } else {
19973af6ab5fSopenharmony_ci            targetType = "enum";
19983af6ab5fSopenharmony_ci        }
19993af6ab5fSopenharmony_ci
20003af6ab5fSopenharmony_ci        if (interfaceFound != nullptr) {
20013af6ab5fSopenharmony_ci            LogTypeError({"Cannot inherit from interface ", interfaceFound->Name(), " because ", targetType, " ",
20023af6ab5fSopenharmony_ci                          it->Name(), " is inherited with a different declaration type"},
20033af6ab5fSopenharmony_ci                         interfaceFound->GetDeclNode()->Start());
20043af6ab5fSopenharmony_ci            return;
20053af6ab5fSopenharmony_ci        }
20063af6ab5fSopenharmony_ci        LogTypeError({"Cannot inherit from class ", classType->SuperType()->Name(), ", because ", targetType, " ",
20073af6ab5fSopenharmony_ci                      it->Name(), " is inherited with a different declaration type"},
20083af6ab5fSopenharmony_ci                     classDef->Super()->Start());
20093af6ab5fSopenharmony_ci    }
20103af6ab5fSopenharmony_ci}
20113af6ab5fSopenharmony_ci
20123af6ab5fSopenharmony_civoid ETSChecker::TransformProperties(ETSObjectType *classType)
20133af6ab5fSopenharmony_ci{
20143af6ab5fSopenharmony_ci    auto propertyList = classType->Fields();
20153af6ab5fSopenharmony_ci    auto *const classDef = classType->GetDeclNode()->AsClassDefinition();
20163af6ab5fSopenharmony_ci
20173af6ab5fSopenharmony_ci    for (auto *const field : propertyList) {
20183af6ab5fSopenharmony_ci        ASSERT(field->Declaration()->Node()->IsClassProperty());
20193af6ab5fSopenharmony_ci        auto *const originalProp = field->Declaration()->Node()->AsClassProperty();
20203af6ab5fSopenharmony_ci
20213af6ab5fSopenharmony_ci        if ((originalProp->Modifiers() & ir::ModifierFlags::GETTER_SETTER) == 0U) {
20223af6ab5fSopenharmony_ci            continue;
20233af6ab5fSopenharmony_ci        }
20243af6ab5fSopenharmony_ci
20253af6ab5fSopenharmony_ci        if (!field->HasFlag(varbinder::VariableFlags::PUBLIC)) {
20263af6ab5fSopenharmony_ci            LogTypeError("Interface property implementation cannot be generated as non-public",
20273af6ab5fSopenharmony_ci                         field->Declaration()->Node()->Start());
20283af6ab5fSopenharmony_ci        }
20293af6ab5fSopenharmony_ci        classType->RemoveProperty<checker::PropertyType::INSTANCE_FIELD>(field);
20303af6ab5fSopenharmony_ci        GenerateGetterSetterPropertyAndMethod(originalProp, classType);
20313af6ab5fSopenharmony_ci    }
20323af6ab5fSopenharmony_ci
20333af6ab5fSopenharmony_ci    for (auto it = classDef->Body().begin(); it != classDef->Body().end(); ++it) {
20343af6ab5fSopenharmony_ci        if ((*it)->IsClassProperty() && ((*it)->Modifiers() & ir::ModifierFlags::GETTER_SETTER) != 0U) {
20353af6ab5fSopenharmony_ci            classDef->Body().erase(it);
20363af6ab5fSopenharmony_ci        }
20373af6ab5fSopenharmony_ci    }
20383af6ab5fSopenharmony_ci}
20393af6ab5fSopenharmony_ci
20403af6ab5fSopenharmony_civoid ETSChecker::CheckGetterSetterProperties(ETSObjectType *classType)
20413af6ab5fSopenharmony_ci{
20423af6ab5fSopenharmony_ci    auto const checkGetterSetter = [this](varbinder::LocalVariable *var, util::StringView name) {
20433af6ab5fSopenharmony_ci        auto const *type = var->TsType()->AsETSFunctionType();
20443af6ab5fSopenharmony_ci        auto const *sigGetter = type->FindGetter();
20453af6ab5fSopenharmony_ci        auto const *sigSetter = type->FindSetter();
20463af6ab5fSopenharmony_ci
20473af6ab5fSopenharmony_ci        for (auto const *sig : type->CallSignatures()) {
20483af6ab5fSopenharmony_ci            if (!sig->Function()->IsGetter() && !sig->Function()->IsSetter()) {
20493af6ab5fSopenharmony_ci                LogTypeError({"Method cannot use the same name as ", name, " accessor property"},
20503af6ab5fSopenharmony_ci                             sig->Function()->Start());
20513af6ab5fSopenharmony_ci                return;
20523af6ab5fSopenharmony_ci            }
20533af6ab5fSopenharmony_ci            if (sig != sigGetter && sig != sigSetter) {
20543af6ab5fSopenharmony_ci                LogTypeError("Duplicate accessor definition", sig->Function()->Start());
20553af6ab5fSopenharmony_ci                return;
20563af6ab5fSopenharmony_ci            }
20573af6ab5fSopenharmony_ci        }
20583af6ab5fSopenharmony_ci        if (sigSetter != nullptr && ((sigGetter->Function()->Modifiers() ^ sigSetter->Function()->Modifiers()) &
20593af6ab5fSopenharmony_ci                                     ir::ModifierFlags::ACCESSOR_MODIFIERS) != 0) {
20603af6ab5fSopenharmony_ci            LogTypeError("Getter and setter methods must have the same accessor modifiers",
20613af6ab5fSopenharmony_ci                         sigGetter->Function()->Start());
20623af6ab5fSopenharmony_ci        }
20633af6ab5fSopenharmony_ci    };
20643af6ab5fSopenharmony_ci
20653af6ab5fSopenharmony_ci    for (const auto &[name, var] : classType->InstanceMethods()) {
20663af6ab5fSopenharmony_ci        if (IsVariableGetterSetter(var)) {
20673af6ab5fSopenharmony_ci            checkGetterSetter(var, name);
20683af6ab5fSopenharmony_ci        }
20693af6ab5fSopenharmony_ci    }
20703af6ab5fSopenharmony_ci
20713af6ab5fSopenharmony_ci    for (const auto &[name, var] : classType->StaticMethods()) {
20723af6ab5fSopenharmony_ci        if (IsVariableGetterSetter(var)) {
20733af6ab5fSopenharmony_ci            checkGetterSetter(var, name);
20743af6ab5fSopenharmony_ci        }
20753af6ab5fSopenharmony_ci    }
20763af6ab5fSopenharmony_ci}
20773af6ab5fSopenharmony_ci
20783af6ab5fSopenharmony_civoid ETSChecker::AddElementsToModuleObject(ETSObjectType *moduleObj, const util::StringView &str)
20793af6ab5fSopenharmony_ci{
20803af6ab5fSopenharmony_ci    for (const auto &[name, var] : VarBinder()->GetScope()->Bindings()) {
20813af6ab5fSopenharmony_ci        if (name.Is(str.Mutf8()) || name.Is(compiler::Signatures::ETS_GLOBAL)) {
20823af6ab5fSopenharmony_ci            continue;
20833af6ab5fSopenharmony_ci        }
20843af6ab5fSopenharmony_ci
20853af6ab5fSopenharmony_ci        if (var->HasFlag(varbinder::VariableFlags::METHOD)) {
20863af6ab5fSopenharmony_ci            moduleObj->AddProperty<checker::PropertyType::STATIC_METHOD>(var->AsLocalVariable());
20873af6ab5fSopenharmony_ci        } else if (var->HasFlag(varbinder::VariableFlags::PROPERTY)) {
20883af6ab5fSopenharmony_ci            moduleObj->AddProperty<checker::PropertyType::STATIC_FIELD>(var->AsLocalVariable());
20893af6ab5fSopenharmony_ci        } else {
20903af6ab5fSopenharmony_ci            moduleObj->AddProperty<checker::PropertyType::STATIC_DECL>(var->AsLocalVariable());
20913af6ab5fSopenharmony_ci        }
20923af6ab5fSopenharmony_ci    }
20933af6ab5fSopenharmony_ci}
20943af6ab5fSopenharmony_ci
20953af6ab5fSopenharmony_ci// This function computes effective runtime view of type
20963af6ab5fSopenharmony_ciType *ETSChecker::GetApparentType(Type *type)
20973af6ab5fSopenharmony_ci{
20983af6ab5fSopenharmony_ci    if (auto it = apparentTypes_.find(type); LIKELY(it != apparentTypes_.end())) {
20993af6ab5fSopenharmony_ci        return it->second;
21003af6ab5fSopenharmony_ci    }
21013af6ab5fSopenharmony_ci    auto cached = [this, type](Type *res) {
21023af6ab5fSopenharmony_ci        if (type != res) {
21033af6ab5fSopenharmony_ci            apparentTypes_.insert({type, res});
21043af6ab5fSopenharmony_ci        }
21053af6ab5fSopenharmony_ci        apparentTypes_.insert({res, res});
21063af6ab5fSopenharmony_ci        return res;
21073af6ab5fSopenharmony_ci    };
21083af6ab5fSopenharmony_ci
21093af6ab5fSopenharmony_ci    if (type->IsETSTypeParameter()) {
21103af6ab5fSopenharmony_ci        return cached(GetApparentType(type->AsETSTypeParameter()->GetConstraintType()));
21113af6ab5fSopenharmony_ci    }
21123af6ab5fSopenharmony_ci    if (type->IsETSNonNullishType()) {
21133af6ab5fSopenharmony_ci        return cached(
21143af6ab5fSopenharmony_ci            GetNonNullishType(GetApparentType(type->AsETSNonNullishType()->GetUnderlying()->GetConstraintType())));
21153af6ab5fSopenharmony_ci    }
21163af6ab5fSopenharmony_ci    if (type->IsETSArrayType()) {
21173af6ab5fSopenharmony_ci        return cached(type);
21183af6ab5fSopenharmony_ci    }
21193af6ab5fSopenharmony_ci    if (type->IsETSUnionType()) {
21203af6ab5fSopenharmony_ci        bool differ = false;
21213af6ab5fSopenharmony_ci        ArenaVector<checker::Type *> newConstituent(Allocator()->Adapter());
21223af6ab5fSopenharmony_ci        for (auto const &ct : type->AsETSUnionType()->ConstituentTypes()) {
21233af6ab5fSopenharmony_ci            newConstituent.push_back(GetApparentType(ct));
21243af6ab5fSopenharmony_ci            differ |= (newConstituent.back() != ct);
21253af6ab5fSopenharmony_ci        }
21263af6ab5fSopenharmony_ci        return cached(differ ? CreateETSUnionType(std::move(newConstituent)) : type);
21273af6ab5fSopenharmony_ci    }
21283af6ab5fSopenharmony_ci    return cached(type);
21293af6ab5fSopenharmony_ci}
21303af6ab5fSopenharmony_ci
21313af6ab5fSopenharmony_ciType const *ETSChecker::GetApparentType(Type const *type) const
21323af6ab5fSopenharmony_ci{
21333af6ab5fSopenharmony_ci    if (auto it = apparentTypes_.find(type); LIKELY(it != apparentTypes_.end())) {
21343af6ab5fSopenharmony_ci        return it->second;
21353af6ab5fSopenharmony_ci    }
21363af6ab5fSopenharmony_ci    // Relaxed for some types
21373af6ab5fSopenharmony_ci    if (type->IsETSTypeParameter()) {
21383af6ab5fSopenharmony_ci        return GetApparentType(type->AsETSTypeParameter()->GetConstraintType());
21393af6ab5fSopenharmony_ci    }
21403af6ab5fSopenharmony_ci    if (type->IsETSArrayType()) {
21413af6ab5fSopenharmony_ci        return type;
21423af6ab5fSopenharmony_ci    }
21433af6ab5fSopenharmony_ci    if (type->IsETSUnionType() || type->IsETSNonNullishType()) {
21443af6ab5fSopenharmony_ci        ASSERT_PRINT(false, std::string("Type ") + type->ToString() + " was not found in apparent_types_");
21453af6ab5fSopenharmony_ci    }
21463af6ab5fSopenharmony_ci    return type;
21473af6ab5fSopenharmony_ci}
21483af6ab5fSopenharmony_ci
21493af6ab5fSopenharmony_ciETSObjectType *ETSChecker::GetClosestCommonAncestor(ETSObjectType *source, ETSObjectType *target)
21503af6ab5fSopenharmony_ci{
21513af6ab5fSopenharmony_ci    if (source->AsETSObjectType()->GetDeclNode() == target->AsETSObjectType()->GetDeclNode()) {
21523af6ab5fSopenharmony_ci        return source;
21533af6ab5fSopenharmony_ci    }
21543af6ab5fSopenharmony_ci    if (target->SuperType() == nullptr) {
21553af6ab5fSopenharmony_ci        return GlobalETSObjectType();
21563af6ab5fSopenharmony_ci    }
21573af6ab5fSopenharmony_ci
21583af6ab5fSopenharmony_ci    auto *targetBase = GetOriginalBaseType(target->SuperType());
21593af6ab5fSopenharmony_ci    auto *targetType = targetBase == nullptr ? target->SuperType() : targetBase;
21603af6ab5fSopenharmony_ci
21613af6ab5fSopenharmony_ci    auto *sourceBase = GetOriginalBaseType(source);
21623af6ab5fSopenharmony_ci    auto *sourceType = sourceBase == nullptr ? source : sourceBase;
21633af6ab5fSopenharmony_ci
21643af6ab5fSopenharmony_ci    if (Relation()->IsSupertypeOf(targetType, sourceType)) {
21653af6ab5fSopenharmony_ci        // NOTE: TorokG. Extending the search to find intersection types
21663af6ab5fSopenharmony_ci        return targetType;
21673af6ab5fSopenharmony_ci    }
21683af6ab5fSopenharmony_ci
21693af6ab5fSopenharmony_ci    return GetClosestCommonAncestor(sourceType, targetType);
21703af6ab5fSopenharmony_ci}
21713af6ab5fSopenharmony_ci
21723af6ab5fSopenharmony_civoid ETSChecker::CheckInvokeMethodsLegitimacy(ETSObjectType *const classType)
21733af6ab5fSopenharmony_ci{
21743af6ab5fSopenharmony_ci    if (classType->HasObjectFlag(ETSObjectFlags::CHECKED_INVOKE_LEGITIMACY)) {
21753af6ab5fSopenharmony_ci        return;
21763af6ab5fSopenharmony_ci    }
21773af6ab5fSopenharmony_ci
21783af6ab5fSopenharmony_ci    auto searchFlag = PropertySearchFlags::SEARCH_IN_INTERFACES | PropertySearchFlags::SEARCH_IN_BASE |
21793af6ab5fSopenharmony_ci                      PropertySearchFlags::SEARCH_STATIC_METHOD;
21803af6ab5fSopenharmony_ci
21813af6ab5fSopenharmony_ci    auto *const invokeMethod = classType->GetProperty(compiler::Signatures::STATIC_INVOKE_METHOD, searchFlag);
21823af6ab5fSopenharmony_ci    if (invokeMethod == nullptr) {
21833af6ab5fSopenharmony_ci        classType->AddObjectFlag(ETSObjectFlags::CHECKED_INVOKE_LEGITIMACY);
21843af6ab5fSopenharmony_ci        return;
21853af6ab5fSopenharmony_ci    }
21863af6ab5fSopenharmony_ci
21873af6ab5fSopenharmony_ci    auto *const instantiateMethod = classType->GetProperty(compiler::Signatures::STATIC_INSTANTIATE_METHOD, searchFlag);
21883af6ab5fSopenharmony_ci    if (instantiateMethod != nullptr) {
21893af6ab5fSopenharmony_ci        LogTypeError({"Static ", compiler::Signatures::STATIC_INVOKE_METHOD, " method and static ",
21903af6ab5fSopenharmony_ci                      compiler::Signatures::STATIC_INSTANTIATE_METHOD, " method both exist in class/interface ",
21913af6ab5fSopenharmony_ci                      classType->Name(), " is not allowed."},
21923af6ab5fSopenharmony_ci                     classType->GetDeclNode()->Start());
21933af6ab5fSopenharmony_ci    }
21943af6ab5fSopenharmony_ci    classType->AddObjectFlag(ETSObjectFlags::CHECKED_INVOKE_LEGITIMACY);
21953af6ab5fSopenharmony_ci}
21963af6ab5fSopenharmony_ci
21973af6ab5fSopenharmony_ci}  // namespace ark::es2panda::checker
2198