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 "ETSAnalyzer.h"
173af6ab5fSopenharmony_ci
183af6ab5fSopenharmony_ci#include "types/signature.h"
193af6ab5fSopenharmony_ci#include "util/helpers.h"
203af6ab5fSopenharmony_ci#include "checker/ETSchecker.h"
213af6ab5fSopenharmony_ci#include "checker/ets/castingContext.h"
223af6ab5fSopenharmony_ci#include "checker/ets/typeRelationContext.h"
233af6ab5fSopenharmony_ci#include "checker/types/globalTypesHolder.h"
243af6ab5fSopenharmony_ci#include "checker/types/ets/etsTupleType.h"
253af6ab5fSopenharmony_ci#include "checker/types/ets/etsAsyncFuncReturnType.h"
263af6ab5fSopenharmony_ci#include "evaluate/scopedDebugInfoPlugin.h"
273af6ab5fSopenharmony_ci#include "types/ts/undefinedType.h"
283af6ab5fSopenharmony_ci#include "ir/statements/namespaceDeclaration.h"
293af6ab5fSopenharmony_ci
303af6ab5fSopenharmony_cinamespace ark::es2panda::checker {
313af6ab5fSopenharmony_ci
323af6ab5fSopenharmony_ciETSChecker *ETSAnalyzer::GetETSChecker() const
333af6ab5fSopenharmony_ci{
343af6ab5fSopenharmony_ci    return static_cast<ETSChecker *>(GetChecker());
353af6ab5fSopenharmony_ci}
363af6ab5fSopenharmony_ci
373af6ab5fSopenharmony_ci// from base folder
383af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::CatchClause *st) const
393af6ab5fSopenharmony_ci{
403af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
413af6ab5fSopenharmony_ci    checker::ETSObjectType *exceptionType = checker->GlobalETSObjectType();
423af6ab5fSopenharmony_ci
433af6ab5fSopenharmony_ci    ir::Identifier *paramIdent = st->Param()->AsIdentifier();
443af6ab5fSopenharmony_ci
453af6ab5fSopenharmony_ci    if (paramIdent->TypeAnnotation() != nullptr) {
463af6ab5fSopenharmony_ci        checker::Type *catchParamAnnotationType = paramIdent->TypeAnnotation()->GetType(checker);
473af6ab5fSopenharmony_ci
483af6ab5fSopenharmony_ci        exceptionType = checker->CheckExceptionOrErrorType(catchParamAnnotationType, st->Param()->Start());
493af6ab5fSopenharmony_ci    }
503af6ab5fSopenharmony_ci
513af6ab5fSopenharmony_ci    paramIdent->Variable()->SetTsType(exceptionType);
523af6ab5fSopenharmony_ci
533af6ab5fSopenharmony_ci    st->Body()->Check(checker);
543af6ab5fSopenharmony_ci
553af6ab5fSopenharmony_ci    st->SetTsType(exceptionType);
563af6ab5fSopenharmony_ci    return exceptionType;
573af6ab5fSopenharmony_ci}
583af6ab5fSopenharmony_ci
593af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ClassDefinition *node) const
603af6ab5fSopenharmony_ci{
613af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
623af6ab5fSopenharmony_ci
633af6ab5fSopenharmony_ci    if (node->TsTypeOrError() == nullptr) {
643af6ab5fSopenharmony_ci        checker->BuildBasicClassProperties(node);
653af6ab5fSopenharmony_ci    }
663af6ab5fSopenharmony_ci
673af6ab5fSopenharmony_ci    if (!node->IsClassDefinitionChecked()) {
683af6ab5fSopenharmony_ci        checker->CheckClassDefinition(node);
693af6ab5fSopenharmony_ci    }
703af6ab5fSopenharmony_ci
713af6ab5fSopenharmony_ci    return nullptr;
723af6ab5fSopenharmony_ci}
733af6ab5fSopenharmony_ci
743af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ClassProperty *st) const
753af6ab5fSopenharmony_ci{
763af6ab5fSopenharmony_ci    ASSERT(st->Id() != nullptr);
773af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
783af6ab5fSopenharmony_ci
793af6ab5fSopenharmony_ci    if (st->TsTypeOrError() != nullptr) {
803af6ab5fSopenharmony_ci        return st->TsTypeOrError();
813af6ab5fSopenharmony_ci    }
823af6ab5fSopenharmony_ci
833af6ab5fSopenharmony_ci    checker::SavedCheckerContext savedContext(checker, checker->Context().Status(),
843af6ab5fSopenharmony_ci                                              checker->Context().ContainingClass(),
853af6ab5fSopenharmony_ci                                              checker->Context().ContainingSignature());
863af6ab5fSopenharmony_ci
873af6ab5fSopenharmony_ci    if (st->IsStatic()) {
883af6ab5fSopenharmony_ci        checker->AddStatus(checker::CheckerStatus::IN_STATIC_CONTEXT);
893af6ab5fSopenharmony_ci    }
903af6ab5fSopenharmony_ci
913af6ab5fSopenharmony_ci    st->SetTsType(checker->CheckVariableDeclaration(st->Id(), st->TypeAnnotation(), st->Value(), st->Modifiers()));
923af6ab5fSopenharmony_ci
933af6ab5fSopenharmony_ci    return st->TsTypeOrError();
943af6ab5fSopenharmony_ci}
953af6ab5fSopenharmony_ci
963af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ClassStaticBlock *st) const
973af6ab5fSopenharmony_ci{
983af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
993af6ab5fSopenharmony_ci
1003af6ab5fSopenharmony_ci    if (checker->HasStatus(checker::CheckerStatus::INNER_CLASS)) {
1013af6ab5fSopenharmony_ci        checker->LogTypeError("Static initializer is not allowed in inner class.", st->Start());
1023af6ab5fSopenharmony_ci        st->SetTsType(checker->GlobalTypeError());
1033af6ab5fSopenharmony_ci        return st->TsTypeOrError();
1043af6ab5fSopenharmony_ci    }
1053af6ab5fSopenharmony_ci
1063af6ab5fSopenharmony_ci    auto *func = st->Function();
1073af6ab5fSopenharmony_ci    checker->BuildFunctionSignature(func);
1083af6ab5fSopenharmony_ci    if (func->Signature() == nullptr) {
1093af6ab5fSopenharmony_ci        st->SetTsType(checker->GlobalTypeError());
1103af6ab5fSopenharmony_ci        return st->TsTypeOrError();
1113af6ab5fSopenharmony_ci    }
1123af6ab5fSopenharmony_ci    st->SetTsType(checker->BuildNamedFunctionType(func));
1133af6ab5fSopenharmony_ci    checker::ScopeContext scopeCtx(checker, func->Scope());
1143af6ab5fSopenharmony_ci    checker::SavedCheckerContext savedContext(checker, checker->Context().Status(),
1153af6ab5fSopenharmony_ci                                              checker->Context().ContainingClass());
1163af6ab5fSopenharmony_ci    checker->AddStatus(checker::CheckerStatus::IN_STATIC_BLOCK | checker::CheckerStatus::IN_STATIC_CONTEXT);
1173af6ab5fSopenharmony_ci    func->Body()->Check(checker);
1183af6ab5fSopenharmony_ci    return st->TsType();
1193af6ab5fSopenharmony_ci}
1203af6ab5fSopenharmony_ci
1213af6ab5fSopenharmony_ci// Satisfy the Chinese code checker
1223af6ab5fSopenharmony_cistatic void HandleNativeAndAsyncMethods(ETSChecker *checker, ir::MethodDefinition *node)
1233af6ab5fSopenharmony_ci{
1243af6ab5fSopenharmony_ci    auto *scriptFunc = node->Function();
1253af6ab5fSopenharmony_ci    if (node->IsNative()) {
1263af6ab5fSopenharmony_ci        if (scriptFunc->ReturnTypeAnnotation() == nullptr) {
1273af6ab5fSopenharmony_ci            checker->LogTypeError("'Native' method should have explicit return type", scriptFunc->Start());
1283af6ab5fSopenharmony_ci            node->SetTsType(checker->GlobalTypeError());
1293af6ab5fSopenharmony_ci        }
1303af6ab5fSopenharmony_ci        ASSERT(!scriptFunc->IsGetter() && !scriptFunc->IsSetter());
1313af6ab5fSopenharmony_ci    }
1323af6ab5fSopenharmony_ci
1333af6ab5fSopenharmony_ci    if (IsAsyncMethod(node)) {
1343af6ab5fSopenharmony_ci        if (scriptFunc->ReturnTypeAnnotation() != nullptr) {
1353af6ab5fSopenharmony_ci            auto *asyncFuncReturnType = scriptFunc->Signature()->ReturnType();
1363af6ab5fSopenharmony_ci
1373af6ab5fSopenharmony_ci            if (!asyncFuncReturnType->IsETSObjectType() ||
1383af6ab5fSopenharmony_ci                asyncFuncReturnType->AsETSObjectType()->GetOriginalBaseType() != checker->GlobalBuiltinPromiseType()) {
1393af6ab5fSopenharmony_ci                checker->LogTypeError("Return type of async function must be 'Promise'.", scriptFunc->Start());
1403af6ab5fSopenharmony_ci                scriptFunc->Signature()->SetReturnType(checker->GlobalTypeError());
1413af6ab5fSopenharmony_ci                return;
1423af6ab5fSopenharmony_ci            }
1433af6ab5fSopenharmony_ci        }
1443af6ab5fSopenharmony_ci
1453af6ab5fSopenharmony_ci        if (node->Function()->HasBody()) {
1463af6ab5fSopenharmony_ci            ComposeAsyncImplMethod(checker, node);
1473af6ab5fSopenharmony_ci        }
1483af6ab5fSopenharmony_ci    }
1493af6ab5fSopenharmony_ci}
1503af6ab5fSopenharmony_ci
1513af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::MethodDefinition *node) const
1523af6ab5fSopenharmony_ci{
1533af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
1543af6ab5fSopenharmony_ci
1553af6ab5fSopenharmony_ci    auto *scriptFunc = node->Function();
1563af6ab5fSopenharmony_ci
1573af6ab5fSopenharmony_ci    if (scriptFunc == nullptr) {
1583af6ab5fSopenharmony_ci        checker->LogTypeError("Invalid function expression", node->Start());
1593af6ab5fSopenharmony_ci        node->SetTsType(checker->GlobalTypeError());
1603af6ab5fSopenharmony_ci        return node->TsTypeOrError();
1613af6ab5fSopenharmony_ci    }
1623af6ab5fSopenharmony_ci
1633af6ab5fSopenharmony_ci    if (scriptFunc->IsProxy()) {
1643af6ab5fSopenharmony_ci        return nullptr;
1653af6ab5fSopenharmony_ci    }
1663af6ab5fSopenharmony_ci
1673af6ab5fSopenharmony_ci    // NOTE: aszilagyi. make it correctly check for open function not have body
1683af6ab5fSopenharmony_ci    if (!scriptFunc->HasBody() && !(node->IsAbstract() || node->IsNative() || node->IsDeclare() ||
1693af6ab5fSopenharmony_ci                                    checker->HasStatus(checker::CheckerStatus::IN_INTERFACE))) {
1703af6ab5fSopenharmony_ci        checker->LogTypeError("Only abstract or native methods can't have body.", scriptFunc->Start());
1713af6ab5fSopenharmony_ci        node->SetTsType(checker->GlobalTypeError());
1723af6ab5fSopenharmony_ci        return node->TsTypeOrError();
1733af6ab5fSopenharmony_ci    }
1743af6ab5fSopenharmony_ci
1753af6ab5fSopenharmony_ci    if (scriptFunc->ReturnTypeAnnotation() == nullptr &&
1763af6ab5fSopenharmony_ci        (node->IsNative() || (node->IsDeclare() && !node->IsConstructor()))) {
1773af6ab5fSopenharmony_ci        checker->LogTypeError("Native and Declare methods should have explicit return type.", scriptFunc->Start());
1783af6ab5fSopenharmony_ci        node->SetTsType(checker->GlobalTypeError());
1793af6ab5fSopenharmony_ci        return node->TsTypeOrError();
1803af6ab5fSopenharmony_ci    }
1813af6ab5fSopenharmony_ci
1823af6ab5fSopenharmony_ci    if (node->TsTypeOrError() == nullptr) {
1833af6ab5fSopenharmony_ci        node->SetTsType(checker->BuildMethodSignature(node));
1843af6ab5fSopenharmony_ci    }
1853af6ab5fSopenharmony_ci
1863af6ab5fSopenharmony_ci    this->CheckMethodModifiers(node);
1873af6ab5fSopenharmony_ci    HandleNativeAndAsyncMethods(checker, node);
1883af6ab5fSopenharmony_ci    DoBodyTypeChecking(checker, node, scriptFunc);
1893af6ab5fSopenharmony_ci    CheckPredefinedMethodReturnType(checker, scriptFunc);
1903af6ab5fSopenharmony_ci    if (node->TsTypeOrError()->IsTypeError()) {
1913af6ab5fSopenharmony_ci        return node->TsTypeOrError();
1923af6ab5fSopenharmony_ci    }
1933af6ab5fSopenharmony_ci    // NOTE(gogabr): temporary, until we have proper bridges, see #16485
1943af6ab5fSopenharmony_ci    // Don't check overriding for synthetic functional classes.
1953af6ab5fSopenharmony_ci    if ((node->Parent()->Modifiers() & ir::ModifierFlags::FUNCTIONAL) == 0) {
1963af6ab5fSopenharmony_ci        checker->CheckOverride(node->TsType()->AsETSFunctionType()->FindSignature(node->Function()));
1973af6ab5fSopenharmony_ci    }
1983af6ab5fSopenharmony_ci
1993af6ab5fSopenharmony_ci    for (auto *overload : node->Overloads()) {
2003af6ab5fSopenharmony_ci        overload->Check(checker);
2013af6ab5fSopenharmony_ci    }
2023af6ab5fSopenharmony_ci
2033af6ab5fSopenharmony_ci    if (scriptFunc->IsRethrowing()) {
2043af6ab5fSopenharmony_ci        checker->CheckRethrowingFunction(scriptFunc);
2053af6ab5fSopenharmony_ci    }
2063af6ab5fSopenharmony_ci
2073af6ab5fSopenharmony_ci    return node->TsType();
2083af6ab5fSopenharmony_ci}
2093af6ab5fSopenharmony_ci
2103af6ab5fSopenharmony_civoid ETSAnalyzer::CheckMethodModifiers(ir::MethodDefinition *node) const
2113af6ab5fSopenharmony_ci{
2123af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
2133af6ab5fSopenharmony_ci    auto const notValidInAbstract = ir::ModifierFlags::NATIVE | ir::ModifierFlags::PRIVATE |
2143af6ab5fSopenharmony_ci                                    ir::ModifierFlags::OVERRIDE | ir::ModifierFlags::FINAL | ir::ModifierFlags::STATIC;
2153af6ab5fSopenharmony_ci
2163af6ab5fSopenharmony_ci    if (node->IsAbstract() && (node->flags_ & notValidInAbstract) != 0U) {
2173af6ab5fSopenharmony_ci        checker->LogTypeError(
2183af6ab5fSopenharmony_ci            "Invalid method modifier(s): an abstract method can't have private, override, static, final or native "
2193af6ab5fSopenharmony_ci            "modifier.",
2203af6ab5fSopenharmony_ci            node->Start());
2213af6ab5fSopenharmony_ci        node->SetTsType(checker->GlobalTypeError());
2223af6ab5fSopenharmony_ci        return;
2233af6ab5fSopenharmony_ci    }
2243af6ab5fSopenharmony_ci
2253af6ab5fSopenharmony_ci    if (node->Function() == nullptr) {
2263af6ab5fSopenharmony_ci        checker->LogTypeError("Invalid function expression", node->Start());
2273af6ab5fSopenharmony_ci        node->SetTsType(checker->GlobalTypeError());
2283af6ab5fSopenharmony_ci        return;
2293af6ab5fSopenharmony_ci    }
2303af6ab5fSopenharmony_ci
2313af6ab5fSopenharmony_ci    if ((node->IsAbstract() || (!node->Function()->HasBody() && !node->IsNative() && !node->IsDeclare())) &&
2323af6ab5fSopenharmony_ci        !(checker->HasStatus(checker::CheckerStatus::IN_ABSTRACT) ||
2333af6ab5fSopenharmony_ci          checker->HasStatus(checker::CheckerStatus::IN_INTERFACE))) {
2343af6ab5fSopenharmony_ci        checker->LogTypeError("Non abstract class has abstract method.", node->Start());
2353af6ab5fSopenharmony_ci        node->SetTsType(checker->GlobalTypeError());
2363af6ab5fSopenharmony_ci    }
2373af6ab5fSopenharmony_ci
2383af6ab5fSopenharmony_ci    auto const notValidInFinal = ir::ModifierFlags::ABSTRACT | ir::ModifierFlags::STATIC | ir::ModifierFlags::NATIVE;
2393af6ab5fSopenharmony_ci
2403af6ab5fSopenharmony_ci    if (node->IsFinal() && (node->flags_ & notValidInFinal) != 0U) {
2413af6ab5fSopenharmony_ci        checker->LogTypeError(
2423af6ab5fSopenharmony_ci            "Invalid method modifier(s): a final method can't have abstract, static or native modifier.",
2433af6ab5fSopenharmony_ci            node->Start());
2443af6ab5fSopenharmony_ci        node->SetTsType(checker->GlobalTypeError());
2453af6ab5fSopenharmony_ci    }
2463af6ab5fSopenharmony_ci
2473af6ab5fSopenharmony_ci    auto const notValidInStatic = ir::ModifierFlags::ABSTRACT | ir::ModifierFlags::FINAL | ir::ModifierFlags::OVERRIDE;
2483af6ab5fSopenharmony_ci
2493af6ab5fSopenharmony_ci    if (node->IsStatic() && (node->flags_ & notValidInStatic) != 0U) {
2503af6ab5fSopenharmony_ci        checker->LogTypeError(
2513af6ab5fSopenharmony_ci            "Invalid method modifier(s): a static method can't have abstract, final or override modifier.",
2523af6ab5fSopenharmony_ci            node->Start());
2533af6ab5fSopenharmony_ci        node->SetTsType(checker->GlobalTypeError());
2543af6ab5fSopenharmony_ci    }
2553af6ab5fSopenharmony_ci}
2563af6ab5fSopenharmony_ci
2573af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::Property *expr) const
2583af6ab5fSopenharmony_ci{
2593af6ab5fSopenharmony_ci    return nullptr;
2603af6ab5fSopenharmony_ci}
2613af6ab5fSopenharmony_ci
2623af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::SpreadElement *expr) const
2633af6ab5fSopenharmony_ci{
2643af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
2653af6ab5fSopenharmony_ci    checker::Type *elementType =
2663af6ab5fSopenharmony_ci        expr->AsSpreadElement()->Argument()->AsIdentifier()->Check(checker)->AsETSArrayType()->ElementType();
2673af6ab5fSopenharmony_ci    expr->SetTsType(elementType);
2683af6ab5fSopenharmony_ci    return expr->TsType();
2693af6ab5fSopenharmony_ci}
2703af6ab5fSopenharmony_ci
2713af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::TemplateElement *expr) const
2723af6ab5fSopenharmony_ci{
2733af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
2743af6ab5fSopenharmony_ci    expr->SetTsType(checker->CreateETSStringLiteralType(expr->Raw()));
2753af6ab5fSopenharmony_ci    return expr->TsType();
2763af6ab5fSopenharmony_ci}
2773af6ab5fSopenharmony_ci
2783af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ETSClassLiteral *expr) const
2793af6ab5fSopenharmony_ci{
2803af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
2813af6ab5fSopenharmony_ci    auto *const literal = expr->Expr();
2823af6ab5fSopenharmony_ci
2833af6ab5fSopenharmony_ci    checker->LogTypeError("Class literal is not yet supported.", literal->Start());
2843af6ab5fSopenharmony_ci    expr->SetTsType(checker->GlobalTypeError());
2853af6ab5fSopenharmony_ci    return expr->TsTypeOrError();
2863af6ab5fSopenharmony_ci
2873af6ab5fSopenharmony_ci    auto *exprType = literal->Check(checker);
2883af6ab5fSopenharmony_ci
2893af6ab5fSopenharmony_ci    if (exprType->IsETSVoidType()) {
2903af6ab5fSopenharmony_ci        checker->LogTypeError("Invalid .class reference", literal->Start());
2913af6ab5fSopenharmony_ci        expr->SetTsType(checker->GlobalTypeError());
2923af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
2933af6ab5fSopenharmony_ci    }
2943af6ab5fSopenharmony_ci
2953af6ab5fSopenharmony_ci    ArenaVector<checker::Type *> typeArgTypes(checker->Allocator()->Adapter());
2963af6ab5fSopenharmony_ci    typeArgTypes.push_back(exprType);  // NOTE: Box it if it's a primitive type
2973af6ab5fSopenharmony_ci
2983af6ab5fSopenharmony_ci    checker::InstantiationContext ctx(checker, checker->GlobalBuiltinTypeType(), std::move(typeArgTypes),
2993af6ab5fSopenharmony_ci                                      expr->Range().start);
3003af6ab5fSopenharmony_ci    expr->SetTsType(ctx.Result());
3013af6ab5fSopenharmony_ci
3023af6ab5fSopenharmony_ci    return expr->TsTypeOrError();
3033af6ab5fSopenharmony_ci}
3043af6ab5fSopenharmony_ci
3053af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ETSFunctionType *node) const
3063af6ab5fSopenharmony_ci{
3073af6ab5fSopenharmony_ci    if (node->TsType() != nullptr) {
3083af6ab5fSopenharmony_ci        return node->TsType();
3093af6ab5fSopenharmony_ci    }
3103af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
3113af6ab5fSopenharmony_ci
3123af6ab5fSopenharmony_ci    size_t optionalParameterIndex = node->DefaultParamIndex();
3133af6ab5fSopenharmony_ci    auto *genericInterfaceType = checker->GlobalBuiltinFunctionType(node->Params().size(), node->Flags());
3143af6ab5fSopenharmony_ci    node->SetFunctionalInterface(genericInterfaceType->GetDeclNode()->AsTSInterfaceDeclaration());
3153af6ab5fSopenharmony_ci
3163af6ab5fSopenharmony_ci    auto *tsType = checker->GetCachedFunctionalInterface(node);
3173af6ab5fSopenharmony_ci    node->SetTsType(tsType);
3183af6ab5fSopenharmony_ci    if (tsType != nullptr) {
3193af6ab5fSopenharmony_ci        return tsType;
3203af6ab5fSopenharmony_ci    }
3213af6ab5fSopenharmony_ci
3223af6ab5fSopenharmony_ci    auto *substitution = checker->NewSubstitution();
3233af6ab5fSopenharmony_ci    ETSObjectType *interfaceType;
3243af6ab5fSopenharmony_ci
3253af6ab5fSopenharmony_ci    if (optionalParameterIndex == node->Params().size()) {
3263af6ab5fSopenharmony_ci        interfaceType = CreateInterfaceTypeForETSFunctionType(checker, node, genericInterfaceType, substitution);
3273af6ab5fSopenharmony_ci    } else {
3283af6ab5fSopenharmony_ci        interfaceType = CreateOptionalSignaturesForFunctionalType(checker, node, genericInterfaceType, substitution,
3293af6ab5fSopenharmony_ci                                                                  optionalParameterIndex);
3303af6ab5fSopenharmony_ci    }
3313af6ab5fSopenharmony_ci
3323af6ab5fSopenharmony_ci    node->SetTsType(interfaceType);
3333af6ab5fSopenharmony_ci    return interfaceType;
3343af6ab5fSopenharmony_ci}
3353af6ab5fSopenharmony_ci
3363af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ETSLaunchExpression *expr) const
3373af6ab5fSopenharmony_ci{
3383af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
3393af6ab5fSopenharmony_ci    expr->expr_->Check(checker);
3403af6ab5fSopenharmony_ci    auto *const launchPromiseType =
3413af6ab5fSopenharmony_ci        checker->GlobalBuiltinPromiseType()
3423af6ab5fSopenharmony_ci            ->Instantiate(checker->Allocator(), checker->Relation(), checker->GetGlobalTypesHolder())
3433af6ab5fSopenharmony_ci            ->AsETSObjectType();
3443af6ab5fSopenharmony_ci    launchPromiseType->AddTypeFlag(checker::TypeFlag::GENERIC);
3453af6ab5fSopenharmony_ci
3463af6ab5fSopenharmony_ci    // Launch expression returns a Promise<T> type, so we need to insert the expression's type
3473af6ab5fSopenharmony_ci    // as type parameter for the Promise class.
3483af6ab5fSopenharmony_ci
3493af6ab5fSopenharmony_ci    auto exprType = [&checker](auto *tsType) {
3503af6ab5fSopenharmony_ci        if (tsType->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) {
3513af6ab5fSopenharmony_ci            return checker->PrimitiveTypeAsETSBuiltinType(tsType);
3523af6ab5fSopenharmony_ci        }
3533af6ab5fSopenharmony_ci
3543af6ab5fSopenharmony_ci        return tsType;
3553af6ab5fSopenharmony_ci    }(expr->expr_->TsType());
3563af6ab5fSopenharmony_ci
3573af6ab5fSopenharmony_ci    checker::Substitution *substitution = checker->NewSubstitution();
3583af6ab5fSopenharmony_ci    ASSERT(launchPromiseType->TypeArguments().size() == 1);
3593af6ab5fSopenharmony_ci    checker::ETSChecker::EmplaceSubstituted(
3603af6ab5fSopenharmony_ci        substitution, launchPromiseType->TypeArguments()[0]->AsETSTypeParameter()->GetOriginal(), exprType);
3613af6ab5fSopenharmony_ci
3623af6ab5fSopenharmony_ci    expr->SetTsType(launchPromiseType->Substitute(checker->Relation(), substitution));
3633af6ab5fSopenharmony_ci    return expr->TsType();
3643af6ab5fSopenharmony_ci}
3653af6ab5fSopenharmony_ci
3663af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ETSNewArrayInstanceExpression *expr) const
3673af6ab5fSopenharmony_ci{
3683af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
3693af6ab5fSopenharmony_ci
3703af6ab5fSopenharmony_ci    auto *elementType = expr->TypeReference()->GetType(checker);
3713af6ab5fSopenharmony_ci    checker->ValidateArrayIndex(expr->Dimension(), true);
3723af6ab5fSopenharmony_ci    if (!elementType->HasTypeFlag(TypeFlag::ETS_PRIMITIVE)) {
3733af6ab5fSopenharmony_ci        if (elementType->IsETSUnionType() && !elementType->AsETSUnionType()->HasNullishType(checker)) {
3743af6ab5fSopenharmony_ci            checker->LogTypeError({"Union types in array declaration must include a nullish type."}, expr->Start());
3753af6ab5fSopenharmony_ci            expr->SetTsType(checker->GlobalTypeError());
3763af6ab5fSopenharmony_ci            return expr->TsTypeOrError();
3773af6ab5fSopenharmony_ci        }
3783af6ab5fSopenharmony_ci        if (elementType->IsETSObjectType()) {
3793af6ab5fSopenharmony_ci            auto *calleeObj = elementType->AsETSObjectType();
3803af6ab5fSopenharmony_ci            const auto flags = checker::ETSObjectFlags::ABSTRACT | checker::ETSObjectFlags::INTERFACE;
3813af6ab5fSopenharmony_ci            if (!calleeObj->HasObjectFlag(flags)) {
3823af6ab5fSopenharmony_ci                // A workaround check for new Interface[...] in test cases
3833af6ab5fSopenharmony_ci                expr->SetSignature(
3843af6ab5fSopenharmony_ci                    checker->CollectParameterlessConstructor(calleeObj->ConstructSignatures(), expr->Start()));
3853af6ab5fSopenharmony_ci                checker->ValidateSignatureAccessibility(calleeObj, nullptr, expr->Signature(), expr->Start());
3863af6ab5fSopenharmony_ci            } else {
3873af6ab5fSopenharmony_ci                checker->LogTypeError("Cannot use array creation expression with abstract classes and interfaces.",
3883af6ab5fSopenharmony_ci                                      expr->Start());
3893af6ab5fSopenharmony_ci                expr->SetTsType(checker->GlobalTypeError());
3903af6ab5fSopenharmony_ci                return expr->TsTypeOrError();
3913af6ab5fSopenharmony_ci            }
3923af6ab5fSopenharmony_ci        }
3933af6ab5fSopenharmony_ci    }
3943af6ab5fSopenharmony_ci    expr->SetTsType(checker->CreateETSArrayType(elementType));
3953af6ab5fSopenharmony_ci    checker->CreateBuiltinArraySignature(expr->TsType()->AsETSArrayType(), 1);
3963af6ab5fSopenharmony_ci    return expr->TsType();
3973af6ab5fSopenharmony_ci}
3983af6ab5fSopenharmony_ci
3993af6ab5fSopenharmony_civoid ETSAnalyzer::CheckInstantatedClass(ir::ETSNewClassInstanceExpression *expr, ETSObjectType *&calleeObj) const
4003af6ab5fSopenharmony_ci{
4013af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
4023af6ab5fSopenharmony_ci    if (expr->ClassDefinition() != nullptr) {
4033af6ab5fSopenharmony_ci        if (calleeObj->HasObjectFlag(checker::ETSObjectFlags::ABSTRACT) && calleeObj->GetDeclNode()->IsFinal()) {
4043af6ab5fSopenharmony_ci            checker->LogTypeError({"Class ", calleeObj->Name(), " cannot be both 'abstract' and 'final'."},
4053af6ab5fSopenharmony_ci                                  calleeObj->GetDeclNode()->Start());
4063af6ab5fSopenharmony_ci            expr->SetTsType(checker->GlobalTypeError());
4073af6ab5fSopenharmony_ci            return;
4083af6ab5fSopenharmony_ci        }
4093af6ab5fSopenharmony_ci
4103af6ab5fSopenharmony_ci        bool fromInterface = calleeObj->HasObjectFlag(checker::ETSObjectFlags::INTERFACE);
4113af6ab5fSopenharmony_ci        auto *classType = checker->BuildAnonymousClassProperties(
4123af6ab5fSopenharmony_ci            expr->ClassDefinition(), fromInterface ? checker->GlobalETSObjectType() : calleeObj);
4133af6ab5fSopenharmony_ci        if (fromInterface) {
4143af6ab5fSopenharmony_ci            classType->AddInterface(calleeObj);
4153af6ab5fSopenharmony_ci            calleeObj = checker->GlobalETSObjectType();
4163af6ab5fSopenharmony_ci        }
4173af6ab5fSopenharmony_ci        expr->ClassDefinition()->SetTsType(classType);
4183af6ab5fSopenharmony_ci        checker->CheckClassDefinition(expr->ClassDefinition());
4193af6ab5fSopenharmony_ci        checker->CheckInnerClassMembers(classType);
4203af6ab5fSopenharmony_ci        expr->SetTsType(classType);
4213af6ab5fSopenharmony_ci    } else if (calleeObj->HasObjectFlag(checker::ETSObjectFlags::ABSTRACT)) {
4223af6ab5fSopenharmony_ci        checker->LogTypeError({calleeObj->Name(), " is abstract therefore cannot be instantiated."}, expr->Start());
4233af6ab5fSopenharmony_ci        expr->SetTsType(checker->GlobalTypeError());
4243af6ab5fSopenharmony_ci    }
4253af6ab5fSopenharmony_ci
4263af6ab5fSopenharmony_ci    if (calleeObj->HasObjectFlag(ETSObjectFlags::REQUIRED) &&
4273af6ab5fSopenharmony_ci        !expr->HasAstNodeFlags(ir::AstNodeFlags::ALLOW_REQUIRED_INSTANTIATION)) {
4283af6ab5fSopenharmony_ci        checker->LogTypeError("Required type can be instantiated only with object literal",
4293af6ab5fSopenharmony_ci                              expr->GetTypeRef()->Start());
4303af6ab5fSopenharmony_ci        expr->SetTsType(checker->GlobalTypeError());
4313af6ab5fSopenharmony_ci    }
4323af6ab5fSopenharmony_ci}
4333af6ab5fSopenharmony_ci
4343af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ETSNewClassInstanceExpression *expr) const
4353af6ab5fSopenharmony_ci{
4363af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
4373af6ab5fSopenharmony_ci    auto *calleeType = GetCalleeType(checker, expr);
4383af6ab5fSopenharmony_ci    if (calleeType == nullptr) {
4393af6ab5fSopenharmony_ci        return expr->TsType();
4403af6ab5fSopenharmony_ci    }
4413af6ab5fSopenharmony_ci
4423af6ab5fSopenharmony_ci    if (calleeType->IsTypeError()) {
4433af6ab5fSopenharmony_ci        expr->SetTsType(calleeType);
4443af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
4453af6ab5fSopenharmony_ci    }
4463af6ab5fSopenharmony_ci    auto *calleeObj = calleeType->AsETSObjectType();
4473af6ab5fSopenharmony_ci    expr->SetTsType(calleeObj);
4483af6ab5fSopenharmony_ci
4493af6ab5fSopenharmony_ci    CheckInstantatedClass(expr, calleeObj);
4503af6ab5fSopenharmony_ci
4513af6ab5fSopenharmony_ci    if (calleeType->IsETSDynamicType() && !calleeType->AsETSDynamicType()->HasDecl()) {
4523af6ab5fSopenharmony_ci        auto lang = calleeType->AsETSDynamicType()->Language();
4533af6ab5fSopenharmony_ci        expr->SetSignature(checker->ResolveDynamicCallExpression(expr->GetTypeRef(), expr->GetArguments(), lang, true));
4543af6ab5fSopenharmony_ci    } else {
4553af6ab5fSopenharmony_ci        auto *signature = checker->ResolveConstructExpression(calleeObj, expr->GetArguments(), expr->Start());
4563af6ab5fSopenharmony_ci
4573af6ab5fSopenharmony_ci        if (signature == nullptr) {
4583af6ab5fSopenharmony_ci            expr->SetTsType(checker->GlobalTypeError());
4593af6ab5fSopenharmony_ci            return expr->TsTypeOrError();
4603af6ab5fSopenharmony_ci        }
4613af6ab5fSopenharmony_ci
4623af6ab5fSopenharmony_ci        checker->CheckObjectLiteralArguments(signature, expr->GetArguments());
4633af6ab5fSopenharmony_ci
4643af6ab5fSopenharmony_ci        checker->ValidateSignatureAccessibility(calleeObj, nullptr, signature, expr->Start());
4653af6ab5fSopenharmony_ci
4663af6ab5fSopenharmony_ci        ASSERT(signature->Function() != nullptr);
4673af6ab5fSopenharmony_ci
4683af6ab5fSopenharmony_ci        if (signature->Function()->IsThrowing() || signature->Function()->IsRethrowing()) {
4693af6ab5fSopenharmony_ci            checker->CheckThrowingStatements(expr);
4703af6ab5fSopenharmony_ci        }
4713af6ab5fSopenharmony_ci
4723af6ab5fSopenharmony_ci        if (calleeType->IsETSDynamicType()) {
4733af6ab5fSopenharmony_ci            ASSERT(signature->Function()->IsDynamic());
4743af6ab5fSopenharmony_ci            auto lang = calleeType->AsETSDynamicType()->Language();
4753af6ab5fSopenharmony_ci            expr->SetSignature(
4763af6ab5fSopenharmony_ci                checker->ResolveDynamicCallExpression(expr->GetTypeRef(), signature->Params(), lang, true));
4773af6ab5fSopenharmony_ci        } else {
4783af6ab5fSopenharmony_ci            ASSERT(!signature->Function()->IsDynamic());
4793af6ab5fSopenharmony_ci            expr->SetSignature(signature);
4803af6ab5fSopenharmony_ci        }
4813af6ab5fSopenharmony_ci    }
4823af6ab5fSopenharmony_ci
4833af6ab5fSopenharmony_ci    return expr->TsTypeOrError();
4843af6ab5fSopenharmony_ci}
4853af6ab5fSopenharmony_ci
4863af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ETSNewMultiDimArrayInstanceExpression *expr) const
4873af6ab5fSopenharmony_ci{
4883af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
4893af6ab5fSopenharmony_ci    auto *elementType = expr->TypeReference()->GetType(checker);
4903af6ab5fSopenharmony_ci
4913af6ab5fSopenharmony_ci    for (auto *dim : expr->Dimensions()) {
4923af6ab5fSopenharmony_ci        checker->ValidateArrayIndex(dim, true);
4933af6ab5fSopenharmony_ci        elementType = checker->CreateETSArrayType(elementType);
4943af6ab5fSopenharmony_ci    }
4953af6ab5fSopenharmony_ci
4963af6ab5fSopenharmony_ci    expr->SetTsType(elementType);
4973af6ab5fSopenharmony_ci    expr->SetSignature(checker->CreateBuiltinArraySignature(elementType->AsETSArrayType(), expr->Dimensions().size()));
4983af6ab5fSopenharmony_ci    return expr->TsType();
4993af6ab5fSopenharmony_ci}
5003af6ab5fSopenharmony_ci
5013af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSPackageDeclaration *st) const
5023af6ab5fSopenharmony_ci{
5033af6ab5fSopenharmony_ci    return nullptr;
5043af6ab5fSopenharmony_ci}
5053af6ab5fSopenharmony_ci
5063af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ETSParameterExpression *expr) const
5073af6ab5fSopenharmony_ci{
5083af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
5093af6ab5fSopenharmony_ci    if (expr->TsTypeOrError() == nullptr) {
5103af6ab5fSopenharmony_ci        checker::Type *paramType;
5113af6ab5fSopenharmony_ci
5123af6ab5fSopenharmony_ci        if (expr->Ident()->TsTypeOrError() != nullptr) {
5133af6ab5fSopenharmony_ci            paramType = expr->Ident()->TsTypeOrError();
5143af6ab5fSopenharmony_ci        } else {
5153af6ab5fSopenharmony_ci            paramType = !expr->IsRestParameter() ? expr->Ident()->Check(checker) : expr->spread_->Check(checker);
5163af6ab5fSopenharmony_ci            if (expr->IsDefault()) {
5173af6ab5fSopenharmony_ci                std::cout << __LINE__ << std::endl;
5183af6ab5fSopenharmony_ci                [[maybe_unused]] auto *const initType = expr->Initializer()->Check(checker);
5193af6ab5fSopenharmony_ci            }
5203af6ab5fSopenharmony_ci        }
5213af6ab5fSopenharmony_ci
5223af6ab5fSopenharmony_ci        expr->SetTsType(paramType);
5233af6ab5fSopenharmony_ci    }
5243af6ab5fSopenharmony_ci
5253af6ab5fSopenharmony_ci    return expr->TsType();
5263af6ab5fSopenharmony_ci}
5273af6ab5fSopenharmony_ci
5283af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSPrimitiveType *node) const
5293af6ab5fSopenharmony_ci{
5303af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
5313af6ab5fSopenharmony_ci    return node->GetType(checker);
5323af6ab5fSopenharmony_ci}
5333af6ab5fSopenharmony_ci
5343af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ETSStructDeclaration *node) const
5353af6ab5fSopenharmony_ci{
5363af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
5373af6ab5fSopenharmony_ci    node->Definition()->Check(checker);
5383af6ab5fSopenharmony_ci    return nullptr;
5393af6ab5fSopenharmony_ci}
5403af6ab5fSopenharmony_ci
5413af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ETSTypeReference *node) const
5423af6ab5fSopenharmony_ci{
5433af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
5443af6ab5fSopenharmony_ci    return node->GetType(checker);
5453af6ab5fSopenharmony_ci}
5463af6ab5fSopenharmony_ci
5473af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ETSTypeReferencePart *node) const
5483af6ab5fSopenharmony_ci{
5493af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
5503af6ab5fSopenharmony_ci    return node->GetType(checker);
5513af6ab5fSopenharmony_ci}
5523af6ab5fSopenharmony_ci
5533af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSNullType *node) const
5543af6ab5fSopenharmony_ci{
5553af6ab5fSopenharmony_ci    return nullptr;
5563af6ab5fSopenharmony_ci}
5573af6ab5fSopenharmony_ci
5583af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSUndefinedType *node) const
5593af6ab5fSopenharmony_ci{
5603af6ab5fSopenharmony_ci    return nullptr;
5613af6ab5fSopenharmony_ci}
5623af6ab5fSopenharmony_ci
5633af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSStringLiteralType *node) const
5643af6ab5fSopenharmony_ci{
5653af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
5663af6ab5fSopenharmony_ci    return node->GetType(checker);
5673af6ab5fSopenharmony_ci}
5683af6ab5fSopenharmony_ci
5693af6ab5fSopenharmony_ci// compile methods for EXPRESSIONS in alphabetical order
5703af6ab5fSopenharmony_ci
5713af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::GetPreferredType(ir::ArrayExpression *expr) const
5723af6ab5fSopenharmony_ci{
5733af6ab5fSopenharmony_ci    return expr->preferredType_;
5743af6ab5fSopenharmony_ci}
5753af6ab5fSopenharmony_ci
5763af6ab5fSopenharmony_cistatic bool CheckArrayElement(ETSChecker *checker, checker::Type *elementType,
5773af6ab5fSopenharmony_ci                              std::vector<checker::Type *> targetElementType, ir::Expression *currentElement,
5783af6ab5fSopenharmony_ci                              bool &isSecondaryChosen)
5793af6ab5fSopenharmony_ci{
5803af6ab5fSopenharmony_ci    if ((targetElementType[0]->IsETSArrayType() &&
5813af6ab5fSopenharmony_ci         targetElementType[0]->AsETSArrayType()->ElementType()->IsETSArrayType() &&
5823af6ab5fSopenharmony_ci         !(targetElementType[0]->AsETSArrayType()->ElementType()->IsETSTupleType() &&
5833af6ab5fSopenharmony_ci           targetElementType[1] == nullptr)) ||
5843af6ab5fSopenharmony_ci        (!checker::AssignmentContext(checker->Relation(), currentElement, elementType, targetElementType[0],
5853af6ab5fSopenharmony_ci                                     currentElement->Start(),
5863af6ab5fSopenharmony_ci                                     {"Array element type '", elementType, "' is not assignable to explicit type '",
5873af6ab5fSopenharmony_ci                                      targetElementType[0], "'"},
5883af6ab5fSopenharmony_ci                                     TypeRelationFlag::NO_THROW)
5893af6ab5fSopenharmony_ci              .IsAssignable() &&
5903af6ab5fSopenharmony_ci         !(targetElementType[0]->IsETSArrayType() && currentElement->IsArrayExpression()))) {
5913af6ab5fSopenharmony_ci        if (targetElementType[1] == nullptr) {
5923af6ab5fSopenharmony_ci            checker->LogTypeError({"Array element type '", elementType, "' is not assignable to explicit type '",
5933af6ab5fSopenharmony_ci                                   targetElementType[0], "'"},
5943af6ab5fSopenharmony_ci                                  currentElement->Start());
5953af6ab5fSopenharmony_ci            return false;
5963af6ab5fSopenharmony_ci        }
5973af6ab5fSopenharmony_ci
5983af6ab5fSopenharmony_ci        if (!(targetElementType[0]->IsETSArrayType() && currentElement->IsArrayExpression()) &&
5993af6ab5fSopenharmony_ci            !checker::AssignmentContext(checker->Relation(), currentElement, elementType, targetElementType[1],
6003af6ab5fSopenharmony_ci                                        currentElement->Start(),
6013af6ab5fSopenharmony_ci                                        {"Array element type '", elementType, "' is not assignable to explicit type '",
6023af6ab5fSopenharmony_ci                                         targetElementType[1], "'"},
6033af6ab5fSopenharmony_ci                                        TypeRelationFlag::NO_THROW)
6043af6ab5fSopenharmony_ci                 .IsAssignable()) {
6053af6ab5fSopenharmony_ci            checker->LogTypeError({"Array element type '", elementType, "' is not assignable to explicit type '",
6063af6ab5fSopenharmony_ci                                   targetElementType[1], "'"},
6073af6ab5fSopenharmony_ci                                  currentElement->Start());
6083af6ab5fSopenharmony_ci            return false;
6093af6ab5fSopenharmony_ci        }
6103af6ab5fSopenharmony_ci        isSecondaryChosen = true;
6113af6ab5fSopenharmony_ci    }
6123af6ab5fSopenharmony_ci    return true;
6133af6ab5fSopenharmony_ci}
6143af6ab5fSopenharmony_ci
6153af6ab5fSopenharmony_cistatic bool CheckElement(ir::ArrayExpression *expr, ETSChecker *checker, std::vector<checker::Type *> targetElementType,
6163af6ab5fSopenharmony_ci                         bool isPreferredTuple)
6173af6ab5fSopenharmony_ci{
6183af6ab5fSopenharmony_ci    bool isSecondaryChosen = false;
6193af6ab5fSopenharmony_ci    bool ok = true;
6203af6ab5fSopenharmony_ci
6213af6ab5fSopenharmony_ci    for (std::size_t idx = 0; idx < expr->Elements().size(); ++idx) {
6223af6ab5fSopenharmony_ci        auto *const currentElement = expr->Elements()[idx];
6233af6ab5fSopenharmony_ci
6243af6ab5fSopenharmony_ci        if (currentElement->IsArrayExpression()) {
6253af6ab5fSopenharmony_ci            if (!expr->HandleNestedArrayExpression(checker, currentElement->AsArrayExpression(), isPreferredTuple,
6263af6ab5fSopenharmony_ci                                                   idx)) {
6273af6ab5fSopenharmony_ci                continue;
6283af6ab5fSopenharmony_ci            }
6293af6ab5fSopenharmony_ci        }
6303af6ab5fSopenharmony_ci
6313af6ab5fSopenharmony_ci        if (currentElement->IsObjectExpression()) {
6323af6ab5fSopenharmony_ci            currentElement->AsObjectExpression()->SetPreferredType(
6333af6ab5fSopenharmony_ci                expr->GetPreferredType()->AsETSArrayType()->ElementType());
6343af6ab5fSopenharmony_ci        }
6353af6ab5fSopenharmony_ci
6363af6ab5fSopenharmony_ci        checker::Type *elementType = currentElement->Check(checker);
6373af6ab5fSopenharmony_ci
6383af6ab5fSopenharmony_ci        if (!elementType->IsETSArrayType() && isPreferredTuple) {
6393af6ab5fSopenharmony_ci            auto const *const tupleType = expr->GetPreferredType()->AsETSTupleType();
6403af6ab5fSopenharmony_ci
6413af6ab5fSopenharmony_ci            auto *compareType = tupleType->GetTypeAtIndex(idx);
6423af6ab5fSopenharmony_ci            if (compareType == nullptr) {
6433af6ab5fSopenharmony_ci                checker->LogTypeError({"Too many elements in array initializer for tuple with size of ",
6443af6ab5fSopenharmony_ci                                       static_cast<uint32_t>(tupleType->GetTupleSize())},
6453af6ab5fSopenharmony_ci                                      currentElement->Start());
6463af6ab5fSopenharmony_ci                ok = false;
6473af6ab5fSopenharmony_ci                continue;
6483af6ab5fSopenharmony_ci            }
6493af6ab5fSopenharmony_ci            // clang-format off
6503af6ab5fSopenharmony_ci            if (!AssignmentContext(checker->Relation(), currentElement, elementType, compareType,
6513af6ab5fSopenharmony_ci                                   currentElement->Start(), {}, TypeRelationFlag::NO_THROW).IsAssignable()) {
6523af6ab5fSopenharmony_ci                checker->LogTypeError({"Array initializer's type is not assignable to tuple type at index: ", idx},
6533af6ab5fSopenharmony_ci                                      currentElement->Start());
6543af6ab5fSopenharmony_ci                                      ok=false;
6553af6ab5fSopenharmony_ci                continue;
6563af6ab5fSopenharmony_ci            }
6573af6ab5fSopenharmony_ci            // clang-format on
6583af6ab5fSopenharmony_ci
6593af6ab5fSopenharmony_ci            elementType = compareType;
6603af6ab5fSopenharmony_ci        }
6613af6ab5fSopenharmony_ci
6623af6ab5fSopenharmony_ci        if (targetElementType[0] == elementType) {
6633af6ab5fSopenharmony_ci            continue;
6643af6ab5fSopenharmony_ci        }
6653af6ab5fSopenharmony_ci
6663af6ab5fSopenharmony_ci        if (!CheckArrayElement(checker, elementType, targetElementType, currentElement, isSecondaryChosen)) {
6673af6ab5fSopenharmony_ci            ok = false;
6683af6ab5fSopenharmony_ci            continue;
6693af6ab5fSopenharmony_ci        }
6703af6ab5fSopenharmony_ci    }
6713af6ab5fSopenharmony_ci
6723af6ab5fSopenharmony_ci    return ok;
6733af6ab5fSopenharmony_ci}
6743af6ab5fSopenharmony_ci
6753af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ArrayExpression *expr) const
6763af6ab5fSopenharmony_ci{
6773af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
6783af6ab5fSopenharmony_ci    if (expr->TsTypeOrError() != nullptr) {
6793af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
6803af6ab5fSopenharmony_ci    }
6813af6ab5fSopenharmony_ci
6823af6ab5fSopenharmony_ci    if (expr->preferredType_ != nullptr && !expr->preferredType_->IsETSArrayType() &&
6833af6ab5fSopenharmony_ci        !checker->Relation()->IsSupertypeOf(expr->preferredType_, checker->GlobalETSObjectType())) {
6843af6ab5fSopenharmony_ci        checker->LogTypeError({"Expected type for array literal should be an array type, got ", expr->preferredType_},
6853af6ab5fSopenharmony_ci                              expr->Start());
6863af6ab5fSopenharmony_ci        expr->SetTsType(checker->GlobalTypeError());
6873af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
6883af6ab5fSopenharmony_ci    }
6893af6ab5fSopenharmony_ci
6903af6ab5fSopenharmony_ci    const bool isArray = (expr->preferredType_ != nullptr) && expr->preferredType_->IsETSArrayType() &&
6913af6ab5fSopenharmony_ci                         !expr->preferredType_->IsETSTupleType();
6923af6ab5fSopenharmony_ci
6933af6ab5fSopenharmony_ci    if (!expr->Elements().empty()) {
6943af6ab5fSopenharmony_ci        if (expr->preferredType_ == nullptr || expr->preferredType_ == checker->GlobalETSObjectType()) {
6953af6ab5fSopenharmony_ci            expr->preferredType_ = checker->CreateETSArrayType(expr->Elements()[0]->Check(checker));
6963af6ab5fSopenharmony_ci        }
6973af6ab5fSopenharmony_ci
6983af6ab5fSopenharmony_ci        const bool isPreferredTuple = expr->preferredType_->IsETSTupleType();
6993af6ab5fSopenharmony_ci        // NOTE(aakmaev): Need to rework type inference of array literal (#19096 internal issue)
7003af6ab5fSopenharmony_ci        auto *targetElementType =
7013af6ab5fSopenharmony_ci            checker->GetNonConstantType(expr->GetPreferredType()->AsETSArrayType()->ElementType());
7023af6ab5fSopenharmony_ci        Type *targetElementTypeSecondary = nullptr;
7033af6ab5fSopenharmony_ci        if (isPreferredTuple && !isArray) {
7043af6ab5fSopenharmony_ci            targetElementTypeSecondary = expr->GetPreferredType()->AsETSTupleType()->ElementType();
7053af6ab5fSopenharmony_ci        }
7063af6ab5fSopenharmony_ci
7073af6ab5fSopenharmony_ci        if (!CheckElement(expr, checker, {targetElementType, targetElementTypeSecondary}, isPreferredTuple)) {
7083af6ab5fSopenharmony_ci            expr->SetTsType(checker->GlobalTypeError());
7093af6ab5fSopenharmony_ci            return expr->TsTypeOrError();
7103af6ab5fSopenharmony_ci        }
7113af6ab5fSopenharmony_ci    }
7123af6ab5fSopenharmony_ci
7133af6ab5fSopenharmony_ci    if (expr->preferredType_ == nullptr) {
7143af6ab5fSopenharmony_ci        checker->LogTypeError("Can't resolve array type", expr->Start());
7153af6ab5fSopenharmony_ci        expr->SetTsType(checker->GlobalTypeError());
7163af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
7173af6ab5fSopenharmony_ci    }
7183af6ab5fSopenharmony_ci
7193af6ab5fSopenharmony_ci    expr->SetTsType(expr->preferredType_);
7203af6ab5fSopenharmony_ci    auto *const arrayType = expr->TsType()->AsETSArrayType();
7213af6ab5fSopenharmony_ci    checker->CreateBuiltinArraySignature(arrayType, arrayType->Rank());
7223af6ab5fSopenharmony_ci    return expr->TsTypeOrError();
7233af6ab5fSopenharmony_ci}
7243af6ab5fSopenharmony_ci
7253af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ArrowFunctionExpression *expr) const
7263af6ab5fSopenharmony_ci{
7273af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
7283af6ab5fSopenharmony_ci
7293af6ab5fSopenharmony_ci    if (expr->TsTypeOrError() != nullptr) {
7303af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
7313af6ab5fSopenharmony_ci    }
7323af6ab5fSopenharmony_ci    checker::ScopeContext scopeCtx(checker, expr->Function()->Scope());
7333af6ab5fSopenharmony_ci
7343af6ab5fSopenharmony_ci    if (checker->HasStatus(checker::CheckerStatus::IN_INSTANCE_EXTENSION_METHOD)) {
7353af6ab5fSopenharmony_ci        /*
7363af6ab5fSopenharmony_ci        example code:
7373af6ab5fSopenharmony_ci        ```
7383af6ab5fSopenharmony_ci            class A {
7393af6ab5fSopenharmony_ci                prop:number
7403af6ab5fSopenharmony_ci            }
7413af6ab5fSopenharmony_ci            function A.method() {
7423af6ab5fSopenharmony_ci                let a = () => {
7433af6ab5fSopenharmony_ci                    console.println(this.prop)
7443af6ab5fSopenharmony_ci                }
7453af6ab5fSopenharmony_ci            }
7463af6ab5fSopenharmony_ci        ```
7473af6ab5fSopenharmony_ci        here the enclosing class of arrow function should be Class A
7483af6ab5fSopenharmony_ci        */
7493af6ab5fSopenharmony_ci        checker->Context().SetContainingClass(
7503af6ab5fSopenharmony_ci            checker->Scope()->Find(varbinder::VarBinder::MANDATORY_PARAM_THIS).variable->TsType()->AsETSObjectType());
7513af6ab5fSopenharmony_ci    }
7523af6ab5fSopenharmony_ci
7533af6ab5fSopenharmony_ci    checker::SavedCheckerContext savedContext(checker, checker->Context().Status(),
7543af6ab5fSopenharmony_ci                                              checker->Context().ContainingClass());
7553af6ab5fSopenharmony_ci
7563af6ab5fSopenharmony_ci    checker->AddStatus(checker::CheckerStatus::IN_LAMBDA);
7573af6ab5fSopenharmony_ci    checker->Context().SetContainingLambda(expr);
7583af6ab5fSopenharmony_ci
7593af6ab5fSopenharmony_ci    checker->BuildFunctionSignature(expr->Function(), false);
7603af6ab5fSopenharmony_ci    if (expr->Function()->Signature() == nullptr) {
7613af6ab5fSopenharmony_ci        expr->SetTsType(checker->GlobalTypeError());
7623af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
7633af6ab5fSopenharmony_ci    }
7643af6ab5fSopenharmony_ci    auto *signature = expr->Function()->Signature();
7653af6ab5fSopenharmony_ci
7663af6ab5fSopenharmony_ci    checker->Context().SetContainingSignature(signature);
7673af6ab5fSopenharmony_ci    expr->Function()->Body()->Check(checker);
7683af6ab5fSopenharmony_ci
7693af6ab5fSopenharmony_ci    ArenaVector<Signature *> signatures(checker->Allocator()->Adapter());
7703af6ab5fSopenharmony_ci    signatures.push_back(signature);
7713af6ab5fSopenharmony_ci    for (auto &sigInfo : checker->ComposeSignatureInfosForArrowFunction(expr)) {
7723af6ab5fSopenharmony_ci        auto sig = checker->ComposeSignature(expr->Function(), sigInfo, signature->ReturnType(), nullptr);
7733af6ab5fSopenharmony_ci        sig->AddSignatureFlag(signature->GetFlags());
7743af6ab5fSopenharmony_ci        signatures.push_back(sig);
7753af6ab5fSopenharmony_ci    }
7763af6ab5fSopenharmony_ci
7773af6ab5fSopenharmony_ci    auto *funcType = checker->CreateETSFunctionType(expr->Function(), std::move(signatures), nullptr);
7783af6ab5fSopenharmony_ci    checker->Context().SetContainingSignature(nullptr);
7793af6ab5fSopenharmony_ci
7803af6ab5fSopenharmony_ci    if (expr->Function()->IsAsyncFunc()) {
7813af6ab5fSopenharmony_ci        auto *retType = signature->ReturnType();
7823af6ab5fSopenharmony_ci        if (!retType->IsETSObjectType() ||
7833af6ab5fSopenharmony_ci            retType->AsETSObjectType()->GetOriginalBaseType() != checker->GlobalBuiltinPromiseType()) {
7843af6ab5fSopenharmony_ci            checker->LogTypeError("Return type of async lambda must be 'Promise'", expr->Function()->Start());
7853af6ab5fSopenharmony_ci            expr->SetTsType(checker->GlobalTypeError());
7863af6ab5fSopenharmony_ci            return expr->TsTypeOrError();
7873af6ab5fSopenharmony_ci        }
7883af6ab5fSopenharmony_ci    }
7893af6ab5fSopenharmony_ci
7903af6ab5fSopenharmony_ci    expr->SetTsType(funcType);
7913af6ab5fSopenharmony_ci    return expr->TsType();
7923af6ab5fSopenharmony_ci}
7933af6ab5fSopenharmony_ci
7943af6ab5fSopenharmony_cistatic bool IsInvalidArrayLengthAssignment(ir::AssignmentExpression *const expr, ETSChecker *checker)
7953af6ab5fSopenharmony_ci{
7963af6ab5fSopenharmony_ci    if (expr->Left()->IsMemberExpression() &&
7973af6ab5fSopenharmony_ci        expr->Left()->AsMemberExpression()->Object()->TsType()->IsETSArrayType() &&
7983af6ab5fSopenharmony_ci        expr->Left()->AsMemberExpression()->Property()->IsIdentifier() &&
7993af6ab5fSopenharmony_ci        expr->Left()->AsMemberExpression()->Property()->AsIdentifier()->Name().Is("length")) {
8003af6ab5fSopenharmony_ci        checker->LogTypeError("Setting the length of an array is not permitted", expr->Left()->Start());
8013af6ab5fSopenharmony_ci        return true;
8023af6ab5fSopenharmony_ci    }
8033af6ab5fSopenharmony_ci    return false;
8043af6ab5fSopenharmony_ci}
8053af6ab5fSopenharmony_ci
8063af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::GetSmartType(ir::AssignmentExpression *expr, checker::Type *leftType,
8073af6ab5fSopenharmony_ci                                         checker::Type *rightType) const
8083af6ab5fSopenharmony_ci{
8093af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
8103af6ab5fSopenharmony_ci    checker::Type *smartType = leftType;
8113af6ab5fSopenharmony_ci
8123af6ab5fSopenharmony_ci    if (expr->Left()->IsIdentifier()) {
8133af6ab5fSopenharmony_ci        //  Now try to define the actual type of Identifier so that smart cast can be used in further checker processing
8143af6ab5fSopenharmony_ci        smartType = checker->ResolveSmartType(rightType, leftType);
8153af6ab5fSopenharmony_ci        auto const *const variable = expr->Target();
8163af6ab5fSopenharmony_ci
8173af6ab5fSopenharmony_ci        //  Add/Remove/Modify smart cast for identifier
8183af6ab5fSopenharmony_ci        //  (excluding the variables defined at top-level scope or captured in lambda-functions!)
8193af6ab5fSopenharmony_ci        auto const *const variableScope = variable->GetScope();
8203af6ab5fSopenharmony_ci        auto const topLevelVariable =
8213af6ab5fSopenharmony_ci            variableScope != nullptr && (variableScope->IsGlobalScope() || (variableScope->Parent() != nullptr &&
8223af6ab5fSopenharmony_ci                                                                            variableScope->Parent()->IsGlobalScope()));
8233af6ab5fSopenharmony_ci        if (!topLevelVariable) {
8243af6ab5fSopenharmony_ci            if (checker->Relation()->IsIdenticalTo(leftType, smartType)) {
8253af6ab5fSopenharmony_ci                checker->Context().RemoveSmartCast(variable);
8263af6ab5fSopenharmony_ci            } else {
8273af6ab5fSopenharmony_ci                expr->Left()->SetTsType(smartType);
8283af6ab5fSopenharmony_ci                checker->Context().SetSmartCast(variable, smartType);
8293af6ab5fSopenharmony_ci            }
8303af6ab5fSopenharmony_ci        }
8313af6ab5fSopenharmony_ci    }
8323af6ab5fSopenharmony_ci    return smartType;
8333af6ab5fSopenharmony_ci}
8343af6ab5fSopenharmony_ci
8353af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::AssignmentExpression *const expr) const
8363af6ab5fSopenharmony_ci{
8373af6ab5fSopenharmony_ci    if (expr->TsTypeOrError() != nullptr) {
8383af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
8393af6ab5fSopenharmony_ci    }
8403af6ab5fSopenharmony_ci
8413af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
8423af6ab5fSopenharmony_ci    auto *const leftType = expr->Left()->Check(checker);
8433af6ab5fSopenharmony_ci
8443af6ab5fSopenharmony_ci    if (IsInvalidArrayLengthAssignment(expr, checker)) {
8453af6ab5fSopenharmony_ci        expr->SetTsType(checker->GlobalTypeError());
8463af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
8473af6ab5fSopenharmony_ci    }
8483af6ab5fSopenharmony_ci
8493af6ab5fSopenharmony_ci    if (expr->Left()->IsIdentifier()) {
8503af6ab5fSopenharmony_ci        expr->target_ = expr->Left()->AsIdentifier()->Variable();
8513af6ab5fSopenharmony_ci    } else if (expr->Left()->IsMemberExpression()) {
8523af6ab5fSopenharmony_ci        expr->target_ = expr->Left()->AsMemberExpression()->PropVar();
8533af6ab5fSopenharmony_ci    } else {
8543af6ab5fSopenharmony_ci        checker->LogTypeError("Invalid left-hand side of assignment expression", expr->Left()->Start());
8553af6ab5fSopenharmony_ci        expr->SetTsType(checker->GlobalTypeError());
8563af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
8573af6ab5fSopenharmony_ci    }
8583af6ab5fSopenharmony_ci
8593af6ab5fSopenharmony_ci    if (expr->target_ != nullptr && !expr->IsIgnoreConstAssign()) {
8603af6ab5fSopenharmony_ci        checker->ValidateUnaryOperatorOperand(expr->target_);
8613af6ab5fSopenharmony_ci    }
8623af6ab5fSopenharmony_ci
8633af6ab5fSopenharmony_ci    auto [rightType, relationNode] = CheckAssignmentExprOperatorType(expr, leftType);
8643af6ab5fSopenharmony_ci    if (rightType == nullptr) {
8653af6ab5fSopenharmony_ci        expr->SetTsType(checker->GlobalTypeError());
8663af6ab5fSopenharmony_ci        return checker->GlobalTypeError();
8673af6ab5fSopenharmony_ci    }
8683af6ab5fSopenharmony_ci
8693af6ab5fSopenharmony_ci    const checker::Type *targetType = checker->TryGettingFunctionTypeFromInvokeFunction(leftType);
8703af6ab5fSopenharmony_ci    const checker::Type *sourceType = checker->TryGettingFunctionTypeFromInvokeFunction(rightType);
8713af6ab5fSopenharmony_ci
8723af6ab5fSopenharmony_ci    checker::AssignmentContext(checker->Relation(), relationNode, rightType, leftType, expr->Right()->Start(),
8733af6ab5fSopenharmony_ci                               {"Type '", sourceType, "' cannot be assigned to type '", targetType, "'"});
8743af6ab5fSopenharmony_ci
8753af6ab5fSopenharmony_ci    checker::Type *smartType = GetSmartType(expr, leftType, rightType);
8763af6ab5fSopenharmony_ci
8773af6ab5fSopenharmony_ci    expr->SetTsType(smartType);
8783af6ab5fSopenharmony_ci    return expr->TsTypeOrError();
8793af6ab5fSopenharmony_ci}
8803af6ab5fSopenharmony_ci
8813af6ab5fSopenharmony_cistd::tuple<Type *, ir::Expression *> ETSAnalyzer::CheckAssignmentExprOperatorType(ir::AssignmentExpression *expr,
8823af6ab5fSopenharmony_ci                                                                                  Type *const leftType) const
8833af6ab5fSopenharmony_ci{
8843af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
8853af6ab5fSopenharmony_ci    checker::Type *sourceType {};
8863af6ab5fSopenharmony_ci    ir::Expression *relationNode = expr->Right();
8873af6ab5fSopenharmony_ci    switch (expr->OperatorType()) {
8883af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_MULTIPLY_EQUAL:
8893af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_EXPONENTIATION_EQUAL:
8903af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL:
8913af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_MOD_EQUAL:
8923af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_MINUS_EQUAL:
8933af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL:
8943af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL:
8953af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL:
8963af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_BITWISE_AND_EQUAL:
8973af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL:
8983af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_BITWISE_OR_EQUAL:
8993af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_PLUS_EQUAL: {
9003af6ab5fSopenharmony_ci            std::tie(std::ignore, expr->operationType_) = checker->CheckBinaryOperator(
9013af6ab5fSopenharmony_ci                expr->Left(), expr->Right(), expr, expr->OperatorType(), expr->Start(), true);
9023af6ab5fSopenharmony_ci
9033af6ab5fSopenharmony_ci            auto unboxedLeft = checker->ETSBuiltinTypeAsPrimitiveType(leftType);
9043af6ab5fSopenharmony_ci            sourceType = unboxedLeft == nullptr ? leftType : unboxedLeft;
9053af6ab5fSopenharmony_ci
9063af6ab5fSopenharmony_ci            relationNode = expr;
9073af6ab5fSopenharmony_ci            break;
9083af6ab5fSopenharmony_ci        }
9093af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_SUBSTITUTION: {
9103af6ab5fSopenharmony_ci            if (leftType->IsETSArrayType() && expr->Right()->IsArrayExpression()) {
9113af6ab5fSopenharmony_ci                checker->ModifyPreferredType(expr->Right()->AsArrayExpression(), leftType);
9123af6ab5fSopenharmony_ci            }
9133af6ab5fSopenharmony_ci
9143af6ab5fSopenharmony_ci            if (expr->Right()->IsObjectExpression()) {
9153af6ab5fSopenharmony_ci                expr->Right()->AsObjectExpression()->SetPreferredType(leftType);
9163af6ab5fSopenharmony_ci            }
9173af6ab5fSopenharmony_ci
9183af6ab5fSopenharmony_ci            sourceType = expr->Right()->Check(checker);
9193af6ab5fSopenharmony_ci            break;
9203af6ab5fSopenharmony_ci        }
9213af6ab5fSopenharmony_ci        default: {
9223af6ab5fSopenharmony_ci            UNREACHABLE();
9233af6ab5fSopenharmony_ci            break;
9243af6ab5fSopenharmony_ci        }
9253af6ab5fSopenharmony_ci    }
9263af6ab5fSopenharmony_ci
9273af6ab5fSopenharmony_ci    return {sourceType, relationNode};
9283af6ab5fSopenharmony_ci}
9293af6ab5fSopenharmony_ci
9303af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::AwaitExpression *expr) const
9313af6ab5fSopenharmony_ci{
9323af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
9333af6ab5fSopenharmony_ci    if (expr->TsTypeOrError() != nullptr) {
9343af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
9353af6ab5fSopenharmony_ci    }
9363af6ab5fSopenharmony_ci
9373af6ab5fSopenharmony_ci    checker::Type *argType = checker->GetApparentType(expr->argument_->Check(checker));
9383af6ab5fSopenharmony_ci    // Check the argument type of await expression
9393af6ab5fSopenharmony_ci    if (!argType->IsETSObjectType() ||
9403af6ab5fSopenharmony_ci        (argType->AsETSObjectType()->GetOriginalBaseType() != checker->GlobalBuiltinPromiseType())) {
9413af6ab5fSopenharmony_ci        checker->LogTypeError("'await' expressions require Promise object as argument.", expr->Argument()->Start());
9423af6ab5fSopenharmony_ci        expr->SetTsType(checker->GlobalTypeError());
9433af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
9443af6ab5fSopenharmony_ci    }
9453af6ab5fSopenharmony_ci
9463af6ab5fSopenharmony_ci    Type *type = argType->AsETSObjectType()->TypeArguments().at(0);
9473af6ab5fSopenharmony_ci    expr->SetTsType(UnwrapPromiseType(type));
9483af6ab5fSopenharmony_ci    return expr->TsType();
9493af6ab5fSopenharmony_ci}
9503af6ab5fSopenharmony_ci
9513af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::UnwrapPromiseType(checker::Type *type) const
9523af6ab5fSopenharmony_ci{
9533af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
9543af6ab5fSopenharmony_ci    checker::Type *promiseType = checker->GlobalBuiltinPromiseType();
9553af6ab5fSopenharmony_ci    while (type->IsETSObjectType() && type->AsETSObjectType()->GetOriginalBaseType() == promiseType) {
9563af6ab5fSopenharmony_ci        type = type->AsETSObjectType()->TypeArguments().at(0);
9573af6ab5fSopenharmony_ci    }
9583af6ab5fSopenharmony_ci    if (!type->IsETSUnionType()) {
9593af6ab5fSopenharmony_ci        return type;
9603af6ab5fSopenharmony_ci    }
9613af6ab5fSopenharmony_ci    const auto &ctypes = type->AsETSUnionType()->ConstituentTypes();
9623af6ab5fSopenharmony_ci    auto it = std::find_if(ctypes.begin(), ctypes.end(), [promiseType](checker::Type *t) {
9633af6ab5fSopenharmony_ci        return t == promiseType || (t->IsETSObjectType() && t->AsETSObjectType()->GetBaseType() == promiseType);
9643af6ab5fSopenharmony_ci    });
9653af6ab5fSopenharmony_ci    if (it == ctypes.end()) {
9663af6ab5fSopenharmony_ci        return type;
9673af6ab5fSopenharmony_ci    }
9683af6ab5fSopenharmony_ci    ArenaVector<Type *> newCTypes(ctypes);
9693af6ab5fSopenharmony_ci    do {
9703af6ab5fSopenharmony_ci        size_t index = it - ctypes.begin();
9713af6ab5fSopenharmony_ci        newCTypes[index] = UnwrapPromiseType(ctypes[index]);
9723af6ab5fSopenharmony_ci        ++it;
9733af6ab5fSopenharmony_ci        it = std::find_if(it, ctypes.end(), [promiseType](checker::Type *t) {
9743af6ab5fSopenharmony_ci            return t == promiseType || t->AsETSObjectType()->GetBaseType() == promiseType;
9753af6ab5fSopenharmony_ci        });
9763af6ab5fSopenharmony_ci    } while (it != ctypes.end());
9773af6ab5fSopenharmony_ci    return checker->CreateETSUnionType(std::move(newCTypes));
9783af6ab5fSopenharmony_ci}
9793af6ab5fSopenharmony_ci
9803af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::BinaryExpression *expr) const
9813af6ab5fSopenharmony_ci{
9823af6ab5fSopenharmony_ci    if (expr->TsTypeOrError() != nullptr) {
9833af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
9843af6ab5fSopenharmony_ci    }
9853af6ab5fSopenharmony_ci
9863af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
9873af6ab5fSopenharmony_ci    checker::Type *newTsType {nullptr};
9883af6ab5fSopenharmony_ci    std::tie(newTsType, expr->operationType_) =
9893af6ab5fSopenharmony_ci        checker->CheckBinaryOperator(expr->Left(), expr->Right(), expr, expr->OperatorType(), expr->Start());
9903af6ab5fSopenharmony_ci    expr->SetTsType(newTsType);
9913af6ab5fSopenharmony_ci
9923af6ab5fSopenharmony_ci    checker->Context().CheckBinarySmartCastCondition(expr);
9933af6ab5fSopenharmony_ci
9943af6ab5fSopenharmony_ci    return expr->TsTypeOrError();
9953af6ab5fSopenharmony_ci}
9963af6ab5fSopenharmony_ci
9973af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::BlockExpression *st) const
9983af6ab5fSopenharmony_ci{
9993af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
10003af6ab5fSopenharmony_ci    checker::ScopeContext scopeCtx(checker, st->Scope());
10013af6ab5fSopenharmony_ci
10023af6ab5fSopenharmony_ci    if (st->TsTypeOrError() == nullptr) {
10033af6ab5fSopenharmony_ci        // NOLINTNEXTLINE(modernize-loop-convert)
10043af6ab5fSopenharmony_ci        for (std::size_t idx = 0; idx < st->Statements().size(); idx++) {
10053af6ab5fSopenharmony_ci            st->Statements()[idx]->Check(checker);
10063af6ab5fSopenharmony_ci        }
10073af6ab5fSopenharmony_ci
10083af6ab5fSopenharmony_ci        auto lastStmt = st->Statements().back();
10093af6ab5fSopenharmony_ci        ASSERT(lastStmt->IsExpressionStatement());
10103af6ab5fSopenharmony_ci        st->SetTsType(lastStmt->AsExpressionStatement()->GetExpression()->TsType());
10113af6ab5fSopenharmony_ci    }
10123af6ab5fSopenharmony_ci
10133af6ab5fSopenharmony_ci    return st->TsTypeOrError();
10143af6ab5fSopenharmony_ci}
10153af6ab5fSopenharmony_ci
10163af6ab5fSopenharmony_cichecker::Signature *ETSAnalyzer::ResolveSignature(ETSChecker *checker, ir::CallExpression *expr,
10173af6ab5fSopenharmony_ci                                                  checker::Type *calleeType, bool isFunctionalInterface,
10183af6ab5fSopenharmony_ci                                                  bool isUnionTypeWithFunctionalInterface) const
10193af6ab5fSopenharmony_ci{
10203af6ab5fSopenharmony_ci    bool extensionFunctionType = expr->Callee()->IsMemberExpression() && checker->ExtensionETSFunctionType(calleeType);
10213af6ab5fSopenharmony_ci
10223af6ab5fSopenharmony_ci    if (calleeType->IsETSExtensionFuncHelperType()) {
10233af6ab5fSopenharmony_ci        return ResolveCallForETSExtensionFuncHelperType(calleeType->AsETSExtensionFuncHelperType(), checker, expr);
10243af6ab5fSopenharmony_ci    }
10253af6ab5fSopenharmony_ci    if (extensionFunctionType) {
10263af6ab5fSopenharmony_ci        return ResolveCallExtensionFunction(calleeType->AsETSFunctionType(), checker, expr);
10273af6ab5fSopenharmony_ci    }
10283af6ab5fSopenharmony_ci    auto &signatures = ChooseSignatures(checker, calleeType, expr->IsETSConstructorCall(), isFunctionalInterface,
10293af6ab5fSopenharmony_ci                                        isUnionTypeWithFunctionalInterface);
10303af6ab5fSopenharmony_ci    // Remove static signatures if the callee is a member expression and the object is initialized
10313af6ab5fSopenharmony_ci    if (expr->Callee()->IsMemberExpression() &&
10323af6ab5fSopenharmony_ci        !expr->Callee()->AsMemberExpression()->Object()->TsType()->IsETSEnumType() &&
10333af6ab5fSopenharmony_ci        (expr->Callee()->AsMemberExpression()->Object()->IsSuperExpression() ||
10343af6ab5fSopenharmony_ci         (expr->Callee()->AsMemberExpression()->Object()->IsIdentifier() &&
10353af6ab5fSopenharmony_ci          expr->Callee()->AsMemberExpression()->Object()->AsIdentifier()->Variable()->HasFlag(
10363af6ab5fSopenharmony_ci              varbinder::VariableFlags::INITIALIZED)))) {
10373af6ab5fSopenharmony_ci        signatures.erase(
10383af6ab5fSopenharmony_ci            std::remove_if(signatures.begin(), signatures.end(),
10393af6ab5fSopenharmony_ci                           [](checker::Signature *signature) { return signature->Function()->IsStatic(); }),
10403af6ab5fSopenharmony_ci            signatures.end());
10413af6ab5fSopenharmony_ci    }
10423af6ab5fSopenharmony_ci
10433af6ab5fSopenharmony_ci    checker::Signature *signature = checker->ResolveCallExpressionAndTrailingLambda(signatures, expr, expr->Start());
10443af6ab5fSopenharmony_ci    if (signature == nullptr) {
10453af6ab5fSopenharmony_ci        return nullptr;
10463af6ab5fSopenharmony_ci    }
10473af6ab5fSopenharmony_ci
10483af6ab5fSopenharmony_ci    if (signature->Function()->IsExtensionMethod()) {
10493af6ab5fSopenharmony_ci        checker->LogTypeError({"No matching call signature"}, expr->Start());
10503af6ab5fSopenharmony_ci        return nullptr;
10513af6ab5fSopenharmony_ci    }
10523af6ab5fSopenharmony_ci    return signature;
10533af6ab5fSopenharmony_ci}
10543af6ab5fSopenharmony_ci
10553af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::GetReturnType(ir::CallExpression *expr, checker::Type *calleeType) const
10563af6ab5fSopenharmony_ci{
10573af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
10583af6ab5fSopenharmony_ci
10593af6ab5fSopenharmony_ci    if (calleeType->IsTypeError()) {
10603af6ab5fSopenharmony_ci        return checker->GlobalTypeError();
10613af6ab5fSopenharmony_ci    }
10623af6ab5fSopenharmony_ci
10633af6ab5fSopenharmony_ci    bool isConstructorCall = expr->IsETSConstructorCall();
10643af6ab5fSopenharmony_ci    bool isUnionTypeWithFunctionalInterface =
10653af6ab5fSopenharmony_ci        calleeType->IsETSUnionType() &&
10663af6ab5fSopenharmony_ci        calleeType->AsETSUnionType()->HasObjectType(checker::ETSObjectFlags::FUNCTIONAL_INTERFACE);
10673af6ab5fSopenharmony_ci    bool isFunctionalInterface = calleeType->IsETSObjectType() && calleeType->AsETSObjectType()->HasObjectFlag(
10683af6ab5fSopenharmony_ci                                                                      checker::ETSObjectFlags::FUNCTIONAL_INTERFACE);
10693af6ab5fSopenharmony_ci    bool etsExtensionFuncHelperType = calleeType->IsETSExtensionFuncHelperType();
10703af6ab5fSopenharmony_ci
10713af6ab5fSopenharmony_ci    if (expr->Callee()->IsArrowFunctionExpression()) {
10723af6ab5fSopenharmony_ci        calleeType = InitAnonymousLambdaCallee(checker, expr->Callee(), calleeType);
10733af6ab5fSopenharmony_ci        isFunctionalInterface = true;
10743af6ab5fSopenharmony_ci    }
10753af6ab5fSopenharmony_ci
10763af6ab5fSopenharmony_ci    if (!isFunctionalInterface && !calleeType->IsETSFunctionType() && !isConstructorCall &&
10773af6ab5fSopenharmony_ci        !etsExtensionFuncHelperType && !isUnionTypeWithFunctionalInterface) {
10783af6ab5fSopenharmony_ci        checker->LogTypeError({"Type '", calleeType, "' has no call signatures."}, expr->Start());
10793af6ab5fSopenharmony_ci        return checker->GlobalTypeError();
10803af6ab5fSopenharmony_ci    }
10813af6ab5fSopenharmony_ci
10823af6ab5fSopenharmony_ci    checker::Signature *signature =
10833af6ab5fSopenharmony_ci        ResolveSignature(checker, expr, calleeType, isFunctionalInterface, isUnionTypeWithFunctionalInterface);
10843af6ab5fSopenharmony_ci    if (signature == nullptr) {
10853af6ab5fSopenharmony_ci        return checker->GlobalTypeError();
10863af6ab5fSopenharmony_ci    }
10873af6ab5fSopenharmony_ci
10883af6ab5fSopenharmony_ci    checker->CheckObjectLiteralArguments(signature, expr->Arguments());
10893af6ab5fSopenharmony_ci
10903af6ab5fSopenharmony_ci    if (!isFunctionalInterface) {
10913af6ab5fSopenharmony_ci        checker::ETSObjectType *calleeObj = ChooseCalleeObj(checker, expr, calleeType, isConstructorCall);
10923af6ab5fSopenharmony_ci        checker->ValidateSignatureAccessibility(calleeObj, expr, signature, expr->Start());
10933af6ab5fSopenharmony_ci    }
10943af6ab5fSopenharmony_ci
10953af6ab5fSopenharmony_ci    ASSERT(signature->Function() != nullptr);
10963af6ab5fSopenharmony_ci    if (signature->Function()->IsThrowing() || signature->Function()->IsRethrowing()) {
10973af6ab5fSopenharmony_ci        checker->CheckThrowingStatements(expr);
10983af6ab5fSopenharmony_ci    }
10993af6ab5fSopenharmony_ci
11003af6ab5fSopenharmony_ci    if (signature->Function()->IsDynamic()) {
11013af6ab5fSopenharmony_ci        ASSERT(signature->Function()->IsDynamic());
11023af6ab5fSopenharmony_ci        auto lang = signature->Function()->Language();
11033af6ab5fSopenharmony_ci        expr->SetSignature(checker->ResolveDynamicCallExpression(expr->Callee(), signature->Params(), lang, false));
11043af6ab5fSopenharmony_ci    } else {
11053af6ab5fSopenharmony_ci        ASSERT(!signature->Function()->IsDynamic());
11063af6ab5fSopenharmony_ci        expr->SetSignature(signature);
11073af6ab5fSopenharmony_ci    }
11083af6ab5fSopenharmony_ci
11093af6ab5fSopenharmony_ci    auto *returnType = signature->ReturnType();
11103af6ab5fSopenharmony_ci
11113af6ab5fSopenharmony_ci    if (signature->HasSignatureFlag(SignatureFlags::THIS_RETURN_TYPE)) {
11123af6ab5fSopenharmony_ci        returnType = ChooseCalleeObj(checker, expr, calleeType, isConstructorCall);
11133af6ab5fSopenharmony_ci    }
11143af6ab5fSopenharmony_ci
11153af6ab5fSopenharmony_ci    return returnType;
11163af6ab5fSopenharmony_ci}
11173af6ab5fSopenharmony_ci
11183af6ab5fSopenharmony_cistatic void CheckAbstractCall(ETSChecker *checker, ir::CallExpression *expr)
11193af6ab5fSopenharmony_ci{
11203af6ab5fSopenharmony_ci    if (expr->Callee()->IsMemberExpression()) {
11213af6ab5fSopenharmony_ci        auto obj = expr->Callee()->AsMemberExpression()->Object();
11223af6ab5fSopenharmony_ci        if (obj != nullptr && obj->IsSuperExpression()) {
11233af6ab5fSopenharmony_ci            if ((expr->Signature() != nullptr) && (expr->Signature()->HasSignatureFlag(SignatureFlags::ABSTRACT))) {
11243af6ab5fSopenharmony_ci                checker->LogTypeError("Cannot call abstract method!", expr->Start());
11253af6ab5fSopenharmony_ci                expr->SetTsType(checker->GlobalTypeError());
11263af6ab5fSopenharmony_ci            }
11273af6ab5fSopenharmony_ci        }
11283af6ab5fSopenharmony_ci    }
11293af6ab5fSopenharmony_ci}
11303af6ab5fSopenharmony_ci
11313af6ab5fSopenharmony_cistatic void CheckCallee(ETSChecker *checker, ir::CallExpression *expr)
11323af6ab5fSopenharmony_ci{
11333af6ab5fSopenharmony_ci    checker->CheckNonNullish(expr->Callee());
11343af6ab5fSopenharmony_ci    if (expr->Callee()->IsMemberExpression() && expr->Callee()->AsMemberExpression()->Object() != nullptr &&
11353af6ab5fSopenharmony_ci        expr->Callee()->AsMemberExpression()->Object()->TsType()->IsETSObjectType() &&
11363af6ab5fSopenharmony_ci        expr->Callee()->AsMemberExpression()->Object()->TsType()->AsETSObjectType()->HasObjectFlag(
11373af6ab5fSopenharmony_ci            ETSObjectFlags::READONLY)) {
11383af6ab5fSopenharmony_ci        checker->LogTypeError("Cannot call readonly type methods.", expr->Start());
11393af6ab5fSopenharmony_ci        expr->SetTsType(checker->GlobalTypeError());
11403af6ab5fSopenharmony_ci    }
11413af6ab5fSopenharmony_ci}
11423af6ab5fSopenharmony_ci
11433af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::GetCallExpressionReturnType(ir::CallExpression *expr, checker::Type *calleeType) const
11443af6ab5fSopenharmony_ci{
11453af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
11463af6ab5fSopenharmony_ci    checker::Type *returnType = nullptr;
11473af6ab5fSopenharmony_ci    if (calleeType->IsETSDynamicType() && !calleeType->AsETSDynamicType()->HasDecl()) {
11483af6ab5fSopenharmony_ci        // Trailing lambda for js function call is not supported, check the correctness of `foo() {}`
11493af6ab5fSopenharmony_ci        checker->EnsureValidCurlyBrace(expr);
11503af6ab5fSopenharmony_ci        auto lang = calleeType->AsETSDynamicType()->Language();
11513af6ab5fSopenharmony_ci        expr->SetSignature(checker->ResolveDynamicCallExpression(expr->Callee(), expr->Arguments(), lang, false));
11523af6ab5fSopenharmony_ci        returnType = expr->Signature()->ReturnType();
11533af6ab5fSopenharmony_ci    } else {
11543af6ab5fSopenharmony_ci        returnType = GetReturnType(expr, calleeType);
11553af6ab5fSopenharmony_ci    }
11563af6ab5fSopenharmony_ci
11573af6ab5fSopenharmony_ci    if (returnType->IsTypeError()) {
11583af6ab5fSopenharmony_ci        return checker->GlobalTypeError();
11593af6ab5fSopenharmony_ci    }
11603af6ab5fSopenharmony_ci
11613af6ab5fSopenharmony_ci    if (expr->Signature()->RestVar() != nullptr) {
11623af6ab5fSopenharmony_ci        auto *const elementType = expr->Signature()->RestVar()->TsType()->AsETSArrayType()->ElementType();
11633af6ab5fSopenharmony_ci        auto *const arrayType = checker->CreateETSArrayType(elementType)->AsETSArrayType();
11643af6ab5fSopenharmony_ci        checker->CreateBuiltinArraySignature(arrayType, arrayType->Rank());
11653af6ab5fSopenharmony_ci    }
11663af6ab5fSopenharmony_ci
11673af6ab5fSopenharmony_ci    if (expr->Signature()->HasSignatureFlag(checker::SignatureFlags::NEED_RETURN_TYPE)) {
11683af6ab5fSopenharmony_ci        checker::SavedCheckerContext savedCtx(checker, checker->Context().Status(), expr->Signature()->Owner());
11693af6ab5fSopenharmony_ci        expr->Signature()->OwnerVar()->Declaration()->Node()->Check(checker);
11703af6ab5fSopenharmony_ci        if (expr->Signature()->HasSignatureFlag(checker::SignatureFlags::NEED_RETURN_TYPE) &&
11713af6ab5fSopenharmony_ci            expr->Signature()->Function()->HasBody()) {
11723af6ab5fSopenharmony_ci            checker::ScopeContext scopeCtx(checker, expr->Signature()->Function()->Body()->Scope());
11733af6ab5fSopenharmony_ci            checker->CollectReturnStatements(expr->Signature()->Function());
11743af6ab5fSopenharmony_ci        }
11753af6ab5fSopenharmony_ci        returnType = expr->Signature()->ReturnType();
11763af6ab5fSopenharmony_ci        // NOTE(vpukhov): #14902 substituted signature is not updated
11773af6ab5fSopenharmony_ci    }
11783af6ab5fSopenharmony_ci
11793af6ab5fSopenharmony_ci    return returnType;
11803af6ab5fSopenharmony_ci}
11813af6ab5fSopenharmony_ci
11823af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::CallExpression *expr) const
11833af6ab5fSopenharmony_ci{
11843af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
11853af6ab5fSopenharmony_ci    if (expr->TsTypeOrError() != nullptr) {
11863af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
11873af6ab5fSopenharmony_ci    }
11883af6ab5fSopenharmony_ci    ASSERT(!expr->IsOptional());
11893af6ab5fSopenharmony_ci
11903af6ab5fSopenharmony_ci    auto *oldCallee = expr->Callee();
11913af6ab5fSopenharmony_ci    checker::Type *calleeType = checker->GetApparentType(expr->Callee()->Check(checker));
11923af6ab5fSopenharmony_ci    if (calleeType->IsTypeError()) {
11933af6ab5fSopenharmony_ci        expr->SetTsType(checker->GlobalTypeError());
11943af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
11953af6ab5fSopenharmony_ci    }
11963af6ab5fSopenharmony_ci
11973af6ab5fSopenharmony_ci    if (expr->Callee() != oldCallee) {
11983af6ab5fSopenharmony_ci        // If it is a static invoke, the callee will be transformed from an identifier to a member expression
11993af6ab5fSopenharmony_ci        // Type check the callee again for member expression
12003af6ab5fSopenharmony_ci        calleeType = checker->GetApparentType(expr->Callee()->Check(checker));
12013af6ab5fSopenharmony_ci    }
12023af6ab5fSopenharmony_ci
12033af6ab5fSopenharmony_ci    CheckCallee(checker, expr);
12043af6ab5fSopenharmony_ci
12053af6ab5fSopenharmony_ci    checker::Type *returnType = GetCallExpressionReturnType(expr, calleeType);
12063af6ab5fSopenharmony_ci    if (returnType->IsTypeError()) {
12073af6ab5fSopenharmony_ci        expr->SetTsType(returnType);
12083af6ab5fSopenharmony_ci        return returnType;
12093af6ab5fSopenharmony_ci    }
12103af6ab5fSopenharmony_ci
12113af6ab5fSopenharmony_ci    expr->SetTsType(returnType);
12123af6ab5fSopenharmony_ci    expr->SetUncheckedType(checker->GuaranteedTypeForUncheckedCallReturn(expr->Signature()));
12133af6ab5fSopenharmony_ci    if (expr->UncheckedType() != nullptr) {
12143af6ab5fSopenharmony_ci        checker->ComputeApparentType(returnType);
12153af6ab5fSopenharmony_ci    }
12163af6ab5fSopenharmony_ci
12173af6ab5fSopenharmony_ci    if (returnType->IsTypeError()) {
12183af6ab5fSopenharmony_ci        expr->SetTsType(returnType);
12193af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
12203af6ab5fSopenharmony_ci    }
12213af6ab5fSopenharmony_ci
12223af6ab5fSopenharmony_ci    CheckVoidTypeExpression(checker, expr);
12233af6ab5fSopenharmony_ci    CheckAbstractCall(checker, expr);
12243af6ab5fSopenharmony_ci    return expr->TsTypeOrError();
12253af6ab5fSopenharmony_ci}
12263af6ab5fSopenharmony_ci
12273af6ab5fSopenharmony_cistatic void HandleTestedTypes(SmartCastTypes testedTypes, ETSChecker *checker)
12283af6ab5fSopenharmony_ci{
12293af6ab5fSopenharmony_ci    if (testedTypes.has_value()) {
12303af6ab5fSopenharmony_ci        for (auto [variable, consequentType, _] : *testedTypes) {
12313af6ab5fSopenharmony_ci            checker->ApplySmartCast(variable, consequentType);
12323af6ab5fSopenharmony_ci        }
12333af6ab5fSopenharmony_ci    }
12343af6ab5fSopenharmony_ci}
12353af6ab5fSopenharmony_ci
12363af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ConditionalExpression *expr) const
12373af6ab5fSopenharmony_ci{
12383af6ab5fSopenharmony_ci    if (expr->TsTypeOrError() != nullptr) {
12393af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
12403af6ab5fSopenharmony_ci    }
12413af6ab5fSopenharmony_ci
12423af6ab5fSopenharmony_ci    ETSChecker *const checker = GetETSChecker();
12433af6ab5fSopenharmony_ci
12443af6ab5fSopenharmony_ci    SmartCastArray smartCasts = checker->Context().EnterTestExpression();
12453af6ab5fSopenharmony_ci    checker->CheckTruthinessOfType(expr->Test());
12463af6ab5fSopenharmony_ci    SmartCastTypes testedTypes = checker->Context().ExitTestExpression();
12473af6ab5fSopenharmony_ci    HandleTestedTypes(testedTypes, checker);
12483af6ab5fSopenharmony_ci
12493af6ab5fSopenharmony_ci    auto *consequent = expr->Consequent();
12503af6ab5fSopenharmony_ci    auto *consequentType = consequent->Check(checker);
12513af6ab5fSopenharmony_ci
12523af6ab5fSopenharmony_ci    if (consequentType->IsETSEnumType()) {
12533af6ab5fSopenharmony_ci        consequent->SetBoxingUnboxingFlags(ir::BoxingUnboxingFlags::BOX_TO_ENUM);
12543af6ab5fSopenharmony_ci        consequentType = consequentType->AsETSEnumType()->GetDecl()->BoxedClass()->TsType();
12553af6ab5fSopenharmony_ci    }
12563af6ab5fSopenharmony_ci    SmartCastArray consequentSmartCasts = checker->Context().CloneSmartCasts();
12573af6ab5fSopenharmony_ci    checker->Context().RestoreSmartCasts(smartCasts);
12583af6ab5fSopenharmony_ci
12593af6ab5fSopenharmony_ci    if (testedTypes.has_value()) {
12603af6ab5fSopenharmony_ci        for (auto [variable, _, alternateType] : *testedTypes) {
12613af6ab5fSopenharmony_ci            checker->ApplySmartCast(variable, alternateType);
12623af6ab5fSopenharmony_ci        }
12633af6ab5fSopenharmony_ci    }
12643af6ab5fSopenharmony_ci
12653af6ab5fSopenharmony_ci    auto *alternate = expr->Alternate();
12663af6ab5fSopenharmony_ci    auto *alternateType = alternate->Check(checker);
12673af6ab5fSopenharmony_ci
12683af6ab5fSopenharmony_ci    if (alternateType->IsETSEnumType()) {
12693af6ab5fSopenharmony_ci        alternate->SetBoxingUnboxingFlags(ir::BoxingUnboxingFlags::BOX_TO_ENUM);
12703af6ab5fSopenharmony_ci        alternateType = alternateType->AsETSEnumType()->GetDecl()->BoxedClass()->TsType();
12713af6ab5fSopenharmony_ci    }
12723af6ab5fSopenharmony_ci
12733af6ab5fSopenharmony_ci    // Here we need to combine types from consequent and alternate if blocks.
12743af6ab5fSopenharmony_ci    checker->Context().CombineSmartCasts(consequentSmartCasts);
12753af6ab5fSopenharmony_ci
12763af6ab5fSopenharmony_ci    if (checker->IsTypeIdenticalTo(consequentType, alternateType)) {
12773af6ab5fSopenharmony_ci        expr->SetTsType(checker->GetNonConstantType(consequentType));
12783af6ab5fSopenharmony_ci    } else {
12793af6ab5fSopenharmony_ci        //  If possible and required update number literal type to the proper value (identical to left-side type)
12803af6ab5fSopenharmony_ci        if (alternate->IsNumberLiteral() &&
12813af6ab5fSopenharmony_ci            checker->AdjustNumberLiteralType(alternate->AsNumberLiteral(), alternateType, consequentType)) {
12823af6ab5fSopenharmony_ci            expr->SetTsType(consequentType);
12833af6ab5fSopenharmony_ci        } else if (consequent->IsNumberLiteral() &&
12843af6ab5fSopenharmony_ci                   checker->AdjustNumberLiteralType(consequent->AsNumberLiteral(), consequentType, alternateType)) {
12853af6ab5fSopenharmony_ci            expr->SetTsType(alternateType);
12863af6ab5fSopenharmony_ci        } else {
12873af6ab5fSopenharmony_ci            expr->SetTsType(checker->CreateETSUnionType({consequentType, alternateType}));
12883af6ab5fSopenharmony_ci            if (expr->TsType()->IsETSReferenceType()) {
12893af6ab5fSopenharmony_ci                checker->MaybeBoxExpression(expr->Consequent());
12903af6ab5fSopenharmony_ci                checker->MaybeBoxExpression(expr->Alternate());
12913af6ab5fSopenharmony_ci            }
12923af6ab5fSopenharmony_ci        }
12933af6ab5fSopenharmony_ci    }
12943af6ab5fSopenharmony_ci
12953af6ab5fSopenharmony_ci    return expr->TsType();
12963af6ab5fSopenharmony_ci}
12973af6ab5fSopenharmony_ci
12983af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::Identifier *expr) const
12993af6ab5fSopenharmony_ci{
13003af6ab5fSopenharmony_ci    if (expr->TsTypeOrError() == nullptr) {
13013af6ab5fSopenharmony_ci        ETSChecker *checker = GetETSChecker();
13023af6ab5fSopenharmony_ci
13033af6ab5fSopenharmony_ci        auto *identType = checker->ResolveIdentifier(expr);
13043af6ab5fSopenharmony_ci        if (expr->Variable() != nullptr && (expr->Parent() == nullptr || !expr->Parent()->IsAssignmentExpression() ||
13053af6ab5fSopenharmony_ci                                            expr != expr->Parent()->AsAssignmentExpression()->Left())) {
13063af6ab5fSopenharmony_ci            if (auto *const smartType = checker->Context().GetSmartCast(expr->Variable()); smartType != nullptr) {
13073af6ab5fSopenharmony_ci                identType = smartType;
13083af6ab5fSopenharmony_ci            }
13093af6ab5fSopenharmony_ci        }
13103af6ab5fSopenharmony_ci        expr->SetTsType(identType);
13113af6ab5fSopenharmony_ci
13123af6ab5fSopenharmony_ci        checker->Context().CheckIdentifierSmartCastCondition(expr);
13133af6ab5fSopenharmony_ci    }
13143af6ab5fSopenharmony_ci    return expr->TsTypeOrError();
13153af6ab5fSopenharmony_ci}
13163af6ab5fSopenharmony_ci
13173af6ab5fSopenharmony_cistd::pair<checker::Type *, util::StringView> SearchReExportsType(ETSObjectType *baseType, ir::MemberExpression *expr,
13183af6ab5fSopenharmony_ci                                                                 util::StringView &aliasName, ETSChecker *checker)
13193af6ab5fSopenharmony_ci{
13203af6ab5fSopenharmony_ci    std::pair<ETSObjectType *, util::StringView> ret {};
13213af6ab5fSopenharmony_ci
13223af6ab5fSopenharmony_ci    for (auto *const item : baseType->ReExports()) {
13233af6ab5fSopenharmony_ci        auto name = item->GetReExportAliasValue(aliasName);
13243af6ab5fSopenharmony_ci        if (name == aliasName && item->IsReExportHaveAliasValue(name)) {
13253af6ab5fSopenharmony_ci            break;
13263af6ab5fSopenharmony_ci        }
13273af6ab5fSopenharmony_ci
13283af6ab5fSopenharmony_ci        if (item->GetProperty(name, PropertySearchFlags::SEARCH_ALL) != nullptr) {
13293af6ab5fSopenharmony_ci            if (ret.first != nullptr) {
13303af6ab5fSopenharmony_ci                checker->LogTypeError({"Ambiguous reference to '", aliasName, "'"}, expr->Start());
13313af6ab5fSopenharmony_ci                expr->SetTsType(checker->GlobalTypeError());
13323af6ab5fSopenharmony_ci                return ret;
13333af6ab5fSopenharmony_ci            }
13343af6ab5fSopenharmony_ci            ret = {item, name};
13353af6ab5fSopenharmony_ci        }
13363af6ab5fSopenharmony_ci
13373af6ab5fSopenharmony_ci        if (auto reExportType = SearchReExportsType(item, expr, name, checker); reExportType.first != nullptr) {
13383af6ab5fSopenharmony_ci            return reExportType;
13393af6ab5fSopenharmony_ci        }
13403af6ab5fSopenharmony_ci    }
13413af6ab5fSopenharmony_ci
13423af6ab5fSopenharmony_ci    return ret;
13433af6ab5fSopenharmony_ci}
13443af6ab5fSopenharmony_ci
13453af6ab5fSopenharmony_cistatic void TypeErrorOnMissingProperty(ir::MemberExpression *expr, checker::Type *baseType,
13463af6ab5fSopenharmony_ci                                       checker::ETSChecker *checker)
13473af6ab5fSopenharmony_ci{
13483af6ab5fSopenharmony_ci    checker->LogTypeError(
13493af6ab5fSopenharmony_ci        {"Property '", expr->Property()->AsIdentifier()->Name(), "' does not exist on type '", baseType, "'"},
13503af6ab5fSopenharmony_ci        expr->Object()->Start());
13513af6ab5fSopenharmony_ci    expr->SetTsType(checker->GlobalTypeError());
13523af6ab5fSopenharmony_ci}
13533af6ab5fSopenharmony_ci
13543af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::MemberExpression *expr) const
13553af6ab5fSopenharmony_ci{
13563af6ab5fSopenharmony_ci    if (expr->TsTypeOrError() != nullptr) {
13573af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
13583af6ab5fSopenharmony_ci    }
13593af6ab5fSopenharmony_ci    ASSERT(!expr->IsOptional());
13603af6ab5fSopenharmony_ci
13613af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
13623af6ab5fSopenharmony_ci    auto *baseType = checker->GetNonConstantType(checker->GetApparentType(expr->Object()->Check(checker)));
13633af6ab5fSopenharmony_ci    //  Note: don't use possible smart cast to null-like types.
13643af6ab5fSopenharmony_ci    //        Such situation should be correctly resolved in the subsequent lowering.
13653af6ab5fSopenharmony_ci    if (baseType->DefinitelyETSNullish() && expr->Object()->IsIdentifier()) {
13663af6ab5fSopenharmony_ci        baseType = expr->Object()->AsIdentifier()->Variable()->TsType();
13673af6ab5fSopenharmony_ci    }
13683af6ab5fSopenharmony_ci
13693af6ab5fSopenharmony_ci    if (baseType->IsETSObjectType() && !baseType->AsETSObjectType()->ReExports().empty() &&
13703af6ab5fSopenharmony_ci        baseType->AsETSObjectType()->GetProperty(expr->Property()->AsIdentifier()->Name(),
13713af6ab5fSopenharmony_ci                                                 PropertySearchFlags::SEARCH_ALL) == nullptr) {
13723af6ab5fSopenharmony_ci        if (auto reExportType = SearchReExportsType(baseType->AsETSObjectType(), expr,
13733af6ab5fSopenharmony_ci                                                    expr->Property()->AsIdentifier()->Name(), checker);
13743af6ab5fSopenharmony_ci            reExportType.first != nullptr) {
13753af6ab5fSopenharmony_ci            baseType = reExportType.first;
13763af6ab5fSopenharmony_ci            expr->object_->AsIdentifier()->SetTsType(baseType);
13773af6ab5fSopenharmony_ci            expr->property_->AsIdentifier()->SetName(reExportType.second);
13783af6ab5fSopenharmony_ci        }
13793af6ab5fSopenharmony_ci    }
13803af6ab5fSopenharmony_ci
13813af6ab5fSopenharmony_ci    if (!checker->CheckNonNullish(expr->Object())) {
13823af6ab5fSopenharmony_ci        expr->SetTsType(checker->GlobalTypeError());
13833af6ab5fSopenharmony_ci        return expr->TsType();
13843af6ab5fSopenharmony_ci    }
13853af6ab5fSopenharmony_ci
13863af6ab5fSopenharmony_ci    if (expr->IsComputed()) {
13873af6ab5fSopenharmony_ci        return expr->AdjustType(checker, expr->CheckComputed(checker, baseType));
13883af6ab5fSopenharmony_ci    }
13893af6ab5fSopenharmony_ci
13903af6ab5fSopenharmony_ci    if (baseType->IsETSArrayType()) {
13913af6ab5fSopenharmony_ci        if (expr->Property()->AsIdentifier()->Name().Is("length")) {
13923af6ab5fSopenharmony_ci            return expr->AdjustType(checker, checker->GlobalIntType());
13933af6ab5fSopenharmony_ci        }
13943af6ab5fSopenharmony_ci
13953af6ab5fSopenharmony_ci        return expr->SetAndAdjustType(checker, checker->GlobalETSObjectType());
13963af6ab5fSopenharmony_ci    }
13973af6ab5fSopenharmony_ci
13983af6ab5fSopenharmony_ci    if (baseType->IsETSObjectType()) {
13993af6ab5fSopenharmony_ci        return expr->SetAndAdjustType(checker, baseType->AsETSObjectType());
14003af6ab5fSopenharmony_ci    }
14013af6ab5fSopenharmony_ci
14023af6ab5fSopenharmony_ci    if (baseType->IsETSEnumType()) {
14033af6ab5fSopenharmony_ci        auto [memberType, memberVar] = expr->ResolveEnumMember(checker, baseType);
14043af6ab5fSopenharmony_ci        expr->SetPropVar(memberVar);
14053af6ab5fSopenharmony_ci        expr->Property()->SetTsType(memberType == nullptr ? checker->GlobalTypeError() : memberType);
14063af6ab5fSopenharmony_ci        return expr->AdjustType(checker, expr->Property()->TsTypeOrError());
14073af6ab5fSopenharmony_ci    }
14083af6ab5fSopenharmony_ci
14093af6ab5fSopenharmony_ci    if (baseType->IsETSUnionType()) {
14103af6ab5fSopenharmony_ci        return expr->AdjustType(checker, expr->CheckUnionMember(checker, baseType));
14113af6ab5fSopenharmony_ci    }
14123af6ab5fSopenharmony_ci    TypeErrorOnMissingProperty(expr, baseType, checker);
14133af6ab5fSopenharmony_ci    return expr->TsTypeOrError();
14143af6ab5fSopenharmony_ci}
14153af6ab5fSopenharmony_ci
14163af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::PreferredType(ir::ObjectExpression *expr) const
14173af6ab5fSopenharmony_ci{
14183af6ab5fSopenharmony_ci    return expr->preferredType_;
14193af6ab5fSopenharmony_ci}
14203af6ab5fSopenharmony_ci
14213af6ab5fSopenharmony_cistatic bool ValidatePreferredType(ir::ObjectExpression *expr, ETSChecker *checker)
14223af6ab5fSopenharmony_ci{
14233af6ab5fSopenharmony_ci    auto preferredType = expr->PreferredType();
14243af6ab5fSopenharmony_ci    if (preferredType == nullptr) {
14253af6ab5fSopenharmony_ci        checker->LogTypeError({"need to specify target type for class composite"}, expr->Start());
14263af6ab5fSopenharmony_ci        return false;
14273af6ab5fSopenharmony_ci    }
14283af6ab5fSopenharmony_ci
14293af6ab5fSopenharmony_ci    if (!preferredType->IsETSObjectType()) {
14303af6ab5fSopenharmony_ci        checker->LogTypeError(
14313af6ab5fSopenharmony_ci            {"Target type for class composite needs to be an object type, found '", preferredType, "'"}, expr->Start());
14323af6ab5fSopenharmony_ci        return false;
14333af6ab5fSopenharmony_ci    }
14343af6ab5fSopenharmony_ci
14353af6ab5fSopenharmony_ci    return true;
14363af6ab5fSopenharmony_ci}
14373af6ab5fSopenharmony_ci
14383af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ObjectExpression *expr) const
14393af6ab5fSopenharmony_ci{
14403af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
14413af6ab5fSopenharmony_ci    if (expr->TsTypeOrError() != nullptr) {
14423af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
14433af6ab5fSopenharmony_ci    }
14443af6ab5fSopenharmony_ci
14453af6ab5fSopenharmony_ci    if (!ValidatePreferredType(expr, checker)) {
14463af6ab5fSopenharmony_ci        expr->SetTsType(checker->GlobalTypeError());
14473af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
14483af6ab5fSopenharmony_ci    }
14493af6ab5fSopenharmony_ci
14503af6ab5fSopenharmony_ci    if (expr->PreferredType()->IsETSDynamicType()) {
14513af6ab5fSopenharmony_ci        for (ir::Expression *propExpr : expr->Properties()) {
14523af6ab5fSopenharmony_ci            ASSERT(propExpr->IsProperty());
14533af6ab5fSopenharmony_ci            ir::Property *prop = propExpr->AsProperty();
14543af6ab5fSopenharmony_ci            ir::Expression *value = prop->Value();
14553af6ab5fSopenharmony_ci            value->Check(checker);
14563af6ab5fSopenharmony_ci            ASSERT(value->TsType());
14573af6ab5fSopenharmony_ci        }
14583af6ab5fSopenharmony_ci
14593af6ab5fSopenharmony_ci        expr->SetTsType(expr->PreferredType());
14603af6ab5fSopenharmony_ci        return expr->PreferredType();
14613af6ab5fSopenharmony_ci    }
14623af6ab5fSopenharmony_ci
14633af6ab5fSopenharmony_ci    checker::ETSObjectType *objType = expr->PreferredType()->AsETSObjectType();
14643af6ab5fSopenharmony_ci    if (objType->HasObjectFlag(checker::ETSObjectFlags::INTERFACE)) {
14653af6ab5fSopenharmony_ci        // Object literal of interface tpye
14663af6ab5fSopenharmony_ci        // Further interfaceObjectLiteralLowering phase will resolve interface type
14673af6ab5fSopenharmony_ci        // and create corresponding anonymous class and class type
14683af6ab5fSopenharmony_ci        // Here we just set the type to pass the checker
14693af6ab5fSopenharmony_ci        CheckObjectExprProps(expr, checker::PropertySearchFlags::SEARCH_INSTANCE_METHOD |
14703af6ab5fSopenharmony_ci                                       checker::PropertySearchFlags::SEARCH_IN_INTERFACES);
14713af6ab5fSopenharmony_ci        expr->SetTsType(objType);
14723af6ab5fSopenharmony_ci        return objType;
14733af6ab5fSopenharmony_ci    }
14743af6ab5fSopenharmony_ci
14753af6ab5fSopenharmony_ci    if (objType->HasObjectFlag(checker::ETSObjectFlags::ABSTRACT)) {
14763af6ab5fSopenharmony_ci        checker->LogTypeError({"target type for class composite ", objType->Name(), " is not instantiable"},
14773af6ab5fSopenharmony_ci                              expr->Start());
14783af6ab5fSopenharmony_ci        expr->SetTsType(checker->GlobalTypeError());
14793af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
14803af6ab5fSopenharmony_ci    }
14813af6ab5fSopenharmony_ci
14823af6ab5fSopenharmony_ci    if (expr->PreferredType()->ToAssemblerName().str() == "escompat.Record" ||
14833af6ab5fSopenharmony_ci        expr->PreferredType()->ToAssemblerName().str() == "escompat.Map") {
14843af6ab5fSopenharmony_ci        // 7.6.3 Object Literal of Record Type
14853af6ab5fSopenharmony_ci        // Record is an alias to Map
14863af6ab5fSopenharmony_ci        // Here we just set the type to pass the checker
14873af6ab5fSopenharmony_ci        // See Record Lowering for details
14883af6ab5fSopenharmony_ci        expr->SetTsType(objType);
14893af6ab5fSopenharmony_ci        return objType;
14903af6ab5fSopenharmony_ci    }
14913af6ab5fSopenharmony_ci
14923af6ab5fSopenharmony_ci    bool haveEmptyConstructor = false;
14933af6ab5fSopenharmony_ci    for (checker::Signature *sig : objType->ConstructSignatures()) {
14943af6ab5fSopenharmony_ci        if (sig->Params().empty()) {
14953af6ab5fSopenharmony_ci            haveEmptyConstructor = true;
14963af6ab5fSopenharmony_ci            checker->ValidateSignatureAccessibility(objType, nullptr, sig, expr->Start());
14973af6ab5fSopenharmony_ci            break;
14983af6ab5fSopenharmony_ci        }
14993af6ab5fSopenharmony_ci    }
15003af6ab5fSopenharmony_ci    if (!haveEmptyConstructor) {
15013af6ab5fSopenharmony_ci        checker->LogTypeError({"type ", objType->Name(), " has no parameterless constructor"}, expr->Start());
15023af6ab5fSopenharmony_ci        expr->SetTsType(checker->GlobalTypeError());
15033af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
15043af6ab5fSopenharmony_ci    }
15053af6ab5fSopenharmony_ci
15063af6ab5fSopenharmony_ci    CheckObjectExprProps(expr, checker::PropertySearchFlags::SEARCH_INSTANCE_FIELD |
15073af6ab5fSopenharmony_ci                                   checker::PropertySearchFlags::SEARCH_IN_BASE |
15083af6ab5fSopenharmony_ci                                   checker::PropertySearchFlags::SEARCH_INSTANCE_METHOD);
15093af6ab5fSopenharmony_ci
15103af6ab5fSopenharmony_ci    expr->SetTsType(objType);
15113af6ab5fSopenharmony_ci    return objType;
15123af6ab5fSopenharmony_ci}
15133af6ab5fSopenharmony_ci
15143af6ab5fSopenharmony_civoid ETSAnalyzer::CheckObjectExprProps(const ir::ObjectExpression *expr, checker::PropertySearchFlags searchFlags) const
15153af6ab5fSopenharmony_ci{
15163af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
15173af6ab5fSopenharmony_ci    checker::ETSObjectType *objType = expr->PreferredType()->AsETSObjectType();
15183af6ab5fSopenharmony_ci
15193af6ab5fSopenharmony_ci    for (ir::Expression *propExpr : expr->Properties()) {
15203af6ab5fSopenharmony_ci        ASSERT(propExpr->IsProperty());
15213af6ab5fSopenharmony_ci        ir::Property *prop = propExpr->AsProperty();
15223af6ab5fSopenharmony_ci        ir::Expression *key = prop->Key();
15233af6ab5fSopenharmony_ci        ir::Expression *value = prop->Value();
15243af6ab5fSopenharmony_ci
15253af6ab5fSopenharmony_ci        util::StringView pname;
15263af6ab5fSopenharmony_ci        if (key->IsStringLiteral()) {
15273af6ab5fSopenharmony_ci            pname = key->AsStringLiteral()->Str();
15283af6ab5fSopenharmony_ci        } else if (key->IsIdentifier()) {
15293af6ab5fSopenharmony_ci            pname = key->AsIdentifier()->Name();
15303af6ab5fSopenharmony_ci        } else {
15313af6ab5fSopenharmony_ci            checker->LogTypeError({"key in class composite should be either identifier or string literal"},
15323af6ab5fSopenharmony_ci                                  expr->Start());
15333af6ab5fSopenharmony_ci            return;
15343af6ab5fSopenharmony_ci        }
15353af6ab5fSopenharmony_ci        varbinder::LocalVariable *lv = objType->GetProperty(pname, searchFlags);
15363af6ab5fSopenharmony_ci        if (lv == nullptr) {
15373af6ab5fSopenharmony_ci            checker->LogTypeError({"type ", objType->Name(), " has no property named ", pname}, propExpr->Start());
15383af6ab5fSopenharmony_ci            return;
15393af6ab5fSopenharmony_ci        }
15403af6ab5fSopenharmony_ci        checker->ValidatePropertyAccess(lv, objType, propExpr->Start());
15413af6ab5fSopenharmony_ci
15423af6ab5fSopenharmony_ci        if (key->IsIdentifier()) {
15433af6ab5fSopenharmony_ci            key->AsIdentifier()->SetVariable(lv);
15443af6ab5fSopenharmony_ci        }
15453af6ab5fSopenharmony_ci
15463af6ab5fSopenharmony_ci        auto *propType = checker->GetTypeOfVariable(lv);
15473af6ab5fSopenharmony_ci        key->SetTsType(propType);
15483af6ab5fSopenharmony_ci
15493af6ab5fSopenharmony_ci        if (value->IsObjectExpression()) {
15503af6ab5fSopenharmony_ci            value->AsObjectExpression()->SetPreferredType(propType);
15513af6ab5fSopenharmony_ci        }
15523af6ab5fSopenharmony_ci        value->SetTsType(value->Check(checker));
15533af6ab5fSopenharmony_ci
15543af6ab5fSopenharmony_ci        auto *const valueType = value->TsType();
15553af6ab5fSopenharmony_ci        const checker::Type *sourceType = checker->TryGettingFunctionTypeFromInvokeFunction(valueType);
15563af6ab5fSopenharmony_ci        const checker::Type *targetType = checker->TryGettingFunctionTypeFromInvokeFunction(propType);
15573af6ab5fSopenharmony_ci
15583af6ab5fSopenharmony_ci        checker::AssignmentContext(
15593af6ab5fSopenharmony_ci            checker->Relation(), value, valueType, propType, value->Start(),
15603af6ab5fSopenharmony_ci            {"Type '", sourceType, "' is not compatible with type '", targetType, "' at property '", pname, "'"});
15613af6ab5fSopenharmony_ci    }
15623af6ab5fSopenharmony_ci
15633af6ab5fSopenharmony_ci    if (objType->HasObjectFlag(ETSObjectFlags::REQUIRED)) {
15643af6ab5fSopenharmony_ci        checker->ValidateObjectLiteralForRequiredType(objType, expr);
15653af6ab5fSopenharmony_ci    }
15663af6ab5fSopenharmony_ci}
15673af6ab5fSopenharmony_ci
15683af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::OpaqueTypeNode *expr) const
15693af6ab5fSopenharmony_ci{
15703af6ab5fSopenharmony_ci    return expr->TsType();
15713af6ab5fSopenharmony_ci}
15723af6ab5fSopenharmony_ci
15733af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::SequenceExpression *expr) const
15743af6ab5fSopenharmony_ci{
15753af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
15763af6ab5fSopenharmony_ci    if (expr->TsTypeOrError() != nullptr) {
15773af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
15783af6ab5fSopenharmony_ci    }
15793af6ab5fSopenharmony_ci
15803af6ab5fSopenharmony_ci    for (auto *it : expr->Sequence()) {
15813af6ab5fSopenharmony_ci        it->Check(checker);
15823af6ab5fSopenharmony_ci    }
15833af6ab5fSopenharmony_ci    ASSERT(!expr->Sequence().empty());
15843af6ab5fSopenharmony_ci    expr->SetTsType(expr->Sequence().back()->TsType());
15853af6ab5fSopenharmony_ci    return nullptr;
15863af6ab5fSopenharmony_ci}
15873af6ab5fSopenharmony_ci
15883af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::SuperExpression *expr) const
15893af6ab5fSopenharmony_ci{
15903af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
15913af6ab5fSopenharmony_ci    if (expr->TsTypeOrError() != nullptr) {
15923af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
15933af6ab5fSopenharmony_ci    }
15943af6ab5fSopenharmony_ci
15953af6ab5fSopenharmony_ci    expr->SetTsType(checker->CheckThisOrSuperAccess(expr, checker->Context().ContainingClass()->SuperType(), "super"));
15963af6ab5fSopenharmony_ci    return expr->TsType();
15973af6ab5fSopenharmony_ci}
15983af6ab5fSopenharmony_ci
15993af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::TemplateLiteral *expr) const
16003af6ab5fSopenharmony_ci{
16013af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
16023af6ab5fSopenharmony_ci    if (expr->TsTypeOrError() != nullptr) {
16033af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
16043af6ab5fSopenharmony_ci    }
16053af6ab5fSopenharmony_ci
16063af6ab5fSopenharmony_ci    if (expr->Quasis().size() != expr->Expressions().size() + 1U) {
16073af6ab5fSopenharmony_ci        checker->LogTypeError("Invalid string template expression", expr->Start());
16083af6ab5fSopenharmony_ci        expr->SetTsType(checker->GlobalTypeError());
16093af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
16103af6ab5fSopenharmony_ci    }
16113af6ab5fSopenharmony_ci
16123af6ab5fSopenharmony_ci    for (auto *it : expr->Expressions()) {
16133af6ab5fSopenharmony_ci        it->Check(checker);
16143af6ab5fSopenharmony_ci    }
16153af6ab5fSopenharmony_ci
16163af6ab5fSopenharmony_ci    for (auto *it : expr->Quasis()) {
16173af6ab5fSopenharmony_ci        it->Check(checker);
16183af6ab5fSopenharmony_ci    }
16193af6ab5fSopenharmony_ci
16203af6ab5fSopenharmony_ci    expr->SetTsType(checker->GlobalBuiltinETSStringType());
16213af6ab5fSopenharmony_ci    return expr->TsType();
16223af6ab5fSopenharmony_ci}
16233af6ab5fSopenharmony_ci
16243af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ThisExpression *expr) const
16253af6ab5fSopenharmony_ci{
16263af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
16273af6ab5fSopenharmony_ci    if (expr->TsTypeOrError() != nullptr) {
16283af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
16293af6ab5fSopenharmony_ci    }
16303af6ab5fSopenharmony_ci
16313af6ab5fSopenharmony_ci    /*
16323af6ab5fSopenharmony_ci    example code:
16333af6ab5fSopenharmony_ci    ```
16343af6ab5fSopenharmony_ci        class A {
16353af6ab5fSopenharmony_ci            prop
16363af6ab5fSopenharmony_ci        }
16373af6ab5fSopenharmony_ci        function A.method() {
16383af6ab5fSopenharmony_ci            let a = () => {
16393af6ab5fSopenharmony_ci                console.println(this.prop)
16403af6ab5fSopenharmony_ci            }
16413af6ab5fSopenharmony_ci        }
16423af6ab5fSopenharmony_ci        is identical to
16433af6ab5fSopenharmony_ci        function method(this: A) {
16443af6ab5fSopenharmony_ci            let a = () => {
16453af6ab5fSopenharmony_ci                console.println(this.prop)
16463af6ab5fSopenharmony_ci            }
16473af6ab5fSopenharmony_ci        }
16483af6ab5fSopenharmony_ci    ```
16493af6ab5fSopenharmony_ci    here when "this" is used inside an extension function, we need to bind "this" to the first
16503af6ab5fSopenharmony_ci    parameter(MANDATORY_PARAM_THIS), and capture the parameter's variable other than containing class's variable
16513af6ab5fSopenharmony_ci    */
16523af6ab5fSopenharmony_ci    auto *variable = checker->AsETSChecker()->Scope()->Find(varbinder::VarBinder::MANDATORY_PARAM_THIS).variable;
16533af6ab5fSopenharmony_ci    if (checker->HasStatus(checker::CheckerStatus::IN_INSTANCE_EXTENSION_METHOD)) {
16543af6ab5fSopenharmony_ci        ASSERT(variable != nullptr);
16553af6ab5fSopenharmony_ci        expr->SetTsType(variable->TsType());
16563af6ab5fSopenharmony_ci    } else {
16573af6ab5fSopenharmony_ci        expr->SetTsType(checker->CheckThisOrSuperAccess(expr, checker->Context().ContainingClass(), "this"));
16583af6ab5fSopenharmony_ci    }
16593af6ab5fSopenharmony_ci
16603af6ab5fSopenharmony_ci    return expr->TsType();
16613af6ab5fSopenharmony_ci}
16623af6ab5fSopenharmony_ci
16633af6ab5fSopenharmony_ci// Get string literal type as potential typeof result type with respect to spec p.7.17
16643af6ab5fSopenharmony_cistatic checker::Type *GetTypeOfStringType(checker::Type *argType, ETSChecker *checker)
16653af6ab5fSopenharmony_ci{
16663af6ab5fSopenharmony_ci    if (auto unboxed = checker->MaybePrimitiveBuiltinType(argType);
16673af6ab5fSopenharmony_ci        unboxed->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) {
16683af6ab5fSopenharmony_ci        switch (checker->TypeKind(unboxed)) {
16693af6ab5fSopenharmony_ci            case TypeFlag::ETS_BOOLEAN: {
16703af6ab5fSopenharmony_ci                return checker->CreateETSStringLiteralType("boolean");
16713af6ab5fSopenharmony_ci            }
16723af6ab5fSopenharmony_ci            case TypeFlag::BYTE:
16733af6ab5fSopenharmony_ci            case TypeFlag::CHAR:
16743af6ab5fSopenharmony_ci            case TypeFlag::SHORT:
16753af6ab5fSopenharmony_ci            case TypeFlag::INT:
16763af6ab5fSopenharmony_ci            case TypeFlag::LONG:
16773af6ab5fSopenharmony_ci            case TypeFlag::FLOAT:
16783af6ab5fSopenharmony_ci            case TypeFlag::DOUBLE: {
16793af6ab5fSopenharmony_ci                return checker->CreateETSStringLiteralType("number");
16803af6ab5fSopenharmony_ci            }
16813af6ab5fSopenharmony_ci            default:
16823af6ab5fSopenharmony_ci                UNREACHABLE();
16833af6ab5fSopenharmony_ci        }
16843af6ab5fSopenharmony_ci    }
16853af6ab5fSopenharmony_ci    if (argType->IsETSUndefinedType()) {
16863af6ab5fSopenharmony_ci        return checker->CreateETSStringLiteralType(util::StringView("undefined"));
16873af6ab5fSopenharmony_ci    }
16883af6ab5fSopenharmony_ci    if (argType->IsETSArrayType() || argType->IsETSNullType()) {
16893af6ab5fSopenharmony_ci        return checker->CreateETSStringLiteralType(util::StringView("object"));
16903af6ab5fSopenharmony_ci    }
16913af6ab5fSopenharmony_ci    if (argType->IsETSIntEnumType()) {
16923af6ab5fSopenharmony_ci        return checker->CreateETSStringLiteralType(util::StringView("number"));
16933af6ab5fSopenharmony_ci    }
16943af6ab5fSopenharmony_ci    if (argType->IsETSStringType() || argType->IsETSStringEnumType()) {
16953af6ab5fSopenharmony_ci        return checker->CreateETSStringLiteralType(util::StringView("string"));
16963af6ab5fSopenharmony_ci    }
16973af6ab5fSopenharmony_ci    if (argType->IsETSBigIntType()) {
16983af6ab5fSopenharmony_ci        return checker->CreateETSStringLiteralType(util::StringView("bigint"));
16993af6ab5fSopenharmony_ci    }
17003af6ab5fSopenharmony_ci    if (argType->IsETSFunctionType()) {
17013af6ab5fSopenharmony_ci        return checker->CreateETSStringLiteralType(util::StringView("function"));
17023af6ab5fSopenharmony_ci    }
17033af6ab5fSopenharmony_ci
17043af6ab5fSopenharmony_ci    return checker->GlobalBuiltinETSStringType();
17053af6ab5fSopenharmony_ci}
17063af6ab5fSopenharmony_ci
17073af6ab5fSopenharmony_cistatic checker::Type *ComputeTypeOfType(ETSChecker *checker, checker::Type *argType)
17083af6ab5fSopenharmony_ci{
17093af6ab5fSopenharmony_ci    checker::Type *ret = nullptr;
17103af6ab5fSopenharmony_ci    ArenaVector<checker::Type *> types(checker->Allocator()->Adapter());
17113af6ab5fSopenharmony_ci    if (argType->IsETSUnionType()) {
17123af6ab5fSopenharmony_ci        for (auto *it : argType->AsETSUnionType()->ConstituentTypes()) {
17133af6ab5fSopenharmony_ci            checker::Type *elType = ComputeTypeOfType(checker, it);
17143af6ab5fSopenharmony_ci            types.push_back(elType);
17153af6ab5fSopenharmony_ci        }
17163af6ab5fSopenharmony_ci        ret = checker->CreateETSUnionType(std::move(types));
17173af6ab5fSopenharmony_ci    } else {
17183af6ab5fSopenharmony_ci        ret = GetTypeOfStringType(argType, checker);
17193af6ab5fSopenharmony_ci    }
17203af6ab5fSopenharmony_ci    return ret;
17213af6ab5fSopenharmony_ci}
17223af6ab5fSopenharmony_ci
17233af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TypeofExpression *expr) const
17243af6ab5fSopenharmony_ci{
17253af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
17263af6ab5fSopenharmony_ci    if (expr->TsTypeOrError() != nullptr) {
17273af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
17283af6ab5fSopenharmony_ci    }
17293af6ab5fSopenharmony_ci
17303af6ab5fSopenharmony_ci    expr->Argument()->Check(checker);
17313af6ab5fSopenharmony_ci    expr->SetTsType(ComputeTypeOfType(checker, expr->Argument()->TsType()));
17323af6ab5fSopenharmony_ci    return expr->TsType();
17333af6ab5fSopenharmony_ci}
17343af6ab5fSopenharmony_ci
17353af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::UnaryExpression *expr) const
17363af6ab5fSopenharmony_ci{
17373af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
17383af6ab5fSopenharmony_ci
17393af6ab5fSopenharmony_ci    if (expr->TsTypeOrError() != nullptr) {
17403af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
17413af6ab5fSopenharmony_ci    }
17423af6ab5fSopenharmony_ci
17433af6ab5fSopenharmony_ci    auto argType = expr->argument_->Check(checker);
17443af6ab5fSopenharmony_ci    const auto isCondExpr = expr->OperatorType() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK;
17453af6ab5fSopenharmony_ci    checker::Type *operandType = checker->ApplyUnaryOperatorPromotion(argType, true, true, isCondExpr);
17463af6ab5fSopenharmony_ci    auto unboxedOperandType = isCondExpr ? checker->ETSBuiltinTypeAsConditionalType(argType)
17473af6ab5fSopenharmony_ci                                         : checker->ETSBuiltinTypeAsPrimitiveType(argType);
17483af6ab5fSopenharmony_ci
17493af6ab5fSopenharmony_ci    if (argType != nullptr && argType->IsETSBigIntType() && argType->HasTypeFlag(checker::TypeFlag::BIGINT_LITERAL)) {
17503af6ab5fSopenharmony_ci        switch (expr->OperatorType()) {
17513af6ab5fSopenharmony_ci            case lexer::TokenType::PUNCTUATOR_MINUS: {
17523af6ab5fSopenharmony_ci                checker::Type *type = checker->CreateETSBigIntLiteralType(argType->AsETSBigIntType()->GetValue());
17533af6ab5fSopenharmony_ci
17543af6ab5fSopenharmony_ci                // We do not need this const anymore as we are negating the bigint object in runtime
17553af6ab5fSopenharmony_ci                type->RemoveTypeFlag(checker::TypeFlag::CONSTANT);
17563af6ab5fSopenharmony_ci                expr->argument_->SetTsType(type);
17573af6ab5fSopenharmony_ci                expr->SetTsType(type);
17583af6ab5fSopenharmony_ci                return expr->TsType();
17593af6ab5fSopenharmony_ci            }
17603af6ab5fSopenharmony_ci            default:
17613af6ab5fSopenharmony_ci                // Handled below
17623af6ab5fSopenharmony_ci                // NOTE(kkonsw): handle other unary operators for bigint literals
17633af6ab5fSopenharmony_ci                break;
17643af6ab5fSopenharmony_ci        }
17653af6ab5fSopenharmony_ci    }
17663af6ab5fSopenharmony_ci
17673af6ab5fSopenharmony_ci    if (argType != nullptr && argType->IsETSBigIntType()) {
17683af6ab5fSopenharmony_ci        switch (expr->OperatorType()) {
17693af6ab5fSopenharmony_ci            case lexer::TokenType::PUNCTUATOR_MINUS:
17703af6ab5fSopenharmony_ci            case lexer::TokenType::PUNCTUATOR_PLUS:
17713af6ab5fSopenharmony_ci            case lexer::TokenType::PUNCTUATOR_TILDE: {
17723af6ab5fSopenharmony_ci                expr->SetTsType(argType);
17733af6ab5fSopenharmony_ci                return expr->TsType();
17743af6ab5fSopenharmony_ci            }
17753af6ab5fSopenharmony_ci            default:
17763af6ab5fSopenharmony_ci                break;
17773af6ab5fSopenharmony_ci        }
17783af6ab5fSopenharmony_ci    }
17793af6ab5fSopenharmony_ci
17803af6ab5fSopenharmony_ci    if (argType != nullptr && argType->IsETSEnumType()) {
17813af6ab5fSopenharmony_ci        expr->Argument()->AddAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF);
17823af6ab5fSopenharmony_ci    }
17833af6ab5fSopenharmony_ci    SetTsTypeForUnaryExpression(checker, expr, operandType);
17843af6ab5fSopenharmony_ci
17853af6ab5fSopenharmony_ci    if ((argType != nullptr) && argType->IsETSObjectType() && (unboxedOperandType != nullptr) &&
17863af6ab5fSopenharmony_ci        unboxedOperandType->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) {
17873af6ab5fSopenharmony_ci        expr->Argument()->AddBoxingUnboxingFlags(checker->GetUnboxingFlag(unboxedOperandType));
17883af6ab5fSopenharmony_ci    }
17893af6ab5fSopenharmony_ci
17903af6ab5fSopenharmony_ci    checker->Context().CheckUnarySmartCastCondition(expr);
17913af6ab5fSopenharmony_ci
17923af6ab5fSopenharmony_ci    return expr->TsType();
17933af6ab5fSopenharmony_ci}
17943af6ab5fSopenharmony_ci
17953af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::UpdateExpression *expr) const
17963af6ab5fSopenharmony_ci{
17973af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
17983af6ab5fSopenharmony_ci    if (expr->TsTypeOrError() != nullptr) {
17993af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
18003af6ab5fSopenharmony_ci    }
18013af6ab5fSopenharmony_ci
18023af6ab5fSopenharmony_ci    checker::Type *operandType = expr->argument_->Check(checker);
18033af6ab5fSopenharmony_ci    if (expr->Argument()->IsIdentifier()) {
18043af6ab5fSopenharmony_ci        checker->ValidateUnaryOperatorOperand(expr->Argument()->AsIdentifier()->Variable());
18053af6ab5fSopenharmony_ci    } else if (expr->Argument()->IsTSAsExpression()) {
18063af6ab5fSopenharmony_ci        if (auto *const asExprVar = expr->Argument()->AsTSAsExpression()->Variable(); asExprVar != nullptr) {
18073af6ab5fSopenharmony_ci            checker->ValidateUnaryOperatorOperand(asExprVar);
18083af6ab5fSopenharmony_ci        }
18093af6ab5fSopenharmony_ci    } else if (expr->Argument()->IsTSNonNullExpression()) {
18103af6ab5fSopenharmony_ci        if (auto *const nonNullExprVar = expr->Argument()->AsTSNonNullExpression()->Variable();
18113af6ab5fSopenharmony_ci            nonNullExprVar != nullptr) {
18123af6ab5fSopenharmony_ci            checker->ValidateUnaryOperatorOperand(nonNullExprVar);
18133af6ab5fSopenharmony_ci        }
18143af6ab5fSopenharmony_ci    } else {
18153af6ab5fSopenharmony_ci        ASSERT(expr->Argument()->IsMemberExpression());
18163af6ab5fSopenharmony_ci        varbinder::LocalVariable *propVar = expr->argument_->AsMemberExpression()->PropVar();
18173af6ab5fSopenharmony_ci        if (propVar != nullptr) {
18183af6ab5fSopenharmony_ci            checker->ValidateUnaryOperatorOperand(propVar);
18193af6ab5fSopenharmony_ci        }
18203af6ab5fSopenharmony_ci    }
18213af6ab5fSopenharmony_ci
18223af6ab5fSopenharmony_ci    if (operandType->IsETSBigIntType()) {
18233af6ab5fSopenharmony_ci        expr->SetTsType(operandType);
18243af6ab5fSopenharmony_ci        return expr->TsType();
18253af6ab5fSopenharmony_ci    }
18263af6ab5fSopenharmony_ci
18273af6ab5fSopenharmony_ci    auto unboxedType = checker->ETSBuiltinTypeAsPrimitiveType(operandType);
18283af6ab5fSopenharmony_ci    if (unboxedType == nullptr || !unboxedType->HasTypeFlag(checker::TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC)) {
18293af6ab5fSopenharmony_ci        checker->LogTypeError("Bad operand type, the type of the operand must be numeric type.",
18303af6ab5fSopenharmony_ci                              expr->Argument()->Start());
18313af6ab5fSopenharmony_ci        expr->SetTsType(checker->GlobalTypeError());
18323af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
18333af6ab5fSopenharmony_ci    }
18343af6ab5fSopenharmony_ci
18353af6ab5fSopenharmony_ci    if (operandType->IsETSObjectType()) {
18363af6ab5fSopenharmony_ci        expr->Argument()->AddBoxingUnboxingFlags(checker->GetUnboxingFlag(unboxedType) |
18373af6ab5fSopenharmony_ci                                                 checker->GetBoxingFlag(unboxedType));
18383af6ab5fSopenharmony_ci    }
18393af6ab5fSopenharmony_ci
18403af6ab5fSopenharmony_ci    expr->SetTsType(operandType);
18413af6ab5fSopenharmony_ci    return expr->TsType();
18423af6ab5fSopenharmony_ci}
18433af6ab5fSopenharmony_ci
18443af6ab5fSopenharmony_ci// compile methods for LITERAL EXPRESSIONS in alphabetical order
18453af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::BigIntLiteral *expr) const
18463af6ab5fSopenharmony_ci{
18473af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
18483af6ab5fSopenharmony_ci    expr->SetTsType(checker->CreateETSBigIntLiteralType(expr->Str()));
18493af6ab5fSopenharmony_ci    return expr->TsType();
18503af6ab5fSopenharmony_ci}
18513af6ab5fSopenharmony_ci
18523af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::BooleanLiteral *expr) const
18533af6ab5fSopenharmony_ci{
18543af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
18553af6ab5fSopenharmony_ci    if (expr->TsTypeOrError() == nullptr) {
18563af6ab5fSopenharmony_ci        expr->SetTsType(checker->CreateETSBooleanType(expr->Value()));
18573af6ab5fSopenharmony_ci    }
18583af6ab5fSopenharmony_ci    return expr->TsType();
18593af6ab5fSopenharmony_ci}
18603af6ab5fSopenharmony_ci
18613af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::CharLiteral *expr) const
18623af6ab5fSopenharmony_ci{
18633af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
18643af6ab5fSopenharmony_ci    if (expr->TsTypeOrError() == nullptr) {
18653af6ab5fSopenharmony_ci        expr->SetTsType(checker->Allocator()->New<checker::CharType>(expr->Char()));
18663af6ab5fSopenharmony_ci    }
18673af6ab5fSopenharmony_ci    return expr->TsType();
18683af6ab5fSopenharmony_ci}
18693af6ab5fSopenharmony_ci
18703af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::NullLiteral *expr) const
18713af6ab5fSopenharmony_ci{
18723af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
18733af6ab5fSopenharmony_ci    if (expr->TsTypeOrError() == nullptr) {
18743af6ab5fSopenharmony_ci        expr->SetTsType(checker->GlobalETSNullType());
18753af6ab5fSopenharmony_ci    }
18763af6ab5fSopenharmony_ci    return expr->TsType();
18773af6ab5fSopenharmony_ci}
18783af6ab5fSopenharmony_ci
18793af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::NamespaceDeclaration *st) const
18803af6ab5fSopenharmony_ci{
18813af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
18823af6ab5fSopenharmony_ci    st->Definition()->Check(checker);
18833af6ab5fSopenharmony_ci    return nullptr;
18843af6ab5fSopenharmony_ci}
18853af6ab5fSopenharmony_ci
18863af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::NamespaceDefinition *st) const
18873af6ab5fSopenharmony_ci{
18883af6ab5fSopenharmony_ci    return nullptr;
18893af6ab5fSopenharmony_ci}
18903af6ab5fSopenharmony_ci
18913af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::NumberLiteral *expr) const
18923af6ab5fSopenharmony_ci{
18933af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
18943af6ab5fSopenharmony_ci    if (expr->Number().IsInt()) {
18953af6ab5fSopenharmony_ci        expr->SetTsType(checker->CreateIntType(expr->Number().GetInt()));
18963af6ab5fSopenharmony_ci        return expr->TsType();
18973af6ab5fSopenharmony_ci    }
18983af6ab5fSopenharmony_ci
18993af6ab5fSopenharmony_ci    if (expr->Number().IsLong()) {
19003af6ab5fSopenharmony_ci        expr->SetTsType(checker->CreateLongType(expr->Number().GetLong()));
19013af6ab5fSopenharmony_ci        return expr->TsType();
19023af6ab5fSopenharmony_ci    }
19033af6ab5fSopenharmony_ci
19043af6ab5fSopenharmony_ci    if (expr->Number().IsFloat()) {
19053af6ab5fSopenharmony_ci        expr->SetTsType(checker->CreateFloatType(expr->Number().GetFloat()));
19063af6ab5fSopenharmony_ci        return expr->TsType();
19073af6ab5fSopenharmony_ci    }
19083af6ab5fSopenharmony_ci
19093af6ab5fSopenharmony_ci    expr->SetTsType(checker->CreateDoubleType(expr->Number().GetDouble()));
19103af6ab5fSopenharmony_ci    return expr->TsType();
19113af6ab5fSopenharmony_ci}
19123af6ab5fSopenharmony_ci
19133af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::StringLiteral *expr) const
19143af6ab5fSopenharmony_ci{
19153af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
19163af6ab5fSopenharmony_ci    if (expr->TsTypeOrError() == nullptr) {
19173af6ab5fSopenharmony_ci        expr->SetTsType(checker->CreateETSStringLiteralType(expr->Str()));
19183af6ab5fSopenharmony_ci    }
19193af6ab5fSopenharmony_ci    return expr->TsType();
19203af6ab5fSopenharmony_ci}
19213af6ab5fSopenharmony_ci
19223af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ImportDeclaration *st) const
19233af6ab5fSopenharmony_ci{
19243af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
19253af6ab5fSopenharmony_ci    checker::Type *type = nullptr;
19263af6ab5fSopenharmony_ci    for (auto *spec : st->Specifiers()) {
19273af6ab5fSopenharmony_ci        if (spec->IsImportNamespaceSpecifier()) {
19283af6ab5fSopenharmony_ci            type = spec->AsImportNamespaceSpecifier()->Check(checker);
19293af6ab5fSopenharmony_ci        }
19303af6ab5fSopenharmony_ci    }
19313af6ab5fSopenharmony_ci
19323af6ab5fSopenharmony_ci    return type;
19333af6ab5fSopenharmony_ci}
19343af6ab5fSopenharmony_ci
19353af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ImportNamespaceSpecifier *st) const
19363af6ab5fSopenharmony_ci{
19373af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
19383af6ab5fSopenharmony_ci    if (st->Local()->Name().Empty()) {
19393af6ab5fSopenharmony_ci        return nullptr;
19403af6ab5fSopenharmony_ci    }
19413af6ab5fSopenharmony_ci
19423af6ab5fSopenharmony_ci    if (st->Local()->AsIdentifier()->TsTypeOrError() != nullptr) {
19433af6ab5fSopenharmony_ci        return st->Local()->TsTypeOrError();
19443af6ab5fSopenharmony_ci    }
19453af6ab5fSopenharmony_ci
19463af6ab5fSopenharmony_ci    auto *importDecl = st->Parent()->AsETSImportDeclaration();
19473af6ab5fSopenharmony_ci
19483af6ab5fSopenharmony_ci    if (importDecl->IsPureDynamic()) {
19493af6ab5fSopenharmony_ci        auto *type = checker->GlobalBuiltinDynamicType(importDecl->Language());
19503af6ab5fSopenharmony_ci        checker->SetrModuleObjectTsType(st->Local(), type);
19513af6ab5fSopenharmony_ci        return type;
19523af6ab5fSopenharmony_ci    }
19533af6ab5fSopenharmony_ci
19543af6ab5fSopenharmony_ci    return checker->GetImportSpecifierObjectType(importDecl, st->Local()->AsIdentifier());
19553af6ab5fSopenharmony_ci}
19563af6ab5fSopenharmony_ci
19573af6ab5fSopenharmony_ci// compile methods for STATEMENTS in alphabetical order
19583af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::AssertStatement *st) const
19593af6ab5fSopenharmony_ci{
19603af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
19613af6ab5fSopenharmony_ci    if (!(st->Test()->Check(checker)->HasTypeFlag(TypeFlag::ETS_BOOLEAN | TypeFlag::BOOLEAN_LIKE) ||
19623af6ab5fSopenharmony_ci          st->Test()->Check(checker)->ToString() == "Boolean")) {
19633af6ab5fSopenharmony_ci        checker->LogTypeError("Bad operand type, the type of the operand must be boolean type.", st->Test()->Start());
19643af6ab5fSopenharmony_ci    }
19653af6ab5fSopenharmony_ci
19663af6ab5fSopenharmony_ci    if (st->Second() != nullptr) {
19673af6ab5fSopenharmony_ci        auto *msgType = st->second_->Check(checker);
19683af6ab5fSopenharmony_ci
19693af6ab5fSopenharmony_ci        if (!msgType->IsETSStringType()) {
19703af6ab5fSopenharmony_ci            checker->LogTypeError("Assert message must be string", st->Second()->Start());
19713af6ab5fSopenharmony_ci        }
19723af6ab5fSopenharmony_ci    }
19733af6ab5fSopenharmony_ci
19743af6ab5fSopenharmony_ci    return nullptr;
19753af6ab5fSopenharmony_ci}
19763af6ab5fSopenharmony_ci
19773af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::BlockStatement *st) const
19783af6ab5fSopenharmony_ci{
19793af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
19803af6ab5fSopenharmony_ci    checker::ScopeContext scopeCtx(checker, st->Scope());
19813af6ab5fSopenharmony_ci
19823af6ab5fSopenharmony_ci    // Iterator type checking of statements is modified to index type, to allow modifying the statement list during
19833af6ab5fSopenharmony_ci    // checking without invalidating the iterator
19843af6ab5fSopenharmony_ci    //---- Don't modify this to iterator, as it may break things during checking
19853af6ab5fSopenharmony_ci    for (std::size_t idx = 0; idx < st->Statements().size(); ++idx) {
19863af6ab5fSopenharmony_ci        auto *stmt = st->Statements()[idx];
19873af6ab5fSopenharmony_ci        stmt->Check(checker);
19883af6ab5fSopenharmony_ci
19893af6ab5fSopenharmony_ci        //  NOTE! Processing of trailing blocks was moved here so that smart casts could be applied correctly
19903af6ab5fSopenharmony_ci        if (auto const tb = st->trailingBlocks_.find(stmt); tb != st->trailingBlocks_.end()) {
19913af6ab5fSopenharmony_ci            auto *const trailingBlock = tb->second;
19923af6ab5fSopenharmony_ci            trailingBlock->Check(checker);
19933af6ab5fSopenharmony_ci            st->Statements().emplace(std::next(st->Statements().begin() + idx), trailingBlock);
19943af6ab5fSopenharmony_ci            ++idx;
19953af6ab5fSopenharmony_ci        }
19963af6ab5fSopenharmony_ci    }
19973af6ab5fSopenharmony_ci    if (UNLIKELY(checker->GetDebugInfoPlugin() != nullptr)) {
19983af6ab5fSopenharmony_ci        // Compilation in eval-mode might require to create additional statements.
19993af6ab5fSopenharmony_ci        // In this case, they must be created after iteration through statements ends.
20003af6ab5fSopenharmony_ci        checker->GetDebugInfoPlugin()->AddPrologueEpilogue(st);
20013af6ab5fSopenharmony_ci    }
20023af6ab5fSopenharmony_ci
20033af6ab5fSopenharmony_ci    //  Remove possible smart casts for variables declared in inner scope:
20043af6ab5fSopenharmony_ci    if (auto const *const scope = st->Scope();
20053af6ab5fSopenharmony_ci        scope->IsFunctionScope() && st->Parent()->Parent()->Parent()->IsMethodDefinition()) {
20063af6ab5fSopenharmony_ci        // When exiting method definition, just clear all smart casts
20073af6ab5fSopenharmony_ci        checker->Context().ClearSmartCasts();
20083af6ab5fSopenharmony_ci    } else if (!scope->IsGlobalScope()) {
20093af6ab5fSopenharmony_ci        // otherwise only check inner declarations
20103af6ab5fSopenharmony_ci        for (auto const *const decl : scope->Decls()) {
20113af6ab5fSopenharmony_ci            if (decl->IsLetOrConstDecl() && decl->Node()->IsIdentifier()) {
20123af6ab5fSopenharmony_ci                checker->Context().RemoveSmartCast(decl->Node()->AsIdentifier()->Variable());
20133af6ab5fSopenharmony_ci            }
20143af6ab5fSopenharmony_ci        }
20153af6ab5fSopenharmony_ci    }
20163af6ab5fSopenharmony_ci
20173af6ab5fSopenharmony_ci    return nullptr;
20183af6ab5fSopenharmony_ci}
20193af6ab5fSopenharmony_ci
20203af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::BreakStatement *st) const
20213af6ab5fSopenharmony_ci{
20223af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
20233af6ab5fSopenharmony_ci    auto node = checker->FindJumpTarget(st);
20243af6ab5fSopenharmony_ci    if (!node.has_value()) {
20253af6ab5fSopenharmony_ci        return checker->GlobalTypeError();
20263af6ab5fSopenharmony_ci    }
20273af6ab5fSopenharmony_ci    st->SetTarget(*node);
20283af6ab5fSopenharmony_ci
20293af6ab5fSopenharmony_ci    checker->Context().OnBreakStatement(st);
20303af6ab5fSopenharmony_ci    return nullptr;
20313af6ab5fSopenharmony_ci}
20323af6ab5fSopenharmony_ci
20333af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ClassDeclaration *st) const
20343af6ab5fSopenharmony_ci{
20353af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
20363af6ab5fSopenharmony_ci    st->Definition()->Check(checker);
20373af6ab5fSopenharmony_ci    return nullptr;
20383af6ab5fSopenharmony_ci}
20393af6ab5fSopenharmony_ci
20403af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ContinueStatement *st) const
20413af6ab5fSopenharmony_ci{
20423af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
20433af6ab5fSopenharmony_ci    auto node = checker->FindJumpTarget(st);
20443af6ab5fSopenharmony_ci    if (!node.has_value()) {
20453af6ab5fSopenharmony_ci        return checker->GlobalTypeError();
20463af6ab5fSopenharmony_ci    }
20473af6ab5fSopenharmony_ci    st->SetTarget(*node);
20483af6ab5fSopenharmony_ci
20493af6ab5fSopenharmony_ci    checker->AddStatus(CheckerStatus::MEET_CONTINUE);
20503af6ab5fSopenharmony_ci    return nullptr;
20513af6ab5fSopenharmony_ci}
20523af6ab5fSopenharmony_ci
20533af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::DoWhileStatement *st) const
20543af6ab5fSopenharmony_ci{
20553af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
20563af6ab5fSopenharmony_ci    checker::ScopeContext scopeCtx(checker, st->Scope());
20573af6ab5fSopenharmony_ci
20583af6ab5fSopenharmony_ci    //  NOTE: Smart casts are not processed correctly within the loops now, thus clear them at this point.
20593af6ab5fSopenharmony_ci    auto [smartCasts, clearFlag] = checker->Context().EnterLoop(*st);
20603af6ab5fSopenharmony_ci
20613af6ab5fSopenharmony_ci    checker->CheckTruthinessOfType(st->Test());
20623af6ab5fSopenharmony_ci    st->Body()->Check(checker);
20633af6ab5fSopenharmony_ci
20643af6ab5fSopenharmony_ci    checker->Context().ExitLoop(smartCasts, clearFlag, st);
20653af6ab5fSopenharmony_ci    return nullptr;
20663af6ab5fSopenharmony_ci}
20673af6ab5fSopenharmony_ci
20683af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::EmptyStatement *st) const
20693af6ab5fSopenharmony_ci{
20703af6ab5fSopenharmony_ci    return nullptr;
20713af6ab5fSopenharmony_ci}
20723af6ab5fSopenharmony_ci
20733af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ExpressionStatement *st) const
20743af6ab5fSopenharmony_ci{
20753af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
20763af6ab5fSopenharmony_ci    return st->GetExpression()->Check(checker);
20773af6ab5fSopenharmony_ci}
20783af6ab5fSopenharmony_ci
20793af6ab5fSopenharmony_cistatic bool ValidateAndProcessIteratorType(ETSChecker *checker, Type *elemType, ir::ForOfStatement *const st)
20803af6ab5fSopenharmony_ci{
20813af6ab5fSopenharmony_ci    checker::Type *iterType = GetIteratorType(checker, elemType, st->Left());
20823af6ab5fSopenharmony_ci    if (iterType->IsTypeError()) {
20833af6ab5fSopenharmony_ci        return false;
20843af6ab5fSopenharmony_ci    }
20853af6ab5fSopenharmony_ci    auto *const relation = checker->Relation();
20863af6ab5fSopenharmony_ci    relation->SetFlags(checker::TypeRelationFlag::ASSIGNMENT_CONTEXT);
20873af6ab5fSopenharmony_ci    relation->SetNode(st->Left()->IsVariableDeclaration()
20883af6ab5fSopenharmony_ci                          ? st->Left()->AsVariableDeclaration()->Declarators().front()->Id()
20893af6ab5fSopenharmony_ci                          : st->Left()->AsIdentifier());
20903af6ab5fSopenharmony_ci
20913af6ab5fSopenharmony_ci    if (!relation->IsAssignableTo(elemType, iterType)) {
20923af6ab5fSopenharmony_ci        std::stringstream ss {};
20933af6ab5fSopenharmony_ci        ss << "Source element type '" << elemType->ToString() << "' is not assignable to the loop iterator type '"
20943af6ab5fSopenharmony_ci           << iterType->ToString() << "'.";
20953af6ab5fSopenharmony_ci        checker->LogTypeError(ss.str(), st->Start());
20963af6ab5fSopenharmony_ci        return false;
20973af6ab5fSopenharmony_ci    }
20983af6ab5fSopenharmony_ci
20993af6ab5fSopenharmony_ci    relation->SetNode(nullptr);
21003af6ab5fSopenharmony_ci    relation->SetFlags(checker::TypeRelationFlag::NONE);
21013af6ab5fSopenharmony_ci
21023af6ab5fSopenharmony_ci    if (iterType->Variable() == nullptr && !iterType->IsETSObjectType() && elemType->IsETSObjectType() &&
21033af6ab5fSopenharmony_ci        st->Left()->IsVariableDeclaration()) {
21043af6ab5fSopenharmony_ci        for (auto &declarator : st->Left()->AsVariableDeclaration()->Declarators()) {
21053af6ab5fSopenharmony_ci            checker->AddBoxingUnboxingFlagsToNode(declarator->Id(), iterType);
21063af6ab5fSopenharmony_ci        }
21073af6ab5fSopenharmony_ci    }
21083af6ab5fSopenharmony_ci    return true;
21093af6ab5fSopenharmony_ci}
21103af6ab5fSopenharmony_ci// NOLINTBEGIN(modernize-avoid-c-arrays)
21113af6ab5fSopenharmony_cistatic constexpr char const MISSING_SOURCE_EXPR_TYPE[] =
21123af6ab5fSopenharmony_ci    "Cannot determine source expression type in the 'for-of' statement.";
21133af6ab5fSopenharmony_cistatic constexpr char const INVALID_SOURCE_EXPR_TYPE[] =
21143af6ab5fSopenharmony_ci    "'For-of' statement source expression is not of iterable type.";
21153af6ab5fSopenharmony_ci// NOLINTEND(modernize-avoid-c-arrays)
21163af6ab5fSopenharmony_ci
21173af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ForOfStatement *const st) const
21183af6ab5fSopenharmony_ci{
21193af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
21203af6ab5fSopenharmony_ci    checker::ScopeContext scopeCtx(checker, st->Scope());
21213af6ab5fSopenharmony_ci
21223af6ab5fSopenharmony_ci    //  NOTE: Smart casts are not processed correctly within the loops now, thus clear them at this point.
21233af6ab5fSopenharmony_ci    auto [smartCasts, clearFlag] = checker->Context().EnterLoop(*st);
21243af6ab5fSopenharmony_ci
21253af6ab5fSopenharmony_ci    checker::Type *const exprType = st->Right()->Check(checker);
21263af6ab5fSopenharmony_ci    if (exprType == nullptr) {
21273af6ab5fSopenharmony_ci        checker->LogTypeError(MISSING_SOURCE_EXPR_TYPE, st->Right()->Start());
21283af6ab5fSopenharmony_ci        return checker->GlobalTypeError();
21293af6ab5fSopenharmony_ci    }
21303af6ab5fSopenharmony_ci
21313af6ab5fSopenharmony_ci    checker::Type *elemType = nullptr;
21323af6ab5fSopenharmony_ci
21333af6ab5fSopenharmony_ci    if (exprType->IsETSStringType()) {
21343af6ab5fSopenharmony_ci        elemType = checker->GetGlobalTypesHolder()->GlobalCharType();
21353af6ab5fSopenharmony_ci    } else if (exprType->IsETSArrayType()) {
21363af6ab5fSopenharmony_ci        elemType = exprType->AsETSArrayType()->ElementType()->Instantiate(checker->Allocator(), checker->Relation(),
21373af6ab5fSopenharmony_ci                                                                          checker->GetGlobalTypesHolder());
21383af6ab5fSopenharmony_ci        if (elemType != nullptr) {
21393af6ab5fSopenharmony_ci            elemType->RemoveTypeFlag(checker::TypeFlag::CONSTANT);
21403af6ab5fSopenharmony_ci        }
21413af6ab5fSopenharmony_ci    } else if (exprType->IsETSObjectType() || exprType->IsETSUnionType() || exprType->IsETSTypeParameter()) {
21423af6ab5fSopenharmony_ci        elemType = st->CheckIteratorMethod(checker);
21433af6ab5fSopenharmony_ci    }
21443af6ab5fSopenharmony_ci
21453af6ab5fSopenharmony_ci    if (elemType == nullptr) {
21463af6ab5fSopenharmony_ci        checker->LogTypeError(INVALID_SOURCE_EXPR_TYPE, st->Right()->Start());
21473af6ab5fSopenharmony_ci        return checker->GlobalTypeError();
21483af6ab5fSopenharmony_ci    }
21493af6ab5fSopenharmony_ci
21503af6ab5fSopenharmony_ci    st->Left()->Check(checker);
21513af6ab5fSopenharmony_ci
21523af6ab5fSopenharmony_ci    if (!ValidateAndProcessIteratorType(checker, elemType, st)) {
21533af6ab5fSopenharmony_ci        return checker->GlobalTypeError();
21543af6ab5fSopenharmony_ci    };
21553af6ab5fSopenharmony_ci
21563af6ab5fSopenharmony_ci    st->Body()->Check(checker);
21573af6ab5fSopenharmony_ci
21583af6ab5fSopenharmony_ci    checker->Context().ExitLoop(smartCasts, clearFlag, st);
21593af6ab5fSopenharmony_ci    return nullptr;
21603af6ab5fSopenharmony_ci}
21613af6ab5fSopenharmony_ci
21623af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ForUpdateStatement *st) const
21633af6ab5fSopenharmony_ci{
21643af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
21653af6ab5fSopenharmony_ci    checker::ScopeContext scopeCtx(checker, st->Scope());
21663af6ab5fSopenharmony_ci
21673af6ab5fSopenharmony_ci    //  NOTE: Smart casts are not processed correctly within the loops now, thus clear them at this point.
21683af6ab5fSopenharmony_ci    auto [smartCasts, clearFlag] = checker->Context().EnterLoop(*st);
21693af6ab5fSopenharmony_ci
21703af6ab5fSopenharmony_ci    if (st->Init() != nullptr) {
21713af6ab5fSopenharmony_ci        st->Init()->Check(checker);
21723af6ab5fSopenharmony_ci    }
21733af6ab5fSopenharmony_ci
21743af6ab5fSopenharmony_ci    if (st->Test() != nullptr) {
21753af6ab5fSopenharmony_ci        checker->CheckTruthinessOfType(st->Test());
21763af6ab5fSopenharmony_ci    }
21773af6ab5fSopenharmony_ci
21783af6ab5fSopenharmony_ci    if (st->Update() != nullptr) {
21793af6ab5fSopenharmony_ci        st->Update()->Check(checker);
21803af6ab5fSopenharmony_ci    }
21813af6ab5fSopenharmony_ci
21823af6ab5fSopenharmony_ci    st->Body()->Check(checker);
21833af6ab5fSopenharmony_ci
21843af6ab5fSopenharmony_ci    checker->Context().ExitLoop(smartCasts, clearFlag, st);
21853af6ab5fSopenharmony_ci    return nullptr;
21863af6ab5fSopenharmony_ci}
21873af6ab5fSopenharmony_ci
21883af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::IfStatement *st) const
21893af6ab5fSopenharmony_ci{
21903af6ab5fSopenharmony_ci    ETSChecker *const checker = GetETSChecker();
21913af6ab5fSopenharmony_ci
21923af6ab5fSopenharmony_ci    SmartCastArray smartCasts = checker->Context().EnterTestExpression();
21933af6ab5fSopenharmony_ci    checker->CheckTruthinessOfType(st->Test());
21943af6ab5fSopenharmony_ci    SmartCastTypes testedTypes = checker->Context().ExitTestExpression();
21953af6ab5fSopenharmony_ci    if (testedTypes.has_value()) {
21963af6ab5fSopenharmony_ci        for (auto [variable, consequentType, _] : *testedTypes) {
21973af6ab5fSopenharmony_ci            checker->ApplySmartCast(variable, consequentType);
21983af6ab5fSopenharmony_ci        }
21993af6ab5fSopenharmony_ci    }
22003af6ab5fSopenharmony_ci
22013af6ab5fSopenharmony_ci    checker->Context().EnterPath();
22023af6ab5fSopenharmony_ci    st->Consequent()->Check(checker);
22033af6ab5fSopenharmony_ci    bool const consequentTerminated = checker->Context().ExitPath();
22043af6ab5fSopenharmony_ci    SmartCastArray consequentSmartCasts = checker->Context().CloneSmartCasts();
22053af6ab5fSopenharmony_ci
22063af6ab5fSopenharmony_ci    // Restore smart casts to initial state.
22073af6ab5fSopenharmony_ci    checker->Context().RestoreSmartCasts(smartCasts);
22083af6ab5fSopenharmony_ci    //  Apply the alternate smart casts
22093af6ab5fSopenharmony_ci    if (testedTypes.has_value()) {
22103af6ab5fSopenharmony_ci        for (auto [variable, _, alternateType] : *testedTypes) {
22113af6ab5fSopenharmony_ci            checker->ApplySmartCast(variable, alternateType);
22123af6ab5fSopenharmony_ci        }
22133af6ab5fSopenharmony_ci    }
22143af6ab5fSopenharmony_ci
22153af6ab5fSopenharmony_ci    if (st->Alternate() != nullptr) {
22163af6ab5fSopenharmony_ci        checker->Context().EnterPath();
22173af6ab5fSopenharmony_ci        st->Alternate()->Check(checker);
22183af6ab5fSopenharmony_ci        bool const alternateTerminated = checker->Context().ExitPath();
22193af6ab5fSopenharmony_ci        if (alternateTerminated) {
22203af6ab5fSopenharmony_ci            if (!consequentTerminated) {
22213af6ab5fSopenharmony_ci                // Here we need to restore types from consequent if block.
22223af6ab5fSopenharmony_ci                checker->Context().RestoreSmartCasts(consequentSmartCasts);
22233af6ab5fSopenharmony_ci            } else {
22243af6ab5fSopenharmony_ci                // Here we need to restore initial smart types.
22253af6ab5fSopenharmony_ci                checker->Context().RestoreSmartCasts(smartCasts);
22263af6ab5fSopenharmony_ci            }
22273af6ab5fSopenharmony_ci        } else if (!consequentTerminated) {
22283af6ab5fSopenharmony_ci            // Here we need to combine types from consequent and alternate if blocks.
22293af6ab5fSopenharmony_ci            checker->Context().CombineSmartCasts(consequentSmartCasts);
22303af6ab5fSopenharmony_ci        }
22313af6ab5fSopenharmony_ci    } else {
22323af6ab5fSopenharmony_ci        if (!consequentTerminated) {
22333af6ab5fSopenharmony_ci            // Here we need to combine types from consequent if block and initial.
22343af6ab5fSopenharmony_ci            checker->Context().CombineSmartCasts(consequentSmartCasts);
22353af6ab5fSopenharmony_ci        }
22363af6ab5fSopenharmony_ci    }
22373af6ab5fSopenharmony_ci
22383af6ab5fSopenharmony_ci    return nullptr;
22393af6ab5fSopenharmony_ci}
22403af6ab5fSopenharmony_ci
22413af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::LabelledStatement *st) const
22423af6ab5fSopenharmony_ci{
22433af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
22443af6ab5fSopenharmony_ci    st->body_->Check(checker);
22453af6ab5fSopenharmony_ci    return nullptr;
22463af6ab5fSopenharmony_ci}
22473af6ab5fSopenharmony_ci
22483af6ab5fSopenharmony_cibool ETSAnalyzer::CheckInferredFunctionReturnType(ir::ReturnStatement *st, ir::ScriptFunction *containingFunc,
22493af6ab5fSopenharmony_ci                                                  checker::Type *&funcReturnType, ir::TypeNode *returnTypeAnnotation,
22503af6ab5fSopenharmony_ci                                                  ETSChecker *checker) const
22513af6ab5fSopenharmony_ci{
22523af6ab5fSopenharmony_ci    funcReturnType = returnTypeAnnotation->GetType(checker);
22533af6ab5fSopenharmony_ci    if (returnTypeAnnotation->IsTSThisType() && (st->Argument() == nullptr || !st->Argument()->IsThisExpression())) {
22543af6ab5fSopenharmony_ci        checker->LogTypeError("The only allowed return value is 'this' if the method's return type is the 'this' type",
22553af6ab5fSopenharmony_ci                              st->Start());
22563af6ab5fSopenharmony_ci        return false;
22573af6ab5fSopenharmony_ci    }
22583af6ab5fSopenharmony_ci
22593af6ab5fSopenharmony_ci    // Case when function's return type is defined explicitly:
22603af6ab5fSopenharmony_ci
22613af6ab5fSopenharmony_ci    if (st->argument_ == nullptr) {
22623af6ab5fSopenharmony_ci        if (!funcReturnType->IsETSVoidType() && funcReturnType != checker->GlobalVoidType() &&
22633af6ab5fSopenharmony_ci            !funcReturnType->IsETSAsyncFuncReturnType()) {
22643af6ab5fSopenharmony_ci            checker->LogTypeError("Missing return value.", st->Start());
22653af6ab5fSopenharmony_ci            return false;
22663af6ab5fSopenharmony_ci        }
22673af6ab5fSopenharmony_ci        funcReturnType = checker->GlobalVoidType();
22683af6ab5fSopenharmony_ci    } else {
22693af6ab5fSopenharmony_ci        const auto name = containingFunc->Scope()->InternalName().Mutf8();
22703af6ab5fSopenharmony_ci        if (!CheckArgumentVoidType(funcReturnType, checker, name, st)) {
22713af6ab5fSopenharmony_ci            return false;
22723af6ab5fSopenharmony_ci        }
22733af6ab5fSopenharmony_ci
22743af6ab5fSopenharmony_ci        if (st->argument_->IsObjectExpression()) {
22753af6ab5fSopenharmony_ci            st->argument_->AsObjectExpression()->SetPreferredType(funcReturnType);
22763af6ab5fSopenharmony_ci        }
22773af6ab5fSopenharmony_ci        if (st->argument_->IsMemberExpression()) {
22783af6ab5fSopenharmony_ci            checker->SetArrayPreferredTypeForNestedMemberExpressions(st->argument_->AsMemberExpression(),
22793af6ab5fSopenharmony_ci                                                                     funcReturnType);
22803af6ab5fSopenharmony_ci        }
22813af6ab5fSopenharmony_ci
22823af6ab5fSopenharmony_ci        if (st->argument_->IsArrayExpression()) {
22833af6ab5fSopenharmony_ci            st->argument_->AsArrayExpression()->SetPreferredType(funcReturnType);
22843af6ab5fSopenharmony_ci        }
22853af6ab5fSopenharmony_ci
22863af6ab5fSopenharmony_ci        checker::Type *argumentType = st->argument_->Check(checker);
22873af6ab5fSopenharmony_ci        return CheckReturnType(checker, funcReturnType, argumentType, st->argument_, containingFunc->IsAsyncFunc());
22883af6ab5fSopenharmony_ci    }
22893af6ab5fSopenharmony_ci    return true;
22903af6ab5fSopenharmony_ci}
22913af6ab5fSopenharmony_ci
22923af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::GetFunctionReturnType(ir::ReturnStatement *st, ir::ScriptFunction *containingFunc) const
22933af6ab5fSopenharmony_ci{
22943af6ab5fSopenharmony_ci    ASSERT(containingFunc->ReturnTypeAnnotation() != nullptr || containingFunc->Signature()->ReturnType() != nullptr);
22953af6ab5fSopenharmony_ci
22963af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
22973af6ab5fSopenharmony_ci    checker::Type *funcReturnType = nullptr;
22983af6ab5fSopenharmony_ci
22993af6ab5fSopenharmony_ci    if (auto *const returnTypeAnnotation = containingFunc->ReturnTypeAnnotation(); returnTypeAnnotation != nullptr) {
23003af6ab5fSopenharmony_ci        if (!CheckInferredFunctionReturnType(st, containingFunc, funcReturnType, returnTypeAnnotation, checker)) {
23013af6ab5fSopenharmony_ci            return checker->GlobalTypeError();
23023af6ab5fSopenharmony_ci        }
23033af6ab5fSopenharmony_ci    } else {
23043af6ab5fSopenharmony_ci        //  Case when function's return type should be inferred from return statement(s):
23053af6ab5fSopenharmony_ci        if (containingFunc->Signature()->HasSignatureFlag(checker::SignatureFlags::NEED_RETURN_TYPE)) {
23063af6ab5fSopenharmony_ci            InferReturnType(checker, containingFunc, funcReturnType,
23073af6ab5fSopenharmony_ci                            st->argument_);  // This removes the NEED_RETURN_TYPE flag, so only the first return
23083af6ab5fSopenharmony_ci                                             // statement going to land here...
23093af6ab5fSopenharmony_ci        } else {
23103af6ab5fSopenharmony_ci            //  All subsequent return statements:
23113af6ab5fSopenharmony_ci            ProcessReturnStatements(checker, containingFunc, funcReturnType, st,
23123af6ab5fSopenharmony_ci                                    st->argument_);  // and the remaining return statements will get processed here.
23133af6ab5fSopenharmony_ci        }
23143af6ab5fSopenharmony_ci    }
23153af6ab5fSopenharmony_ci
23163af6ab5fSopenharmony_ci    if ((st->argument_ != nullptr) && st->argument_->IsArrayExpression() && funcReturnType->IsArrayType()) {
23173af6ab5fSopenharmony_ci        checker->ModifyPreferredType(st->argument_->AsArrayExpression(), funcReturnType);
23183af6ab5fSopenharmony_ci        st->argument_->Check(checker);
23193af6ab5fSopenharmony_ci    }
23203af6ab5fSopenharmony_ci
23213af6ab5fSopenharmony_ci    return funcReturnType;
23223af6ab5fSopenharmony_ci}
23233af6ab5fSopenharmony_ci
23243af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ReturnStatement *st) const
23253af6ab5fSopenharmony_ci{
23263af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
23273af6ab5fSopenharmony_ci
23283af6ab5fSopenharmony_ci    ir::AstNode *ancestor = util::Helpers::FindAncestorGivenByType(st, ir::AstNodeType::SCRIPT_FUNCTION);
23293af6ab5fSopenharmony_ci    ASSERT(ancestor && ancestor->IsScriptFunction());
23303af6ab5fSopenharmony_ci    auto *containingFunc = ancestor->AsScriptFunction();
23313af6ab5fSopenharmony_ci
23323af6ab5fSopenharmony_ci    checker->AddStatus(CheckerStatus::MEET_RETURN);
23333af6ab5fSopenharmony_ci
23343af6ab5fSopenharmony_ci    if (containingFunc->IsConstructor()) {
23353af6ab5fSopenharmony_ci        if (st->argument_ != nullptr) {
23363af6ab5fSopenharmony_ci            checker->LogTypeError("Return statement with expression isn't allowed in constructor.", st->Start());
23373af6ab5fSopenharmony_ci            return checker->GlobalTypeError();
23383af6ab5fSopenharmony_ci        }
23393af6ab5fSopenharmony_ci        return nullptr;
23403af6ab5fSopenharmony_ci    }
23413af6ab5fSopenharmony_ci
23423af6ab5fSopenharmony_ci    st->returnType_ = GetFunctionReturnType(st, containingFunc);
23433af6ab5fSopenharmony_ci
23443af6ab5fSopenharmony_ci    if (containingFunc->ReturnTypeAnnotation() == nullptr) {
23453af6ab5fSopenharmony_ci        containingFunc->AddReturnStatement(st);
23463af6ab5fSopenharmony_ci    }
23473af6ab5fSopenharmony_ci
23483af6ab5fSopenharmony_ci    return nullptr;
23493af6ab5fSopenharmony_ci}
23503af6ab5fSopenharmony_ci
23513af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::SwitchStatement *st) const
23523af6ab5fSopenharmony_ci{
23533af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
23543af6ab5fSopenharmony_ci    checker::ScopeContext scopeCtx(checker, st->Scope());
23553af6ab5fSopenharmony_ci    checker::SavedTypeRelationFlagsContext savedTypeRelationFlagCtx(checker->Relation(),
23563af6ab5fSopenharmony_ci                                                                    checker::TypeRelationFlag::NONE);
23573af6ab5fSopenharmony_ci
23583af6ab5fSopenharmony_ci    auto *comparedExprType = checker->CheckSwitchDiscriminant(st->Discriminant());
23593af6ab5fSopenharmony_ci    auto unboxedDiscType = (st->Discriminant()->GetBoxingUnboxingFlags() & ir::BoxingUnboxingFlags::UNBOXING_FLAG) != 0U
23603af6ab5fSopenharmony_ci                               ? checker->ETSBuiltinTypeAsPrimitiveType(comparedExprType)
23613af6ab5fSopenharmony_ci                               : comparedExprType;
23623af6ab5fSopenharmony_ci
23633af6ab5fSopenharmony_ci    SmartCastArray smartCasts = checker->Context().CloneSmartCasts();
23643af6ab5fSopenharmony_ci    bool hasDefaultCase = false;
23653af6ab5fSopenharmony_ci
23663af6ab5fSopenharmony_ci    for (auto &it : st->Cases()) {
23673af6ab5fSopenharmony_ci        checker->Context().EnterPath();
23683af6ab5fSopenharmony_ci        it->CheckAndTestCase(checker, comparedExprType, unboxedDiscType, st->Discriminant(), hasDefaultCase);
23693af6ab5fSopenharmony_ci        bool const caseTerminated = checker->Context().ExitPath();
23703af6ab5fSopenharmony_ci
23713af6ab5fSopenharmony_ci        if (it != st->Cases().back()) {
23723af6ab5fSopenharmony_ci            if (!caseTerminated) {
23733af6ab5fSopenharmony_ci                checker->Context().CombineSmartCasts(smartCasts);
23743af6ab5fSopenharmony_ci            } else {
23753af6ab5fSopenharmony_ci                checker->Context().RestoreSmartCasts(smartCasts);
23763af6ab5fSopenharmony_ci            }
23773af6ab5fSopenharmony_ci        } else {
23783af6ab5fSopenharmony_ci            if (!caseTerminated) {
23793af6ab5fSopenharmony_ci                //  if the recent switch case isn't terminated in any way, copy actual smart casts to the array of
23803af6ab5fSopenharmony_ci                //  smart casts for the other case blocks so that it can be processed in unified way
23813af6ab5fSopenharmony_ci                checker->Context().AddBreakSmartCasts(st, checker->Context().CloneSmartCasts());
23823af6ab5fSopenharmony_ci            }
23833af6ab5fSopenharmony_ci            checker->Context().ClearSmartCasts();
23843af6ab5fSopenharmony_ci        }
23853af6ab5fSopenharmony_ci    }
23863af6ab5fSopenharmony_ci
23873af6ab5fSopenharmony_ci    // If default case is absent initial smart casts should be also applied here
23883af6ab5fSopenharmony_ci    if (!hasDefaultCase) {
23893af6ab5fSopenharmony_ci        checker->Context().AddBreakSmartCasts(st, std::move(smartCasts));
23903af6ab5fSopenharmony_ci    }
23913af6ab5fSopenharmony_ci
23923af6ab5fSopenharmony_ci    // Combine smart casts from all [non-terminated] case blocks with 'break'
23933af6ab5fSopenharmony_ci    checker->Context().CombineBreakSmartCasts(st);
23943af6ab5fSopenharmony_ci
23953af6ab5fSopenharmony_ci    checker->CheckForSameSwitchCases(st->Cases());
23963af6ab5fSopenharmony_ci    return nullptr;
23973af6ab5fSopenharmony_ci}
23983af6ab5fSopenharmony_ci
23993af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::ThrowStatement *st) const
24003af6ab5fSopenharmony_ci{
24013af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
24023af6ab5fSopenharmony_ci    auto *argType = st->argument_->Check(checker);
24033af6ab5fSopenharmony_ci    checker->CheckExceptionOrErrorType(argType, st->Start());
24043af6ab5fSopenharmony_ci
24053af6ab5fSopenharmony_ci    if (checker->Relation()->IsAssignableTo(argType, checker->GlobalBuiltinExceptionType())) {
24063af6ab5fSopenharmony_ci        checker->CheckThrowingStatements(st);
24073af6ab5fSopenharmony_ci    }
24083af6ab5fSopenharmony_ci
24093af6ab5fSopenharmony_ci    checker->AddStatus(CheckerStatus::MEET_THROW);
24103af6ab5fSopenharmony_ci    return nullptr;
24113af6ab5fSopenharmony_ci}
24123af6ab5fSopenharmony_ci
24133af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::TryStatement *st) const
24143af6ab5fSopenharmony_ci{
24153af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
24163af6ab5fSopenharmony_ci    std::vector<checker::ETSObjectType *> exceptions {};
24173af6ab5fSopenharmony_ci
24183af6ab5fSopenharmony_ci    std::vector<SmartCastArray> casts {};
24193af6ab5fSopenharmony_ci    auto smartCasts = checker->Context().CheckTryBlock(*st->Block());
24203af6ab5fSopenharmony_ci    st->Block()->Check(checker);
24213af6ab5fSopenharmony_ci
24223af6ab5fSopenharmony_ci    bool defaultCatchFound = false;
24233af6ab5fSopenharmony_ci    for (auto *catchClause : st->CatchClauses()) {
24243af6ab5fSopenharmony_ci        if (defaultCatchFound) {
24253af6ab5fSopenharmony_ci            checker->LogTypeError("Default catch clause should be the last in the try statement", catchClause->Start());
24263af6ab5fSopenharmony_ci            return checker->GlobalTypeError();
24273af6ab5fSopenharmony_ci        }
24283af6ab5fSopenharmony_ci
24293af6ab5fSopenharmony_ci        checker->Context().RestoreSmartCasts(smartCasts);
24303af6ab5fSopenharmony_ci
24313af6ab5fSopenharmony_ci        if (auto const exceptionType = catchClause->Check(checker);
24323af6ab5fSopenharmony_ci            exceptionType != nullptr && catchClause->Param() != nullptr) {
24333af6ab5fSopenharmony_ci            auto *clauseType = exceptionType->AsETSObjectType();
24343af6ab5fSopenharmony_ci            checker->CheckExceptionClauseType(exceptions, catchClause, clauseType);
24353af6ab5fSopenharmony_ci            exceptions.emplace_back(clauseType);
24363af6ab5fSopenharmony_ci        }
24373af6ab5fSopenharmony_ci
24383af6ab5fSopenharmony_ci        defaultCatchFound = catchClause->IsDefaultCatchClause();
24393af6ab5fSopenharmony_ci
24403af6ab5fSopenharmony_ci        casts.emplace_back(checker->Context().CloneSmartCasts());
24413af6ab5fSopenharmony_ci    }
24423af6ab5fSopenharmony_ci
24433af6ab5fSopenharmony_ci    checker->Context().RestoreSmartCasts(smartCasts);
24443af6ab5fSopenharmony_ci    if (!casts.empty()) {
24453af6ab5fSopenharmony_ci        for (auto const &cast : casts) {
24463af6ab5fSopenharmony_ci            checker->Context().CombineSmartCasts(cast);
24473af6ab5fSopenharmony_ci        }
24483af6ab5fSopenharmony_ci    }
24493af6ab5fSopenharmony_ci
24503af6ab5fSopenharmony_ci    if (st->HasFinalizer()) {
24513af6ab5fSopenharmony_ci        st->FinallyBlock()->Check(checker);
24523af6ab5fSopenharmony_ci    }
24533af6ab5fSopenharmony_ci
24543af6ab5fSopenharmony_ci    return nullptr;
24553af6ab5fSopenharmony_ci}
24563af6ab5fSopenharmony_ci
24573af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::VariableDeclarator *st) const
24583af6ab5fSopenharmony_ci{
24593af6ab5fSopenharmony_ci    if (st->TsTypeOrError() != nullptr) {
24603af6ab5fSopenharmony_ci        return st->TsTypeOrError();
24613af6ab5fSopenharmony_ci    }
24623af6ab5fSopenharmony_ci
24633af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
24643af6ab5fSopenharmony_ci    ASSERT(st->Id()->IsIdentifier());
24653af6ab5fSopenharmony_ci    auto *const ident = st->Id()->AsIdentifier();
24663af6ab5fSopenharmony_ci    ir::ModifierFlags flags = ir::ModifierFlags::NONE;
24673af6ab5fSopenharmony_ci
24683af6ab5fSopenharmony_ci    if (ident->Parent()->Parent()->AsVariableDeclaration()->Kind() ==
24693af6ab5fSopenharmony_ci        ir::VariableDeclaration::VariableDeclarationKind::CONST) {
24703af6ab5fSopenharmony_ci        flags |= ir::ModifierFlags::CONST;
24713af6ab5fSopenharmony_ci    }
24723af6ab5fSopenharmony_ci
24733af6ab5fSopenharmony_ci    if (ident->IsOptionalDeclaration()) {
24743af6ab5fSopenharmony_ci        flags |= ir::ModifierFlags::OPTIONAL;
24753af6ab5fSopenharmony_ci    }
24763af6ab5fSopenharmony_ci
24773af6ab5fSopenharmony_ci    auto *const variableType = checker->CheckVariableDeclaration(ident, ident->TypeAnnotation(), st->Init(), flags);
24783af6ab5fSopenharmony_ci    auto *smartType = variableType;
24793af6ab5fSopenharmony_ci
24803af6ab5fSopenharmony_ci    //  Now try to define the actual type of Identifier so that smart cast can be used in further checker processing
24813af6ab5fSopenharmony_ci    //  NOTE: T_S and K_o_t_l_i_n don't act in such way, but we can try - why not? :)
24823af6ab5fSopenharmony_ci    if (auto *const initType = st->Init() != nullptr ? st->Init()->TsTypeOrError() : nullptr; initType != nullptr) {
24833af6ab5fSopenharmony_ci        smartType = checker->ResolveSmartType(initType, variableType);
24843af6ab5fSopenharmony_ci        //  Set smart type for identifier if it differs from annotated type
24853af6ab5fSopenharmony_ci        //  Top-level and captured variables are not processed here!
24863af6ab5fSopenharmony_ci        if (!checker->Relation()->IsIdenticalTo(variableType, smartType)) {
24873af6ab5fSopenharmony_ci            ident->SetTsType(smartType);
24883af6ab5fSopenharmony_ci            checker->Context().SetSmartCast(ident->Variable(), smartType);
24893af6ab5fSopenharmony_ci        }
24903af6ab5fSopenharmony_ci    }
24913af6ab5fSopenharmony_ci
24923af6ab5fSopenharmony_ci    st->SetTsType(smartType);
24933af6ab5fSopenharmony_ci    return smartType;
24943af6ab5fSopenharmony_ci}
24953af6ab5fSopenharmony_ci
24963af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::VariableDeclaration *st) const
24973af6ab5fSopenharmony_ci{
24983af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
24993af6ab5fSopenharmony_ci    for (auto *it : st->Declarators()) {
25003af6ab5fSopenharmony_ci        it->Check(checker);
25013af6ab5fSopenharmony_ci    }
25023af6ab5fSopenharmony_ci
25033af6ab5fSopenharmony_ci    return nullptr;
25043af6ab5fSopenharmony_ci}
25053af6ab5fSopenharmony_ci
25063af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::WhileStatement *st) const
25073af6ab5fSopenharmony_ci{
25083af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
25093af6ab5fSopenharmony_ci    checker::ScopeContext scopeCtx(checker, st->Scope());
25103af6ab5fSopenharmony_ci
25113af6ab5fSopenharmony_ci    //  NOTE: Smart casts are not processed correctly within the loops now, thus clear them at this point.
25123af6ab5fSopenharmony_ci    auto [smartCasts, clearFlag] = checker->Context().EnterLoop(*st);
25133af6ab5fSopenharmony_ci
25143af6ab5fSopenharmony_ci    checker->CheckTruthinessOfType(st->Test());
25153af6ab5fSopenharmony_ci    st->Body()->Check(checker);
25163af6ab5fSopenharmony_ci
25173af6ab5fSopenharmony_ci    checker->Context().ExitLoop(smartCasts, clearFlag, st);
25183af6ab5fSopenharmony_ci    return nullptr;
25193af6ab5fSopenharmony_ci}
25203af6ab5fSopenharmony_ci
25213af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::TSArrayType *node) const
25223af6ab5fSopenharmony_ci{
25233af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
25243af6ab5fSopenharmony_ci    node->elementType_->Check(checker);
25253af6ab5fSopenharmony_ci    node->SetTsType(node->GetType(checker));
25263af6ab5fSopenharmony_ci
25273af6ab5fSopenharmony_ci    const auto arrayType = node->TsType()->AsETSArrayType();
25283af6ab5fSopenharmony_ci    checker->CreateBuiltinArraySignature(arrayType, arrayType->Rank());
25293af6ab5fSopenharmony_ci    return nullptr;
25303af6ab5fSopenharmony_ci}
25313af6ab5fSopenharmony_ci
25323af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::TSAsExpression *expr) const
25333af6ab5fSopenharmony_ci{
25343af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
25353af6ab5fSopenharmony_ci
25363af6ab5fSopenharmony_ci    if (expr->TsTypeOrError() != nullptr) {
25373af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
25383af6ab5fSopenharmony_ci    }
25393af6ab5fSopenharmony_ci
25403af6ab5fSopenharmony_ci    auto *const targetType = expr->TypeAnnotation()->AsTypeNode()->GetType(checker);
25413af6ab5fSopenharmony_ci    // Object expression requires that its type be set by the context before checking. in this case, the target type
25423af6ab5fSopenharmony_ci    // provides that context.
25433af6ab5fSopenharmony_ci    if (expr->Expr()->IsObjectExpression()) {
25443af6ab5fSopenharmony_ci        expr->Expr()->AsObjectExpression()->SetPreferredType(targetType);
25453af6ab5fSopenharmony_ci    }
25463af6ab5fSopenharmony_ci
25473af6ab5fSopenharmony_ci    if (expr->Expr()->IsArrayExpression()) {
25483af6ab5fSopenharmony_ci        expr->Expr()->AsArrayExpression()->SetPreferredType(targetType);
25493af6ab5fSopenharmony_ci    }
25503af6ab5fSopenharmony_ci
25513af6ab5fSopenharmony_ci    auto *const sourceType = expr->Expr()->Check(checker);
25523af6ab5fSopenharmony_ci    if (sourceType->IsTypeError()) {
25533af6ab5fSopenharmony_ci        expr->SetTsType(checker->GlobalTypeError());
25543af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
25553af6ab5fSopenharmony_ci    }
25563af6ab5fSopenharmony_ci
25573af6ab5fSopenharmony_ci    if (targetType->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE) && sourceType->IsETSReferenceType()) {
25583af6ab5fSopenharmony_ci        auto *const boxedTargetType = checker->PrimitiveTypeAsETSBuiltinType(targetType);
25593af6ab5fSopenharmony_ci        if (!checker->Relation()->IsIdenticalTo(sourceType, boxedTargetType)) {
25603af6ab5fSopenharmony_ci            expr->Expr()->AddAstNodeFlags(ir::AstNodeFlags::CHECKCAST);
25613af6ab5fSopenharmony_ci        }
25623af6ab5fSopenharmony_ci    }
25633af6ab5fSopenharmony_ci
25643af6ab5fSopenharmony_ci    if (sourceType->DefinitelyETSNullish() && !targetType->PossiblyETSNullish()) {
25653af6ab5fSopenharmony_ci        checker->LogTypeError("Cannot cast 'null' or 'undefined' to non-nullish type.", expr->Expr()->Start());
25663af6ab5fSopenharmony_ci        expr->SetTsType(checker->GlobalTypeError());
25673af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
25683af6ab5fSopenharmony_ci    }
25693af6ab5fSopenharmony_ci
25703af6ab5fSopenharmony_ci    const checker::CastingContext ctx(
25713af6ab5fSopenharmony_ci        checker->Relation(),
25723af6ab5fSopenharmony_ci        std::initializer_list<TypeErrorMessageElement> {"Cannot cast type '", sourceType, "' to '", targetType, "'"},
25733af6ab5fSopenharmony_ci        checker::CastingContext::ConstructorData {expr->Expr(), sourceType, targetType, expr->Expr()->Start()});
25743af6ab5fSopenharmony_ci
25753af6ab5fSopenharmony_ci    if (sourceType->IsETSDynamicType() && targetType->IsLambdaObject()) {
25763af6ab5fSopenharmony_ci        // NOTE: itrubachev. change targetType to created lambdaobject type.
25773af6ab5fSopenharmony_ci        // Now targetType is not changed, only construct signature is added to it
25783af6ab5fSopenharmony_ci        checker->BuildLambdaObjectClass(targetType->AsETSObjectType(),
25793af6ab5fSopenharmony_ci                                        expr->TypeAnnotation()->AsETSFunctionType()->ReturnType());
25803af6ab5fSopenharmony_ci    }
25813af6ab5fSopenharmony_ci    expr->isUncheckedCast_ = ctx.UncheckedCast();
25823af6ab5fSopenharmony_ci
25833af6ab5fSopenharmony_ci    // Make sure the array type symbol gets created for the assembler to be able to emit checkcast.
25843af6ab5fSopenharmony_ci    // Because it might not exist, if this particular array type was never created explicitly.
25853af6ab5fSopenharmony_ci    if (!expr->isUncheckedCast_ && targetType->IsETSArrayType()) {
25863af6ab5fSopenharmony_ci        auto *const targetArrayType = targetType->AsETSArrayType();
25873af6ab5fSopenharmony_ci        checker->CreateBuiltinArraySignature(targetArrayType, targetArrayType->Rank());
25883af6ab5fSopenharmony_ci    }
25893af6ab5fSopenharmony_ci
25903af6ab5fSopenharmony_ci    if (targetType == checker->GetGlobalTypesHolder()->GlobalBuiltinNeverType()) {
25913af6ab5fSopenharmony_ci        checker->LogTypeError("Cast to 'never' is prohibited", expr->Start());
25923af6ab5fSopenharmony_ci        expr->SetTsType(checker->GlobalTypeError());
25933af6ab5fSopenharmony_ci        return expr->TsTypeOrError();
25943af6ab5fSopenharmony_ci    }
25953af6ab5fSopenharmony_ci
25963af6ab5fSopenharmony_ci    checker->ComputeApparentType(targetType);
25973af6ab5fSopenharmony_ci    expr->SetTsType(targetType);
25983af6ab5fSopenharmony_ci    return expr->TsType();
25993af6ab5fSopenharmony_ci}
26003af6ab5fSopenharmony_ci
26013af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::TSEnumDeclaration *st) const
26023af6ab5fSopenharmony_ci{
26033af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
26043af6ab5fSopenharmony_ci    varbinder::Variable *enumVar = st->Key()->Variable();
26053af6ab5fSopenharmony_ci    ASSERT(enumVar != nullptr);
26063af6ab5fSopenharmony_ci
26073af6ab5fSopenharmony_ci    if (enumVar->TsTypeOrError() == nullptr) {
26083af6ab5fSopenharmony_ci        checker::Type *etsEnumType = nullptr;
26093af6ab5fSopenharmony_ci        Check(st->BoxedClass());
26103af6ab5fSopenharmony_ci        if (auto *const itemInit = st->Members().front()->AsTSEnumMember()->Init(); itemInit->IsNumberLiteral()) {
26113af6ab5fSopenharmony_ci            etsEnumType = checker->CreateEnumIntTypeFromEnumDeclaration(st);
26123af6ab5fSopenharmony_ci        } else if (itemInit->IsStringLiteral()) {
26133af6ab5fSopenharmony_ci            etsEnumType = checker->CreateEnumStringTypeFromEnumDeclaration(st);
26143af6ab5fSopenharmony_ci        } else {
26153af6ab5fSopenharmony_ci            checker->LogTypeError("Invalid enumeration value type.", st->Start());
26163af6ab5fSopenharmony_ci            st->SetTsType(checker->GlobalTypeError());
26173af6ab5fSopenharmony_ci            return st->TsTypeOrError();
26183af6ab5fSopenharmony_ci        }
26193af6ab5fSopenharmony_ci        st->SetTsType(etsEnumType);
26203af6ab5fSopenharmony_ci        etsEnumType->SetVariable(enumVar);
26213af6ab5fSopenharmony_ci        enumVar->SetTsType(etsEnumType);
26223af6ab5fSopenharmony_ci    } else if (st->TsTypeOrError() == nullptr) {
26233af6ab5fSopenharmony_ci        st->SetTsType(enumVar->TsTypeOrError());
26243af6ab5fSopenharmony_ci    }
26253af6ab5fSopenharmony_ci
26263af6ab5fSopenharmony_ci    return st->TsTypeOrError();
26273af6ab5fSopenharmony_ci}
26283af6ab5fSopenharmony_ci
26293af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::TSInterfaceDeclaration *st) const
26303af6ab5fSopenharmony_ci{
26313af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
26323af6ab5fSopenharmony_ci
26333af6ab5fSopenharmony_ci    checker::ETSObjectType *interfaceType {};
26343af6ab5fSopenharmony_ci
26353af6ab5fSopenharmony_ci    if (st->TsTypeOrError() != nullptr) {
26363af6ab5fSopenharmony_ci        return st->TsTypeOrError();
26373af6ab5fSopenharmony_ci    }
26383af6ab5fSopenharmony_ci
26393af6ab5fSopenharmony_ci    interfaceType = checker->BuildBasicInterfaceProperties(st);
26403af6ab5fSopenharmony_ci    ASSERT(interfaceType != nullptr);
26413af6ab5fSopenharmony_ci    interfaceType->SetSuperType(checker->GlobalETSObjectType());
26423af6ab5fSopenharmony_ci    checker->CheckInvokeMethodsLegitimacy(interfaceType);
26433af6ab5fSopenharmony_ci    st->SetTsType(interfaceType);
26443af6ab5fSopenharmony_ci
26453af6ab5fSopenharmony_ci    checker::ScopeContext scopeCtx(checker, st->Scope());
26463af6ab5fSopenharmony_ci    auto savedContext = checker::SavedCheckerContext(checker, checker::CheckerStatus::IN_INTERFACE, interfaceType);
26473af6ab5fSopenharmony_ci
26483af6ab5fSopenharmony_ci    for (auto *it : st->Body()->Body()) {
26493af6ab5fSopenharmony_ci        it->Check(checker);
26503af6ab5fSopenharmony_ci    }
26513af6ab5fSopenharmony_ci
26523af6ab5fSopenharmony_ci    return nullptr;
26533af6ab5fSopenharmony_ci}
26543af6ab5fSopenharmony_ci
26553af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::TSNonNullExpression *expr) const
26563af6ab5fSopenharmony_ci{
26573af6ab5fSopenharmony_ci    if (expr->TsTypeOrError() == nullptr) {
26583af6ab5fSopenharmony_ci        ETSChecker *checker = GetETSChecker();
26593af6ab5fSopenharmony_ci        auto exprType = expr->expr_->Check(checker);
26603af6ab5fSopenharmony_ci        //  If the actual [smart] type is definitely 'null' or 'undefined' then probably CTE should be thrown.
26613af6ab5fSopenharmony_ci        //  Anyway we'll definitely obtain NullPointerException at runtime.
26623af6ab5fSopenharmony_ci        if (exprType->DefinitelyETSNullish()) {
26633af6ab5fSopenharmony_ci            checker->LogTypeError(
26643af6ab5fSopenharmony_ci                "Bad operand type, the operand of the non-nullish expression is 'null' or 'undefined'.",
26653af6ab5fSopenharmony_ci                expr->Expr()->Start());
26663af6ab5fSopenharmony_ci            expr->SetTsType(checker->GlobalTypeError());
26673af6ab5fSopenharmony_ci            return expr->TsTypeOrError();
26683af6ab5fSopenharmony_ci        }
26693af6ab5fSopenharmony_ci        expr->SetTsType(checker->GetNonNullishType(exprType));
26703af6ab5fSopenharmony_ci    }
26713af6ab5fSopenharmony_ci    expr->SetOriginalType(expr->TsType());
26723af6ab5fSopenharmony_ci    return expr->TsType();
26733af6ab5fSopenharmony_ci}
26743af6ab5fSopenharmony_ci
26753af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::TSQualifiedName *expr) const
26763af6ab5fSopenharmony_ci{
26773af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
26783af6ab5fSopenharmony_ci    checker::Type *baseType = expr->Left()->Check(checker);
26793af6ab5fSopenharmony_ci
26803af6ab5fSopenharmony_ci    if (baseType->IsETSObjectType()) {
26813af6ab5fSopenharmony_ci        auto importDecl = baseType->AsETSObjectType()->GetDeclNode()->Parent()->Parent();
26823af6ab5fSopenharmony_ci        // clang-format off
26833af6ab5fSopenharmony_ci        auto searchName =
26843af6ab5fSopenharmony_ci            importDecl->IsETSImportDeclaration()
26853af6ab5fSopenharmony_ci                ? checker->VarBinder()->AsETSBinder()->FindNameInAliasMap(
26863af6ab5fSopenharmony_ci                    importDecl->AsETSImportDeclaration()->ResolvedSource()->Str(), expr->Right()->Name())
26873af6ab5fSopenharmony_ci                : expr->Right()->Name();
26883af6ab5fSopenharmony_ci        // clang-format on
26893af6ab5fSopenharmony_ci        // NOTE (oeotvos) This should be done differently in the follow-up patch.
26903af6ab5fSopenharmony_ci        if (searchName.Empty()) {
26913af6ab5fSopenharmony_ci            searchName = expr->Right()->Name();
26923af6ab5fSopenharmony_ci        }
26933af6ab5fSopenharmony_ci        varbinder::Variable *prop =
26943af6ab5fSopenharmony_ci            baseType->AsETSObjectType()->GetProperty(searchName, checker::PropertySearchFlags::SEARCH_DECL);
26953af6ab5fSopenharmony_ci        // NOTE(dslynko): in debugger evaluation mode must lazily generate module's properties here.
26963af6ab5fSopenharmony_ci
26973af6ab5fSopenharmony_ci        if (prop == nullptr) {
26983af6ab5fSopenharmony_ci            checker->LogTypeError({"'", expr->Right()->Name(), "' type does not exist."}, expr->Right()->Start());
26993af6ab5fSopenharmony_ci            return checker->GlobalTypeError();
27003af6ab5fSopenharmony_ci        }
27013af6ab5fSopenharmony_ci
27023af6ab5fSopenharmony_ci        if (expr->Right()->Name().Is(searchName.Mutf8()) && prop->Declaration()->Node()->HasExportAlias()) {
27033af6ab5fSopenharmony_ci            checker->LogTypeError({"Cannot find imported element '", searchName, "' exported with alias"},
27043af6ab5fSopenharmony_ci                                  expr->Right()->Start());
27053af6ab5fSopenharmony_ci            return checker->GlobalTypeError();
27063af6ab5fSopenharmony_ci        }
27073af6ab5fSopenharmony_ci
27083af6ab5fSopenharmony_ci        expr->Right()->SetVariable(prop);
27093af6ab5fSopenharmony_ci        return checker->GetTypeOfVariable(prop);
27103af6ab5fSopenharmony_ci    }
27113af6ab5fSopenharmony_ci
27123af6ab5fSopenharmony_ci    checker->LogTypeError({"'", expr->Right()->Name(), "' type does not exist."}, expr->Right()->Start());
27133af6ab5fSopenharmony_ci    return checker->GlobalTypeError();
27143af6ab5fSopenharmony_ci}
27153af6ab5fSopenharmony_ci
27163af6ab5fSopenharmony_cichecker::Type *ETSAnalyzer::Check(ir::TSTypeAliasDeclaration *st) const
27173af6ab5fSopenharmony_ci{
27183af6ab5fSopenharmony_ci    ETSChecker *checker = GetETSChecker();
27193af6ab5fSopenharmony_ci    if (st->TypeParams() == nullptr) {
27203af6ab5fSopenharmony_ci        const checker::SavedTypeRelationFlagsContext savedFlagsCtx(
27213af6ab5fSopenharmony_ci            checker->Relation(), checker::TypeRelationFlag::NO_THROW_GENERIC_TYPEALIAS);
27223af6ab5fSopenharmony_ci
27233af6ab5fSopenharmony_ci        if (st->TypeAnnotation()->TsTypeOrError() == nullptr) {
27243af6ab5fSopenharmony_ci            st->TypeAnnotation()->Check(checker);
27253af6ab5fSopenharmony_ci        }
27263af6ab5fSopenharmony_ci
27273af6ab5fSopenharmony_ci        return nullptr;
27283af6ab5fSopenharmony_ci    }
27293af6ab5fSopenharmony_ci
27303af6ab5fSopenharmony_ci    if (st->TypeParameterTypes().empty()) {
27313af6ab5fSopenharmony_ci        auto [typeParamTypes, ok] = checker->CreateUnconstrainedTypeParameters(st->TypeParams());
27323af6ab5fSopenharmony_ci        st->SetTypeParameterTypes(std::move(typeParamTypes));
27333af6ab5fSopenharmony_ci        if (ok) {
27343af6ab5fSopenharmony_ci            checker->AssignTypeParameterConstraints(st->TypeParams());
27353af6ab5fSopenharmony_ci        }
27363af6ab5fSopenharmony_ci    }
27373af6ab5fSopenharmony_ci
27383af6ab5fSopenharmony_ci    for (auto *const param : st->TypeParams()->Params()) {
27393af6ab5fSopenharmony_ci        const auto *const res = st->TypeAnnotation()->FindChild([&param](const ir::AstNode *const node) {
27403af6ab5fSopenharmony_ci            if (!node->IsIdentifier()) {
27413af6ab5fSopenharmony_ci                return false;
27423af6ab5fSopenharmony_ci            }
27433af6ab5fSopenharmony_ci
27443af6ab5fSopenharmony_ci            return param->Name()->AsIdentifier()->Variable() == node->AsIdentifier()->Variable();
27453af6ab5fSopenharmony_ci        });
27463af6ab5fSopenharmony_ci
27473af6ab5fSopenharmony_ci        if (res == nullptr) {
27483af6ab5fSopenharmony_ci            checker->LogTypeError(
27493af6ab5fSopenharmony_ci                {"Type alias generic parameter '", param->Name()->Name(), "' is not used in type annotation"},
27503af6ab5fSopenharmony_ci                param->Start());
27513af6ab5fSopenharmony_ci            return checker->GlobalTypeError();
27523af6ab5fSopenharmony_ci        }
27533af6ab5fSopenharmony_ci    }
27543af6ab5fSopenharmony_ci
27553af6ab5fSopenharmony_ci    const checker::SavedTypeRelationFlagsContext savedFlagsCtx(checker->Relation(),
27563af6ab5fSopenharmony_ci                                                               checker::TypeRelationFlag::NO_THROW_GENERIC_TYPEALIAS);
27573af6ab5fSopenharmony_ci
27583af6ab5fSopenharmony_ci    if (st->TypeAnnotation()->TsTypeOrError() == nullptr) {
27593af6ab5fSopenharmony_ci        st->TypeAnnotation()->Check(checker);
27603af6ab5fSopenharmony_ci    }
27613af6ab5fSopenharmony_ci
27623af6ab5fSopenharmony_ci    return nullptr;
27633af6ab5fSopenharmony_ci}
27643af6ab5fSopenharmony_ci}  // namespace ark::es2panda::checker
2765