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([¶m](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