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 "ETSAnalyzerHelpers.h" 173af6ab5fSopenharmony_ci#include "checker/types/ets/etsAsyncFuncReturnType.h" 183af6ab5fSopenharmony_ci 193af6ab5fSopenharmony_cinamespace ark::es2panda::checker { 203af6ab5fSopenharmony_civoid CheckExtensionIsShadowedInCurrentClassOrInterface(checker::ETSChecker *checker, checker::ETSObjectType *objType, 213af6ab5fSopenharmony_ci ir::ScriptFunction *extensionFunc, checker::Signature *signature) 223af6ab5fSopenharmony_ci{ 233af6ab5fSopenharmony_ci const auto methodName = extensionFunc->Id()->Name(); 243af6ab5fSopenharmony_ci // Only check if there are class and interfaces' instance methods which would shadow instance extension method 253af6ab5fSopenharmony_ci auto *const variable = objType->GetOwnProperty<checker::PropertyType::INSTANCE_METHOD>(methodName); 263af6ab5fSopenharmony_ci if (variable == nullptr) { 273af6ab5fSopenharmony_ci return; 283af6ab5fSopenharmony_ci } 293af6ab5fSopenharmony_ci 303af6ab5fSopenharmony_ci const auto *const funcType = variable->TsType()->AsETSFunctionType(); 313af6ab5fSopenharmony_ci for (auto *funcSignature : funcType->CallSignatures()) { 323af6ab5fSopenharmony_ci signature->SetReturnType(funcSignature->ReturnType()); 333af6ab5fSopenharmony_ci if (!checker->Relation()->IsCompatibleTo(signature, funcSignature)) { 343af6ab5fSopenharmony_ci continue; 353af6ab5fSopenharmony_ci } 363af6ab5fSopenharmony_ci 373af6ab5fSopenharmony_ci checker->ReportWarning({"extension is shadowed by a instance member function '", funcType->Name(), 383af6ab5fSopenharmony_ci funcSignature, "' in class ", objType->Name()}, 393af6ab5fSopenharmony_ci extensionFunc->Body()->Start()); 403af6ab5fSopenharmony_ci return; 413af6ab5fSopenharmony_ci } 423af6ab5fSopenharmony_ci} 433af6ab5fSopenharmony_ci 443af6ab5fSopenharmony_civoid CheckExtensionIsShadowedByMethod(checker::ETSChecker *checker, checker::ETSObjectType *objType, 453af6ab5fSopenharmony_ci ir::ScriptFunction *extensionFunc, checker::Signature *signature) 463af6ab5fSopenharmony_ci{ 473af6ab5fSopenharmony_ci if (objType == nullptr) { 483af6ab5fSopenharmony_ci return; 493af6ab5fSopenharmony_ci } 503af6ab5fSopenharmony_ci 513af6ab5fSopenharmony_ci CheckExtensionIsShadowedInCurrentClassOrInterface(checker, objType, extensionFunc, signature); 523af6ab5fSopenharmony_ci 533af6ab5fSopenharmony_ci for (auto *interface : objType->Interfaces()) { 543af6ab5fSopenharmony_ci CheckExtensionIsShadowedByMethod(checker, interface, extensionFunc, signature); 553af6ab5fSopenharmony_ci } 563af6ab5fSopenharmony_ci 573af6ab5fSopenharmony_ci CheckExtensionIsShadowedByMethod(checker, objType->SuperType(), extensionFunc, signature); 583af6ab5fSopenharmony_ci} 593af6ab5fSopenharmony_ci 603af6ab5fSopenharmony_cistatic void ReplaceThisInExtensionMethod(checker::ETSChecker *checker, ir::ScriptFunction *extensionFunc) 613af6ab5fSopenharmony_ci{ 623af6ab5fSopenharmony_ci ASSERT(!extensionFunc->Params().empty()); 633af6ab5fSopenharmony_ci ASSERT(extensionFunc->Params()[0]->AsETSParameterExpression()->Ident()->Name() == 643af6ab5fSopenharmony_ci varbinder::TypedBinder::MANDATORY_PARAM_THIS); 653af6ab5fSopenharmony_ci auto thisVariable = extensionFunc->Params()[0]->Variable(); 663af6ab5fSopenharmony_ci extensionFunc->Body()->TransformChildrenRecursively( 673af6ab5fSopenharmony_ci [=](ir::AstNode *ast) { 683af6ab5fSopenharmony_ci if (ast->IsThisExpression()) { 693af6ab5fSopenharmony_ci auto *thisParam = checker->Allocator()->New<ir::Identifier>( 703af6ab5fSopenharmony_ci varbinder::TypedBinder::MANDATORY_PARAM_THIS, checker->Allocator()); 713af6ab5fSopenharmony_ci thisParam->SetParent(ast->Parent()); 723af6ab5fSopenharmony_ci thisParam->SetVariable(thisVariable); 733af6ab5fSopenharmony_ci return static_cast<ir::AstNode *>(thisParam); 743af6ab5fSopenharmony_ci } 753af6ab5fSopenharmony_ci return ast; 763af6ab5fSopenharmony_ci }, 773af6ab5fSopenharmony_ci "replace-this-in-extension-method"); 783af6ab5fSopenharmony_ci} 793af6ab5fSopenharmony_ci 803af6ab5fSopenharmony_civoid CheckExtensionMethod(checker::ETSChecker *checker, ir::ScriptFunction *extensionFunc, ir::MethodDefinition *node) 813af6ab5fSopenharmony_ci{ 823af6ab5fSopenharmony_ci auto *const classType = checker->GetApparentType(extensionFunc->Signature()->Params()[0]->TsType()); 833af6ab5fSopenharmony_ci if (!classType->IsETSObjectType() || 843af6ab5fSopenharmony_ci (!classType->AsETSObjectType()->HasObjectFlag(checker::ETSObjectFlags::CLASS) && 853af6ab5fSopenharmony_ci !classType->AsETSObjectType()->HasObjectFlag(checker::ETSObjectFlags::INTERFACE))) { 863af6ab5fSopenharmony_ci checker->LogTypeError("Extension function can only defined for class and interface type.", node->Start()); 873af6ab5fSopenharmony_ci } 883af6ab5fSopenharmony_ci if (classType->Variable()->Declaration()->Node()->IsClassDefinition() && 893af6ab5fSopenharmony_ci !classType->Variable()->Declaration()->Node()->AsClassDefinition()->IsClassDefinitionChecked()) { 903af6ab5fSopenharmony_ci classType->Variable()->Declaration()->Node()->Check(checker); 913af6ab5fSopenharmony_ci } 923af6ab5fSopenharmony_ci 933af6ab5fSopenharmony_ci // NOTE(gogabr): should be done in a lowering 943af6ab5fSopenharmony_ci ReplaceThisInExtensionMethod(checker, extensionFunc); 953af6ab5fSopenharmony_ci 963af6ab5fSopenharmony_ci checker::SignatureInfo *originalExtensionSigInfo = checker->Allocator()->New<checker::SignatureInfo>( 973af6ab5fSopenharmony_ci extensionFunc->Signature()->GetSignatureInfo(), checker->Allocator()); 983af6ab5fSopenharmony_ci originalExtensionSigInfo->minArgCount -= 1; 993af6ab5fSopenharmony_ci originalExtensionSigInfo->params.erase(originalExtensionSigInfo->params.begin()); 1003af6ab5fSopenharmony_ci checker::Signature *originalExtensionSigature = 1013af6ab5fSopenharmony_ci checker->CreateSignature(originalExtensionSigInfo, extensionFunc->Signature()->ReturnType(), extensionFunc); 1023af6ab5fSopenharmony_ci 1033af6ab5fSopenharmony_ci CheckExtensionIsShadowedByMethod(checker, classType->AsETSObjectType(), extensionFunc, originalExtensionSigature); 1043af6ab5fSopenharmony_ci} 1053af6ab5fSopenharmony_ci 1063af6ab5fSopenharmony_civoid DoBodyTypeChecking(ETSChecker *checker, ir::MethodDefinition *node, ir::ScriptFunction *scriptFunc) 1073af6ab5fSopenharmony_ci{ 1083af6ab5fSopenharmony_ci if (scriptFunc->HasBody() && (node->IsNative() || node->IsAbstract() || node->IsDeclare())) { 1093af6ab5fSopenharmony_ci checker->LogTypeError("Native, Abstract and Declare methods cannot have body.", scriptFunc->Body()->Start()); 1103af6ab5fSopenharmony_ci } 1113af6ab5fSopenharmony_ci 1123af6ab5fSopenharmony_ci if (!scriptFunc->IsAsyncFunc() && scriptFunc->HasBody() && 1133af6ab5fSopenharmony_ci (!scriptFunc->IsExternal() || scriptFunc->IsExternalOverload())) { 1143af6ab5fSopenharmony_ci checker::ScopeContext scopeCtx(checker, scriptFunc->Scope()); 1153af6ab5fSopenharmony_ci checker::SavedCheckerContext savedContext(checker, checker->Context().Status(), 1163af6ab5fSopenharmony_ci checker->Context().ContainingClass()); 1173af6ab5fSopenharmony_ci checker->Context().SetContainingSignature(checker->GetSignatureFromMethodDefinition(node)); 1183af6ab5fSopenharmony_ci 1193af6ab5fSopenharmony_ci if (node->IsStatic() && !node->IsConstructor() && 1203af6ab5fSopenharmony_ci !checker->Context().ContainingClass()->HasObjectFlag(checker::ETSObjectFlags::GLOBAL)) { 1213af6ab5fSopenharmony_ci checker->AddStatus(checker::CheckerStatus::IN_STATIC_CONTEXT); 1223af6ab5fSopenharmony_ci } 1233af6ab5fSopenharmony_ci 1243af6ab5fSopenharmony_ci if (node->IsConstructor()) { 1253af6ab5fSopenharmony_ci checker->AddStatus(checker::CheckerStatus::IN_CONSTRUCTOR); 1263af6ab5fSopenharmony_ci } 1273af6ab5fSopenharmony_ci 1283af6ab5fSopenharmony_ci if (node->IsExtensionMethod()) { 1293af6ab5fSopenharmony_ci CheckExtensionMethod(checker, scriptFunc, node); 1303af6ab5fSopenharmony_ci } 1313af6ab5fSopenharmony_ci 1323af6ab5fSopenharmony_ci scriptFunc->Body()->Check(checker); 1333af6ab5fSopenharmony_ci 1343af6ab5fSopenharmony_ci if (scriptFunc->ReturnTypeAnnotation() == nullptr) { 1353af6ab5fSopenharmony_ci if (scriptFunc->IsAsyncImplFunc()) { 1363af6ab5fSopenharmony_ci ComposeAsyncImplFuncReturnType(checker, scriptFunc); 1373af6ab5fSopenharmony_ci } 1383af6ab5fSopenharmony_ci 1393af6ab5fSopenharmony_ci for (auto &returnStatement : scriptFunc->ReturnStatements()) { 1403af6ab5fSopenharmony_ci returnStatement->SetReturnType(checker, scriptFunc->Signature()->ReturnType()); 1413af6ab5fSopenharmony_ci } 1423af6ab5fSopenharmony_ci } 1433af6ab5fSopenharmony_ci 1443af6ab5fSopenharmony_ci checker->Context().SetContainingSignature(nullptr); 1453af6ab5fSopenharmony_ci } 1463af6ab5fSopenharmony_ci} 1473af6ab5fSopenharmony_ci 1483af6ab5fSopenharmony_civoid ComposeAsyncImplFuncReturnType(ETSChecker *checker, ir::ScriptFunction *scriptFunc) 1493af6ab5fSopenharmony_ci{ 1503af6ab5fSopenharmony_ci const auto &promiseGlobal = checker->GlobalBuiltinPromiseType()->AsETSObjectType(); 1513af6ab5fSopenharmony_ci auto promiseType = 1523af6ab5fSopenharmony_ci promiseGlobal->Instantiate(checker->Allocator(), checker->Relation(), checker->GetGlobalTypesHolder()) 1533af6ab5fSopenharmony_ci ->AsETSObjectType(); 1543af6ab5fSopenharmony_ci promiseType->AddTypeFlag(checker::TypeFlag::GENERIC); 1553af6ab5fSopenharmony_ci promiseType->TypeArguments().clear(); 1563af6ab5fSopenharmony_ci promiseType->TypeArguments().emplace_back(scriptFunc->Signature()->ReturnType()); 1573af6ab5fSopenharmony_ci 1583af6ab5fSopenharmony_ci auto *objectId = 1593af6ab5fSopenharmony_ci checker->AllocNode<ir::Identifier>(compiler::Signatures::BUILTIN_OBJECT_CLASS, checker->Allocator()); 1603af6ab5fSopenharmony_ci objectId->SetReference(); 1613af6ab5fSopenharmony_ci checker->VarBinder()->AsETSBinder()->LookupTypeReference(objectId, false); 1623af6ab5fSopenharmony_ci auto *returnType = checker->AllocNode<ir::ETSTypeReference>( 1633af6ab5fSopenharmony_ci checker->AllocNode<ir::ETSTypeReferencePart>(objectId, nullptr, nullptr)); 1643af6ab5fSopenharmony_ci objectId->SetParent(returnType->Part()); 1653af6ab5fSopenharmony_ci returnType->Part()->SetParent(returnType); 1663af6ab5fSopenharmony_ci returnType->SetTsType( 1673af6ab5fSopenharmony_ci checker->Allocator()->New<ETSAsyncFuncReturnType>(checker->Allocator(), checker->Relation(), promiseType)); 1683af6ab5fSopenharmony_ci returnType->Check(checker); 1693af6ab5fSopenharmony_ci scriptFunc->Signature()->SetReturnType(returnType->TsType()); 1703af6ab5fSopenharmony_ci} 1713af6ab5fSopenharmony_ci 1723af6ab5fSopenharmony_civoid ComposeAsyncImplMethod(ETSChecker *checker, ir::MethodDefinition *node) 1733af6ab5fSopenharmony_ci{ 1743af6ab5fSopenharmony_ci auto *classDef = checker->FindAncestorGivenByType(node, ir::AstNodeType::CLASS_DEFINITION)->AsClassDefinition(); 1753af6ab5fSopenharmony_ci auto *scriptFunc = node->Function(); 1763af6ab5fSopenharmony_ci ir::MethodDefinition *implMethod = checker->CreateAsyncProxy(node, classDef); 1773af6ab5fSopenharmony_ci 1783af6ab5fSopenharmony_ci implMethod->Check(checker); 1793af6ab5fSopenharmony_ci node->SetAsyncPairMethod(implMethod); 1803af6ab5fSopenharmony_ci 1813af6ab5fSopenharmony_ci if (scriptFunc->Signature()->HasSignatureFlag(SignatureFlags::NEED_RETURN_TYPE)) { 1823af6ab5fSopenharmony_ci node->Function()->Signature()->SetReturnType( 1833af6ab5fSopenharmony_ci implMethod->Function()->Signature()->ReturnType()->AsETSAsyncFuncReturnType()->PromiseType()); 1843af6ab5fSopenharmony_ci scriptFunc->Signature()->RemoveSignatureFlag(SignatureFlags::NEED_RETURN_TYPE); 1853af6ab5fSopenharmony_ci } 1863af6ab5fSopenharmony_ci 1873af6ab5fSopenharmony_ci if (node->Function()->IsOverload()) { 1883af6ab5fSopenharmony_ci auto *baseOverloadImplMethod = node->BaseOverloadMethod()->AsyncPairMethod(); 1893af6ab5fSopenharmony_ci implMethod->Function()->Id()->SetVariable(baseOverloadImplMethod->Function()->Id()->Variable()); 1903af6ab5fSopenharmony_ci baseOverloadImplMethod->AddOverload(implMethod); 1913af6ab5fSopenharmony_ci } else { 1923af6ab5fSopenharmony_ci classDef->Body().push_back(implMethod); 1933af6ab5fSopenharmony_ci } 1943af6ab5fSopenharmony_ci} 1953af6ab5fSopenharmony_ci 1963af6ab5fSopenharmony_civoid CheckPredefinedMethodReturnType(ETSChecker *checker, ir::ScriptFunction *scriptFunc) 1973af6ab5fSopenharmony_ci{ 1983af6ab5fSopenharmony_ci auto const &position = scriptFunc->Start(); 1993af6ab5fSopenharmony_ci 2003af6ab5fSopenharmony_ci if (scriptFunc->IsSetter() && (scriptFunc->Signature()->ReturnType() != checker->GlobalVoidType())) { 2013af6ab5fSopenharmony_ci checker->LogTypeError("Setter must have void return type", position); 2023af6ab5fSopenharmony_ci } 2033af6ab5fSopenharmony_ci 2043af6ab5fSopenharmony_ci if (scriptFunc->IsGetter() && (scriptFunc->Signature()->ReturnType() == checker->GlobalVoidType())) { 2053af6ab5fSopenharmony_ci checker->LogTypeError("Getter must return a value", position); 2063af6ab5fSopenharmony_ci } 2073af6ab5fSopenharmony_ci 2083af6ab5fSopenharmony_ci auto const name = scriptFunc->Id()->Name(); 2093af6ab5fSopenharmony_ci auto const methodName = std::string {ir::PREDEFINED_METHOD} + std::string {name.Utf8()}; 2103af6ab5fSopenharmony_ci 2113af6ab5fSopenharmony_ci if (name.Is(compiler::Signatures::GET_INDEX_METHOD)) { 2123af6ab5fSopenharmony_ci if (scriptFunc->Signature()->ReturnType() == checker->GlobalVoidType()) { 2133af6ab5fSopenharmony_ci checker->LogTypeError(methodName + "' shouldn't have void return type.", position); 2143af6ab5fSopenharmony_ci } 2153af6ab5fSopenharmony_ci } else if (name.Is(compiler::Signatures::SET_INDEX_METHOD)) { 2163af6ab5fSopenharmony_ci if (scriptFunc->Signature()->ReturnType() != checker->GlobalVoidType()) { 2173af6ab5fSopenharmony_ci checker->LogTypeError(methodName + "' should have void return type.", position); 2183af6ab5fSopenharmony_ci } 2193af6ab5fSopenharmony_ci } else if (name.Is(compiler::Signatures::ITERATOR_METHOD)) { 2203af6ab5fSopenharmony_ci CheckIteratorMethodReturnType(checker, scriptFunc, position, methodName); 2213af6ab5fSopenharmony_ci } 2223af6ab5fSopenharmony_ci} 2233af6ab5fSopenharmony_ci 2243af6ab5fSopenharmony_cistatic bool HasIteratorInterface(ETSObjectType const *const objectType) 2253af6ab5fSopenharmony_ci{ 2263af6ab5fSopenharmony_ci auto const hasIteratorInterfaceImpl = [](ETSObjectType const *const checkType, 2273af6ab5fSopenharmony_ci auto &&iteratorInterfaceImpl) -> bool { 2283af6ab5fSopenharmony_ci if (checkType->Name().Is(ir::ITERATOR_INTERFACE_NAME)) { 2293af6ab5fSopenharmony_ci return true; 2303af6ab5fSopenharmony_ci } 2313af6ab5fSopenharmony_ci for (const auto *const interface : checkType->Interfaces()) { 2323af6ab5fSopenharmony_ci if (iteratorInterfaceImpl(interface, iteratorInterfaceImpl)) { 2333af6ab5fSopenharmony_ci return true; 2343af6ab5fSopenharmony_ci } 2353af6ab5fSopenharmony_ci } 2363af6ab5fSopenharmony_ci return false; 2373af6ab5fSopenharmony_ci }; 2383af6ab5fSopenharmony_ci 2393af6ab5fSopenharmony_ci return hasIteratorInterfaceImpl(objectType, hasIteratorInterfaceImpl); 2403af6ab5fSopenharmony_ci} 2413af6ab5fSopenharmony_ci 2423af6ab5fSopenharmony_civoid CheckIteratorMethodReturnType(ETSChecker *checker, ir::ScriptFunction *scriptFunc, 2433af6ab5fSopenharmony_ci const lexer::SourcePosition &position, const std::string &methodName) 2443af6ab5fSopenharmony_ci{ 2453af6ab5fSopenharmony_ci const auto *returnType = scriptFunc->Signature()->ReturnType(); 2463af6ab5fSopenharmony_ci 2473af6ab5fSopenharmony_ci if (returnType == nullptr) { 2483af6ab5fSopenharmony_ci checker->LogTypeError(methodName + "' doesn't have return type.", position); 2493af6ab5fSopenharmony_ci } 2503af6ab5fSopenharmony_ci 2513af6ab5fSopenharmony_ci if (returnType->IsETSTypeParameter()) { 2523af6ab5fSopenharmony_ci returnType = checker->GetApparentType(returnType->AsETSTypeParameter()->GetConstraintType()); 2533af6ab5fSopenharmony_ci } 2543af6ab5fSopenharmony_ci 2553af6ab5fSopenharmony_ci if (returnType->IsETSObjectType() && HasIteratorInterface(returnType->AsETSObjectType())) { 2563af6ab5fSopenharmony_ci return; 2573af6ab5fSopenharmony_ci } 2583af6ab5fSopenharmony_ci 2593af6ab5fSopenharmony_ci while (returnType->IsETSObjectType() && returnType->AsETSObjectType()->SuperType() != nullptr) { 2603af6ab5fSopenharmony_ci returnType = returnType->AsETSObjectType()->SuperType(); 2613af6ab5fSopenharmony_ci if (returnType->IsETSObjectType() && HasIteratorInterface(returnType->AsETSObjectType())) { 2623af6ab5fSopenharmony_ci return; 2633af6ab5fSopenharmony_ci } 2643af6ab5fSopenharmony_ci } 2653af6ab5fSopenharmony_ci 2663af6ab5fSopenharmony_ci checker->LogTypeError( 2673af6ab5fSopenharmony_ci {"The return type of '", scriptFunc->Id()->Name(), "' must be a type that implements Iterator interface."}, 2683af6ab5fSopenharmony_ci position); 2693af6ab5fSopenharmony_ci} 2703af6ab5fSopenharmony_ci 2713af6ab5fSopenharmony_cichecker::Type *InitAnonymousLambdaCallee(checker::ETSChecker *checker, ir::Expression *callee, 2723af6ab5fSopenharmony_ci checker::Type *calleeType) 2733af6ab5fSopenharmony_ci{ 2743af6ab5fSopenharmony_ci auto *const arrowFunc = callee->AsArrowFunctionExpression()->Function(); 2753af6ab5fSopenharmony_ci 2763af6ab5fSopenharmony_ci ArenaVector<ir::Expression *> params {checker->Allocator()->Adapter()}; 2773af6ab5fSopenharmony_ci checker->CopyParams(arrowFunc->Params(), params); 2783af6ab5fSopenharmony_ci checker::Type *funcReturnType = nullptr; 2793af6ab5fSopenharmony_ci 2803af6ab5fSopenharmony_ci auto *typeAnnotation = arrowFunc->ReturnTypeAnnotation(); 2813af6ab5fSopenharmony_ci if (typeAnnotation != nullptr) { 2823af6ab5fSopenharmony_ci typeAnnotation = typeAnnotation->Clone(checker->Allocator(), nullptr); 2833af6ab5fSopenharmony_ci typeAnnotation->SetTsType(arrowFunc->ReturnTypeAnnotation()->TsType()); 2843af6ab5fSopenharmony_ci } else if (arrowFunc->Signature()->ReturnType() != nullptr) { 2853af6ab5fSopenharmony_ci auto newTypeAnnotation = callee->AsArrowFunctionExpression()->CreateTypeAnnotation(checker); 2863af6ab5fSopenharmony_ci typeAnnotation = arrowFunc->ReturnTypeAnnotation(); 2873af6ab5fSopenharmony_ci funcReturnType = newTypeAnnotation->GetType(checker); 2883af6ab5fSopenharmony_ci } 2893af6ab5fSopenharmony_ci 2903af6ab5fSopenharmony_ci auto signature = ir::FunctionSignature(nullptr, std::move(params), typeAnnotation); 2913af6ab5fSopenharmony_ci auto *funcType = checker->AllocNode<ir::ETSFunctionType>(std::move(signature), ir::ScriptFunctionFlags::NONE); 2923af6ab5fSopenharmony_ci 2933af6ab5fSopenharmony_ci funcType->SetScope(arrowFunc->Scope()->AsFunctionScope()->ParamScope()); 2943af6ab5fSopenharmony_ci auto *const funcIface = typeAnnotation != nullptr ? funcType->Check(checker) : funcReturnType; 2953af6ab5fSopenharmony_ci checker->Relation()->SetNode(callee); 2963af6ab5fSopenharmony_ci checker->Relation()->IsAssignableTo(calleeType, funcIface); 2973af6ab5fSopenharmony_ci return funcIface; 2983af6ab5fSopenharmony_ci} 2993af6ab5fSopenharmony_ci 3003af6ab5fSopenharmony_cichecker::Signature *ResolveCallExtensionFunction(checker::ETSFunctionType *functionType, checker::ETSChecker *checker, 3013af6ab5fSopenharmony_ci ir::CallExpression *expr) 3023af6ab5fSopenharmony_ci{ 3033af6ab5fSopenharmony_ci auto *memberExpr = expr->Callee()->AsMemberExpression(); 3043af6ab5fSopenharmony_ci expr->Arguments().insert(expr->Arguments().begin(), memberExpr->Object()); 3053af6ab5fSopenharmony_ci auto *signature = 3063af6ab5fSopenharmony_ci checker->ResolveCallExpressionAndTrailingLambda(functionType->CallSignatures(), expr, expr->Start()); 3073af6ab5fSopenharmony_ci if (signature == nullptr) { 3083af6ab5fSopenharmony_ci return nullptr; 3093af6ab5fSopenharmony_ci } 3103af6ab5fSopenharmony_ci if (!signature->Function()->IsExtensionMethod()) { 3113af6ab5fSopenharmony_ci checker->LogTypeError({"Property '", memberExpr->Property()->AsIdentifier()->Name(), 3123af6ab5fSopenharmony_ci "' does not exist on type '", memberExpr->ObjType()->Name(), "'"}, 3133af6ab5fSopenharmony_ci memberExpr->Property()->Start()); 3143af6ab5fSopenharmony_ci } 3153af6ab5fSopenharmony_ci expr->SetSignature(signature); 3163af6ab5fSopenharmony_ci expr->SetCallee(memberExpr->Property()); 3173af6ab5fSopenharmony_ci memberExpr->Property()->AsIdentifier()->SetParent(expr); 3183af6ab5fSopenharmony_ci expr->Arguments()[0]->SetParent(expr); 3193af6ab5fSopenharmony_ci checker->HandleUpdatedCallExpressionNode(expr); 3203af6ab5fSopenharmony_ci // Set TsType for new Callee(original member expression's Object) 3213af6ab5fSopenharmony_ci expr->Callee()->Check(checker); 3223af6ab5fSopenharmony_ci return signature; 3233af6ab5fSopenharmony_ci} 3243af6ab5fSopenharmony_ci 3253af6ab5fSopenharmony_cichecker::Signature *ResolveCallForETSExtensionFuncHelperType(checker::ETSExtensionFuncHelperType *type, 3263af6ab5fSopenharmony_ci checker::ETSChecker *checker, ir::CallExpression *expr) 3273af6ab5fSopenharmony_ci{ 3283af6ab5fSopenharmony_ci checker::Signature *signature = checker->ResolveCallExpressionAndTrailingLambda( 3293af6ab5fSopenharmony_ci type->ClassMethodType()->CallSignatures(), expr, expr->Start(), checker::TypeRelationFlag::NO_THROW); 3303af6ab5fSopenharmony_ci 3313af6ab5fSopenharmony_ci if (signature != nullptr) { 3323af6ab5fSopenharmony_ci if (expr->Callee()->IsMemberExpression()) { 3333af6ab5fSopenharmony_ci auto memberExpr = expr->Callee()->AsMemberExpression(); 3343af6ab5fSopenharmony_ci auto var = type->ClassMethodType()->Variable(); 3353af6ab5fSopenharmony_ci memberExpr->Property()->AsIdentifier()->SetVariable(var); 3363af6ab5fSopenharmony_ci } 3373af6ab5fSopenharmony_ci 3383af6ab5fSopenharmony_ci return signature; 3393af6ab5fSopenharmony_ci } 3403af6ab5fSopenharmony_ci 3413af6ab5fSopenharmony_ci return ResolveCallExtensionFunction(type->ExtensionMethodType(), checker, expr); 3423af6ab5fSopenharmony_ci} 3433af6ab5fSopenharmony_ci 3443af6ab5fSopenharmony_ciArenaVector<checker::Signature *> GetUnionTypeSignatures(ETSChecker *checker, checker::ETSUnionType *etsUnionType) 3453af6ab5fSopenharmony_ci{ 3463af6ab5fSopenharmony_ci ArenaVector<checker::Signature *> callSignatures(checker->Allocator()->Adapter()); 3473af6ab5fSopenharmony_ci 3483af6ab5fSopenharmony_ci for (auto *constituentType : etsUnionType->ConstituentTypes()) { 3493af6ab5fSopenharmony_ci if (constituentType->IsETSObjectType()) { 3503af6ab5fSopenharmony_ci ArenaVector<checker::Signature *> tmpCallSignatures(checker->Allocator()->Adapter()); 3513af6ab5fSopenharmony_ci tmpCallSignatures = constituentType->AsETSObjectType() 3523af6ab5fSopenharmony_ci ->GetOwnProperty<checker::PropertyType::INSTANCE_METHOD>("invoke0") 3533af6ab5fSopenharmony_ci ->TsType() 3543af6ab5fSopenharmony_ci ->AsETSFunctionType() 3553af6ab5fSopenharmony_ci ->CallSignatures(); 3563af6ab5fSopenharmony_ci callSignatures.insert(callSignatures.end(), tmpCallSignatures.begin(), tmpCallSignatures.end()); 3573af6ab5fSopenharmony_ci } 3583af6ab5fSopenharmony_ci if (constituentType->IsETSFunctionType()) { 3593af6ab5fSopenharmony_ci ArenaVector<checker::Signature *> tmpCallSignatures(checker->Allocator()->Adapter()); 3603af6ab5fSopenharmony_ci tmpCallSignatures = constituentType->AsETSFunctionType()->CallSignatures(); 3613af6ab5fSopenharmony_ci callSignatures.insert(callSignatures.end(), tmpCallSignatures.begin(), tmpCallSignatures.end()); 3623af6ab5fSopenharmony_ci } 3633af6ab5fSopenharmony_ci if (constituentType->IsETSUnionType()) { 3643af6ab5fSopenharmony_ci ArenaVector<checker::Signature *> tmpCallSignatures(checker->Allocator()->Adapter()); 3653af6ab5fSopenharmony_ci tmpCallSignatures = GetUnionTypeSignatures(checker, constituentType->AsETSUnionType()); 3663af6ab5fSopenharmony_ci callSignatures.insert(callSignatures.end(), tmpCallSignatures.begin(), tmpCallSignatures.end()); 3673af6ab5fSopenharmony_ci } 3683af6ab5fSopenharmony_ci } 3693af6ab5fSopenharmony_ci 3703af6ab5fSopenharmony_ci return callSignatures; 3713af6ab5fSopenharmony_ci} 3723af6ab5fSopenharmony_ci 3733af6ab5fSopenharmony_ciArenaVector<checker::Signature *> &ChooseSignatures(ETSChecker *checker, checker::Type *calleeType, 3743af6ab5fSopenharmony_ci bool isConstructorCall, bool isFunctionalInterface, 3753af6ab5fSopenharmony_ci bool isUnionTypeWithFunctionalInterface) 3763af6ab5fSopenharmony_ci{ 3773af6ab5fSopenharmony_ci static ArenaVector<checker::Signature *> unionSignatures(checker->Allocator()->Adapter()); 3783af6ab5fSopenharmony_ci unionSignatures.clear(); 3793af6ab5fSopenharmony_ci if (isConstructorCall) { 3803af6ab5fSopenharmony_ci return calleeType->AsETSObjectType()->ConstructSignatures(); 3813af6ab5fSopenharmony_ci } 3823af6ab5fSopenharmony_ci if (isFunctionalInterface) { 3833af6ab5fSopenharmony_ci return calleeType->AsETSObjectType() 3843af6ab5fSopenharmony_ci ->GetOwnProperty<checker::PropertyType::INSTANCE_METHOD>(FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME) 3853af6ab5fSopenharmony_ci ->TsType() 3863af6ab5fSopenharmony_ci ->AsETSFunctionType() 3873af6ab5fSopenharmony_ci ->CallSignatures(); 3883af6ab5fSopenharmony_ci } 3893af6ab5fSopenharmony_ci if (isUnionTypeWithFunctionalInterface) { 3903af6ab5fSopenharmony_ci unionSignatures = GetUnionTypeSignatures(checker, calleeType->AsETSUnionType()); 3913af6ab5fSopenharmony_ci return unionSignatures; 3923af6ab5fSopenharmony_ci } 3933af6ab5fSopenharmony_ci return calleeType->AsETSFunctionType()->CallSignatures(); 3943af6ab5fSopenharmony_ci} 3953af6ab5fSopenharmony_ci 3963af6ab5fSopenharmony_cichecker::ETSObjectType *ChooseCalleeObj(ETSChecker *checker, ir::CallExpression *expr, checker::Type *calleeType, 3973af6ab5fSopenharmony_ci bool isConstructorCall) 3983af6ab5fSopenharmony_ci{ 3993af6ab5fSopenharmony_ci if (isConstructorCall) { 4003af6ab5fSopenharmony_ci return calleeType->AsETSObjectType(); 4013af6ab5fSopenharmony_ci } 4023af6ab5fSopenharmony_ci if (expr->Callee()->IsIdentifier()) { 4033af6ab5fSopenharmony_ci return checker->Context().ContainingClass(); 4043af6ab5fSopenharmony_ci } 4053af6ab5fSopenharmony_ci ASSERT(expr->Callee()->IsMemberExpression()); 4063af6ab5fSopenharmony_ci return expr->Callee()->AsMemberExpression()->ObjType(); 4073af6ab5fSopenharmony_ci} 4083af6ab5fSopenharmony_ci 4093af6ab5fSopenharmony_civoid ProcessExclamationMark(ETSChecker *checker, ir::UnaryExpression *expr, checker::Type *operandType) 4103af6ab5fSopenharmony_ci{ 4113af6ab5fSopenharmony_ci if (checker->IsNullLikeOrVoidExpression(expr->Argument())) { 4123af6ab5fSopenharmony_ci auto tsType = checker->CreateETSBooleanType(true); 4133af6ab5fSopenharmony_ci tsType->AddTypeFlag(checker::TypeFlag::CONSTANT); 4143af6ab5fSopenharmony_ci expr->SetTsType(tsType); 4153af6ab5fSopenharmony_ci return; 4163af6ab5fSopenharmony_ci } 4173af6ab5fSopenharmony_ci 4183af6ab5fSopenharmony_ci if (operandType == nullptr || !operandType->IsConditionalExprType()) { 4193af6ab5fSopenharmony_ci checker->LogTypeError("Bad operand type, the type of the operand must be boolean type.", 4203af6ab5fSopenharmony_ci expr->Argument()->Start()); 4213af6ab5fSopenharmony_ci expr->SetTsType(checker->GlobalTypeError()); 4223af6ab5fSopenharmony_ci return; 4233af6ab5fSopenharmony_ci } 4243af6ab5fSopenharmony_ci 4253af6ab5fSopenharmony_ci auto exprRes = operandType->ResolveConditionExpr(); 4263af6ab5fSopenharmony_ci if (std::get<0>(exprRes)) { 4273af6ab5fSopenharmony_ci auto tsType = checker->CreateETSBooleanType(!std::get<1>(exprRes)); 4283af6ab5fSopenharmony_ci tsType->AddTypeFlag(checker::TypeFlag::CONSTANT); 4293af6ab5fSopenharmony_ci expr->SetTsType(tsType); 4303af6ab5fSopenharmony_ci return; 4313af6ab5fSopenharmony_ci } 4323af6ab5fSopenharmony_ci 4333af6ab5fSopenharmony_ci expr->SetTsType(checker->GlobalETSBooleanType()); 4343af6ab5fSopenharmony_ci} 4353af6ab5fSopenharmony_ci 4363af6ab5fSopenharmony_civoid SetTsTypeForUnaryExpression(ETSChecker *checker, ir::UnaryExpression *expr, checker::Type *operandType) 4373af6ab5fSopenharmony_ci{ 4383af6ab5fSopenharmony_ci switch (expr->OperatorType()) { 4393af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_MINUS: 4403af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_PLUS: { 4413af6ab5fSopenharmony_ci if (operandType == nullptr || !operandType->HasTypeFlag(checker::TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC)) { 4423af6ab5fSopenharmony_ci checker->LogTypeError("Bad operand type, the type of the operand must be numeric type.", 4433af6ab5fSopenharmony_ci expr->Argument()->Start()); 4443af6ab5fSopenharmony_ci expr->SetTsType(checker->GlobalTypeError()); 4453af6ab5fSopenharmony_ci break; 4463af6ab5fSopenharmony_ci } 4473af6ab5fSopenharmony_ci 4483af6ab5fSopenharmony_ci if (operandType->HasTypeFlag(checker::TypeFlag::CONSTANT) && 4493af6ab5fSopenharmony_ci expr->OperatorType() == lexer::TokenType::PUNCTUATOR_MINUS) { 4503af6ab5fSopenharmony_ci expr->SetTsType(checker->NegateNumericType(operandType, expr)); 4513af6ab5fSopenharmony_ci break; 4523af6ab5fSopenharmony_ci } 4533af6ab5fSopenharmony_ci 4543af6ab5fSopenharmony_ci expr->SetTsType(operandType); 4553af6ab5fSopenharmony_ci break; 4563af6ab5fSopenharmony_ci } 4573af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_TILDE: { 4583af6ab5fSopenharmony_ci if (operandType == nullptr || !operandType->HasTypeFlag(checker::TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC)) { 4593af6ab5fSopenharmony_ci checker->LogTypeError("Bad operand type, the type of the operand must be numeric type.", 4603af6ab5fSopenharmony_ci expr->Argument()->Start()); 4613af6ab5fSopenharmony_ci expr->SetTsType(checker->GlobalTypeError()); 4623af6ab5fSopenharmony_ci break; 4633af6ab5fSopenharmony_ci } 4643af6ab5fSopenharmony_ci 4653af6ab5fSopenharmony_ci if (operandType->HasTypeFlag(checker::TypeFlag::CONSTANT)) { 4663af6ab5fSopenharmony_ci expr->SetTsType(checker->BitwiseNegateNumericType(operandType, expr)); 4673af6ab5fSopenharmony_ci break; 4683af6ab5fSopenharmony_ci } 4693af6ab5fSopenharmony_ci 4703af6ab5fSopenharmony_ci expr->SetTsType(checker->SelectGlobalIntegerTypeForNumeric(operandType)); 4713af6ab5fSopenharmony_ci break; 4723af6ab5fSopenharmony_ci } 4733af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: { 4743af6ab5fSopenharmony_ci ProcessExclamationMark(checker, expr, operandType); 4753af6ab5fSopenharmony_ci break; 4763af6ab5fSopenharmony_ci } 4773af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_DOLLAR_DOLLAR: { 4783af6ab5fSopenharmony_ci expr->SetTsType(expr->Argument()->TsType()); 4793af6ab5fSopenharmony_ci break; 4803af6ab5fSopenharmony_ci } 4813af6ab5fSopenharmony_ci default: { 4823af6ab5fSopenharmony_ci UNREACHABLE(); 4833af6ab5fSopenharmony_ci break; 4843af6ab5fSopenharmony_ci } 4853af6ab5fSopenharmony_ci } 4863af6ab5fSopenharmony_ci} 4873af6ab5fSopenharmony_ci 4883af6ab5fSopenharmony_cichecker::ETSObjectType *CreateSyntheticType(ETSChecker *checker, util::StringView const &syntheticName, 4893af6ab5fSopenharmony_ci checker::ETSObjectType *lastObjectType, ir::Identifier *id) 4903af6ab5fSopenharmony_ci{ 4913af6ab5fSopenharmony_ci auto *syntheticObjType = checker->Allocator()->New<checker::ETSObjectType>( 4923af6ab5fSopenharmony_ci checker->Allocator(), syntheticName, syntheticName, 4933af6ab5fSopenharmony_ci std::make_tuple(id, checker::ETSObjectFlags::NO_OPTS, checker->Relation())); 4943af6ab5fSopenharmony_ci 4953af6ab5fSopenharmony_ci auto *classDecl = checker->Allocator()->New<varbinder::ClassDecl>(syntheticName); 4963af6ab5fSopenharmony_ci varbinder::LocalVariable *var = 4973af6ab5fSopenharmony_ci checker->Allocator()->New<varbinder::LocalVariable>(classDecl, varbinder::VariableFlags::CLASS); 4983af6ab5fSopenharmony_ci var->SetTsType(syntheticObjType); 4993af6ab5fSopenharmony_ci lastObjectType->AddProperty<checker::PropertyType::STATIC_FIELD>(var); 5003af6ab5fSopenharmony_ci syntheticObjType->SetEnclosingType(lastObjectType); 5013af6ab5fSopenharmony_ci return syntheticObjType; 5023af6ab5fSopenharmony_ci} 5033af6ab5fSopenharmony_ci 5043af6ab5fSopenharmony_ci// NOLINTBEGIN(modernize-avoid-c-arrays) 5053af6ab5fSopenharmony_cistatic constexpr char const INVALID_CONST_ASSIGNMENT[] = "Cannot assign a value to a constant variable "; 5063af6ab5fSopenharmony_cistatic constexpr char const INVALID_READONLY_ASSIGNMENT[] = "Cannot assign a value to a readonly variable "; 5073af6ab5fSopenharmony_cistatic constexpr char const ITERATOR_TYPE_ABSENT[] = "Cannot obtain iterator type in 'for-of' statement."; 5083af6ab5fSopenharmony_ci// NOLINTEND(modernize-avoid-c-arrays) 5093af6ab5fSopenharmony_ci 5103af6ab5fSopenharmony_cichecker::Type *GetIteratorType(ETSChecker *checker, checker::Type *elemType, ir::AstNode *left) 5113af6ab5fSopenharmony_ci{ 5123af6ab5fSopenharmony_ci // Just to avoid extra nested level(s) 5133af6ab5fSopenharmony_ci auto const getIterType = [checker, elemType](ir::VariableDeclarator *const declarator) -> checker::Type * { 5143af6ab5fSopenharmony_ci if (declarator->TsType() == nullptr) { 5153af6ab5fSopenharmony_ci if (auto *resolved = checker->FindVariableInFunctionScope(declarator->Id()->AsIdentifier()->Name(), 5163af6ab5fSopenharmony_ci varbinder::ResolveBindingOptions::ALL_NON_TYPE); 5173af6ab5fSopenharmony_ci resolved != nullptr) { 5183af6ab5fSopenharmony_ci resolved->SetTsType(elemType); 5193af6ab5fSopenharmony_ci return elemType; 5203af6ab5fSopenharmony_ci } 5213af6ab5fSopenharmony_ci } else { 5223af6ab5fSopenharmony_ci return declarator->TsType(); 5233af6ab5fSopenharmony_ci } 5243af6ab5fSopenharmony_ci return checker->GlobalTypeError(); 5253af6ab5fSopenharmony_ci }; 5263af6ab5fSopenharmony_ci 5273af6ab5fSopenharmony_ci checker::Type *iterType = nullptr; 5283af6ab5fSopenharmony_ci if (left->IsIdentifier()) { 5293af6ab5fSopenharmony_ci if (auto *const variable = left->AsIdentifier()->Variable(); variable != nullptr) { 5303af6ab5fSopenharmony_ci auto *decl = variable->Declaration(); 5313af6ab5fSopenharmony_ci if (decl->IsConstDecl() || decl->IsReadonlyDecl()) { 5323af6ab5fSopenharmony_ci std::string_view errorMsg = 5333af6ab5fSopenharmony_ci decl->IsConstDecl() ? INVALID_CONST_ASSIGNMENT : INVALID_READONLY_ASSIGNMENT; 5343af6ab5fSopenharmony_ci checker->LogTypeError({errorMsg, variable->Name()}, decl->Node()->Start()); 5353af6ab5fSopenharmony_ci } 5363af6ab5fSopenharmony_ci } 5373af6ab5fSopenharmony_ci iterType = left->AsIdentifier()->TsType(); 5383af6ab5fSopenharmony_ci } else if (left->IsVariableDeclaration()) { 5393af6ab5fSopenharmony_ci if (auto const &declarators = left->AsVariableDeclaration()->Declarators(); !declarators.empty()) { 5403af6ab5fSopenharmony_ci iterType = getIterType(declarators.front()); 5413af6ab5fSopenharmony_ci } 5423af6ab5fSopenharmony_ci } 5433af6ab5fSopenharmony_ci 5443af6ab5fSopenharmony_ci if (iterType == nullptr) { 5453af6ab5fSopenharmony_ci checker->LogTypeError(ITERATOR_TYPE_ABSENT, left->Start()); 5463af6ab5fSopenharmony_ci return checker->GlobalTypeError(); 5473af6ab5fSopenharmony_ci } 5483af6ab5fSopenharmony_ci return iterType; 5493af6ab5fSopenharmony_ci} 5503af6ab5fSopenharmony_ci 5513af6ab5fSopenharmony_cibool CheckArgumentVoidType(checker::Type *&funcReturnType, ETSChecker *checker, const std::string &name, 5523af6ab5fSopenharmony_ci ir::ReturnStatement *st) 5533af6ab5fSopenharmony_ci{ 5543af6ab5fSopenharmony_ci if (name.find(compiler::Signatures::ETS_MAIN_WITH_MANGLE_BEGIN) != std::string::npos) { 5553af6ab5fSopenharmony_ci if (!funcReturnType->IsETSVoidType() && !funcReturnType->IsIntType()) { 5563af6ab5fSopenharmony_ci checker->LogTypeError("Bad return type, main enable only void or int type.", st->Start()); 5573af6ab5fSopenharmony_ci } 5583af6ab5fSopenharmony_ci } 5593af6ab5fSopenharmony_ci return true; 5603af6ab5fSopenharmony_ci} 5613af6ab5fSopenharmony_ci 5623af6ab5fSopenharmony_cibool CheckReturnType(ETSChecker *checker, checker::Type *funcReturnType, checker::Type *argumentType, 5633af6ab5fSopenharmony_ci ir::Expression *stArgument, bool isAsync) 5643af6ab5fSopenharmony_ci{ 5653af6ab5fSopenharmony_ci if (funcReturnType->IsETSVoidType() || funcReturnType == checker->GlobalVoidType()) { 5663af6ab5fSopenharmony_ci if (argumentType != checker->GlobalVoidType()) { 5673af6ab5fSopenharmony_ci checker->LogTypeError("Unexpected return value, enclosing method return type is void.", 5683af6ab5fSopenharmony_ci stArgument->Start()); 5693af6ab5fSopenharmony_ci return false; 5703af6ab5fSopenharmony_ci } 5713af6ab5fSopenharmony_ci if (!checker::AssignmentContext(checker->Relation(), stArgument, argumentType, funcReturnType, 5723af6ab5fSopenharmony_ci stArgument->Start(), {}, 5733af6ab5fSopenharmony_ci checker::TypeRelationFlag::DIRECT_RETURN | checker::TypeRelationFlag::NO_THROW) 5743af6ab5fSopenharmony_ci .IsAssignable()) { 5753af6ab5fSopenharmony_ci checker->LogTypeError({"Return statement type is not compatible with the enclosing method's return type."}, 5763af6ab5fSopenharmony_ci stArgument->Start()); 5773af6ab5fSopenharmony_ci return false; 5783af6ab5fSopenharmony_ci } 5793af6ab5fSopenharmony_ci return true; 5803af6ab5fSopenharmony_ci } 5813af6ab5fSopenharmony_ci 5823af6ab5fSopenharmony_ci if (isAsync && funcReturnType->IsETSObjectType() && 5833af6ab5fSopenharmony_ci funcReturnType->AsETSObjectType()->GetOriginalBaseType() == checker->GlobalBuiltinPromiseType()) { 5843af6ab5fSopenharmony_ci auto promiseArg = funcReturnType->AsETSObjectType()->TypeArguments()[0]; 5853af6ab5fSopenharmony_ci checker::AssignmentContext(checker->Relation(), stArgument, argumentType, promiseArg, stArgument->Start(), {}, 5863af6ab5fSopenharmony_ci checker::TypeRelationFlag::DIRECT_RETURN | checker::TypeRelationFlag::NO_THROW); 5873af6ab5fSopenharmony_ci if (checker->Relation()->IsTrue()) { 5883af6ab5fSopenharmony_ci return true; 5893af6ab5fSopenharmony_ci } 5903af6ab5fSopenharmony_ci } 5913af6ab5fSopenharmony_ci 5923af6ab5fSopenharmony_ci const Type *targetType = checker->TryGettingFunctionTypeFromInvokeFunction(funcReturnType); 5933af6ab5fSopenharmony_ci const Type *sourceType = checker->TryGettingFunctionTypeFromInvokeFunction(argumentType); 5943af6ab5fSopenharmony_ci if (!checker::AssignmentContext(checker->Relation(), stArgument, argumentType, funcReturnType, stArgument->Start(), 5953af6ab5fSopenharmony_ci {}, checker::TypeRelationFlag::DIRECT_RETURN | checker::TypeRelationFlag::NO_THROW) 5963af6ab5fSopenharmony_ci .IsAssignable()) { 5973af6ab5fSopenharmony_ci checker->LogTypeError( 5983af6ab5fSopenharmony_ci {"Type '", sourceType, "' is not compatible with the enclosing method's return type '", targetType, "'"}, 5993af6ab5fSopenharmony_ci stArgument->Start()); 6003af6ab5fSopenharmony_ci return false; 6013af6ab5fSopenharmony_ci } 6023af6ab5fSopenharmony_ci return true; 6033af6ab5fSopenharmony_ci} 6043af6ab5fSopenharmony_ci 6053af6ab5fSopenharmony_civoid InferReturnType(ETSChecker *checker, ir::ScriptFunction *containingFunc, checker::Type *&funcReturnType, 6063af6ab5fSopenharmony_ci ir::Expression *stArgument) 6073af6ab5fSopenharmony_ci{ 6083af6ab5fSopenharmony_ci // First (or single) return statement in the function: 6093af6ab5fSopenharmony_ci funcReturnType = 6103af6ab5fSopenharmony_ci stArgument == nullptr ? checker->GlobalVoidType() : checker->GetNonConstantType(stArgument->Check(checker)); 6113af6ab5fSopenharmony_ci /* 6123af6ab5fSopenharmony_ci when st_argment is ArrowFunctionExpression, need infer type for st_argment 6133af6ab5fSopenharmony_ci example code: 6143af6ab5fSopenharmony_ci ``` 6153af6ab5fSopenharmony_ci return () => {} 6163af6ab5fSopenharmony_ci ``` 6173af6ab5fSopenharmony_ci */ 6183af6ab5fSopenharmony_ci if (stArgument != nullptr && stArgument->IsArrowFunctionExpression()) { 6193af6ab5fSopenharmony_ci auto arrowFunc = stArgument->AsArrowFunctionExpression(); 6203af6ab5fSopenharmony_ci auto typeAnnotation = arrowFunc->CreateTypeAnnotation(checker); 6213af6ab5fSopenharmony_ci 6223af6ab5fSopenharmony_ci auto *argumentType = arrowFunc->TsType(); 6233af6ab5fSopenharmony_ci funcReturnType = typeAnnotation->GetType(checker); 6243af6ab5fSopenharmony_ci 6253af6ab5fSopenharmony_ci const Type *sourceType = checker->TryGettingFunctionTypeFromInvokeFunction(argumentType); 6263af6ab5fSopenharmony_ci const Type *targetType = checker->TryGettingFunctionTypeFromInvokeFunction(funcReturnType); 6273af6ab5fSopenharmony_ci 6283af6ab5fSopenharmony_ci if (!checker::AssignmentContext(checker->Relation(), arrowFunc, argumentType, funcReturnType, 6293af6ab5fSopenharmony_ci stArgument->Start(), {}, 6303af6ab5fSopenharmony_ci checker::TypeRelationFlag::DIRECT_RETURN | checker::TypeRelationFlag::NO_THROW) 6313af6ab5fSopenharmony_ci .IsAssignable()) { 6323af6ab5fSopenharmony_ci checker->LogTypeError({"Type '", sourceType, 6333af6ab5fSopenharmony_ci "' is not compatible with the enclosing method's return type '", targetType, "'"}, 6343af6ab5fSopenharmony_ci stArgument->Start()); 6353af6ab5fSopenharmony_ci funcReturnType = checker->GlobalTypeError(); 6363af6ab5fSopenharmony_ci return; 6373af6ab5fSopenharmony_ci } 6383af6ab5fSopenharmony_ci } 6393af6ab5fSopenharmony_ci 6403af6ab5fSopenharmony_ci containingFunc->Signature()->SetReturnType(funcReturnType); 6413af6ab5fSopenharmony_ci containingFunc->Signature()->RemoveSignatureFlag(checker::SignatureFlags::NEED_RETURN_TYPE); 6423af6ab5fSopenharmony_ci containingFunc->Signature()->AddSignatureFlag(checker::SignatureFlags::INFERRED_RETURN_TYPE); 6433af6ab5fSopenharmony_ci checker->VarBinder()->AsETSBinder()->BuildFunctionName(containingFunc); 6443af6ab5fSopenharmony_ci 6453af6ab5fSopenharmony_ci if (stArgument != nullptr && stArgument->IsObjectExpression()) { 6463af6ab5fSopenharmony_ci stArgument->AsObjectExpression()->SetPreferredType(funcReturnType); 6473af6ab5fSopenharmony_ci } 6483af6ab5fSopenharmony_ci} 6493af6ab5fSopenharmony_ci 6503af6ab5fSopenharmony_civoid ProcessReturnStatements(ETSChecker *checker, ir::ScriptFunction *containingFunc, checker::Type *&funcReturnType, 6513af6ab5fSopenharmony_ci ir::ReturnStatement *st, ir::Expression *stArgument) 6523af6ab5fSopenharmony_ci{ 6533af6ab5fSopenharmony_ci funcReturnType = containingFunc->Signature()->ReturnType(); 6543af6ab5fSopenharmony_ci 6553af6ab5fSopenharmony_ci if (stArgument == nullptr) { 6563af6ab5fSopenharmony_ci // previous return statement(s) have value 6573af6ab5fSopenharmony_ci if (!funcReturnType->IsETSVoidType() && funcReturnType != checker->GlobalVoidType()) { 6583af6ab5fSopenharmony_ci checker->LogTypeError("All return statements in the function should be empty or have a value.", 6593af6ab5fSopenharmony_ci st->Start()); 6603af6ab5fSopenharmony_ci return; 6613af6ab5fSopenharmony_ci } 6623af6ab5fSopenharmony_ci } else { 6633af6ab5fSopenharmony_ci if (stArgument->IsObjectExpression()) { 6643af6ab5fSopenharmony_ci stArgument->AsObjectExpression()->SetPreferredType(funcReturnType); 6653af6ab5fSopenharmony_ci } 6663af6ab5fSopenharmony_ci 6673af6ab5fSopenharmony_ci if (stArgument->IsMemberExpression()) { 6683af6ab5fSopenharmony_ci checker->SetArrayPreferredTypeForNestedMemberExpressions(stArgument->AsMemberExpression(), funcReturnType); 6693af6ab5fSopenharmony_ci } 6703af6ab5fSopenharmony_ci 6713af6ab5fSopenharmony_ci checker::Type *argumentType = checker->GetNonConstantType(stArgument->Check(checker)); 6723af6ab5fSopenharmony_ci 6733af6ab5fSopenharmony_ci // previous return statement(s) don't have any value 6743af6ab5fSopenharmony_ci if (funcReturnType->IsETSVoidType() && !argumentType->IsETSVoidType()) { 6753af6ab5fSopenharmony_ci checker->LogTypeError("All return statements in the function should be empty or have a value.", 6763af6ab5fSopenharmony_ci stArgument->Start()); 6773af6ab5fSopenharmony_ci return; 6783af6ab5fSopenharmony_ci } 6793af6ab5fSopenharmony_ci 6803af6ab5fSopenharmony_ci const auto name = containingFunc->Scope()->InternalName().Mutf8(); 6813af6ab5fSopenharmony_ci if (!CheckArgumentVoidType(funcReturnType, checker, name, st)) { 6823af6ab5fSopenharmony_ci return; 6833af6ab5fSopenharmony_ci } 6843af6ab5fSopenharmony_ci 6853af6ab5fSopenharmony_ci auto *const relation = checker->Relation(); 6863af6ab5fSopenharmony_ci relation->SetNode(stArgument); 6873af6ab5fSopenharmony_ci 6883af6ab5fSopenharmony_ci if (!relation->IsIdenticalTo(funcReturnType, argumentType)) { 6893af6ab5fSopenharmony_ci checker->ResolveReturnStatement(funcReturnType, argumentType, containingFunc, st); 6903af6ab5fSopenharmony_ci } 6913af6ab5fSopenharmony_ci 6923af6ab5fSopenharmony_ci relation->SetNode(nullptr); 6933af6ab5fSopenharmony_ci relation->SetFlags(checker::TypeRelationFlag::NONE); 6943af6ab5fSopenharmony_ci } 6953af6ab5fSopenharmony_ci} 6963af6ab5fSopenharmony_ci 6973af6ab5fSopenharmony_ciETSObjectType *CreateOptionalSignaturesForFunctionalType(ETSChecker *checker, ir::ETSFunctionType *node, 6983af6ab5fSopenharmony_ci ETSObjectType *genericInterfaceType, 6993af6ab5fSopenharmony_ci Substitution *substitution, size_t optionalParameterIndex) 7003af6ab5fSopenharmony_ci{ 7013af6ab5fSopenharmony_ci const auto ¶ms = node->Params(); 7023af6ab5fSopenharmony_ci auto returnType = node->ReturnType()->GetType(checker); 7033af6ab5fSopenharmony_ci 7043af6ab5fSopenharmony_ci for (size_t i = 0; i < optionalParameterIndex; i++) { 7053af6ab5fSopenharmony_ci checker::ETSChecker::EmplaceSubstituted( 7063af6ab5fSopenharmony_ci substitution, genericInterfaceType->TypeArguments()[i]->AsETSTypeParameter()->GetOriginal(), 7073af6ab5fSopenharmony_ci InstantiateBoxedPrimitiveType(checker, params[i], 7083af6ab5fSopenharmony_ci params[i]->AsETSParameterExpression()->TypeAnnotation()->GetType(checker))); 7093af6ab5fSopenharmony_ci } 7103af6ab5fSopenharmony_ci 7113af6ab5fSopenharmony_ci for (size_t i = optionalParameterIndex; i < params.size(); i++) { 7123af6ab5fSopenharmony_ci checker::ETSChecker::EmplaceSubstituted( 7133af6ab5fSopenharmony_ci substitution, genericInterfaceType->TypeArguments()[i]->AsETSTypeParameter()->GetOriginal(), 7143af6ab5fSopenharmony_ci CreateParamTypeWithDefaultParam(checker, params[i])); 7153af6ab5fSopenharmony_ci } 7163af6ab5fSopenharmony_ci 7173af6ab5fSopenharmony_ci checker::ETSChecker::EmplaceSubstituted( 7183af6ab5fSopenharmony_ci substitution, 7193af6ab5fSopenharmony_ci genericInterfaceType->TypeArguments()[genericInterfaceType->TypeArguments().size() - 1] 7203af6ab5fSopenharmony_ci ->AsETSTypeParameter() 7213af6ab5fSopenharmony_ci ->GetOriginal(), 7223af6ab5fSopenharmony_ci InstantiateBoxedPrimitiveType(checker, node->ReturnType(), returnType)); 7233af6ab5fSopenharmony_ci 7243af6ab5fSopenharmony_ci return genericInterfaceType->Substitute(checker->Relation(), substitution)->AsETSObjectType(); 7253af6ab5fSopenharmony_ci} 7263af6ab5fSopenharmony_ci 7273af6ab5fSopenharmony_ciETSObjectType *CreateInterfaceTypeForETSFunctionType(ETSChecker *checker, ir::ETSFunctionType *node, 7283af6ab5fSopenharmony_ci ETSObjectType *genericInterfaceType, Substitution *substitution) 7293af6ab5fSopenharmony_ci{ 7303af6ab5fSopenharmony_ci size_t i = 0; 7313af6ab5fSopenharmony_ci if (auto const ¶ms = node->Params(); params.size() < checker->GlobalBuiltinFunctionTypeVariadicThreshold()) { 7323af6ab5fSopenharmony_ci for (; i < params.size(); i++) { 7333af6ab5fSopenharmony_ci checker::ETSChecker::EmplaceSubstituted( 7343af6ab5fSopenharmony_ci substitution, genericInterfaceType->TypeArguments()[i]->AsETSTypeParameter()->GetOriginal(), 7353af6ab5fSopenharmony_ci InstantiateBoxedPrimitiveType( 7363af6ab5fSopenharmony_ci checker, params[i], params[i]->AsETSParameterExpression()->TypeAnnotation()->GetType(checker))); 7373af6ab5fSopenharmony_ci } 7383af6ab5fSopenharmony_ci } 7393af6ab5fSopenharmony_ci 7403af6ab5fSopenharmony_ci checker::ETSChecker::EmplaceSubstituted( 7413af6ab5fSopenharmony_ci substitution, genericInterfaceType->TypeArguments()[i]->AsETSTypeParameter()->GetOriginal(), 7423af6ab5fSopenharmony_ci InstantiateBoxedPrimitiveType(checker, node->ReturnType(), node->ReturnType()->GetType(checker))); 7433af6ab5fSopenharmony_ci return genericInterfaceType->Substitute(checker->Relation(), substitution)->AsETSObjectType(); 7443af6ab5fSopenharmony_ci} 7453af6ab5fSopenharmony_ci 7463af6ab5fSopenharmony_ciType *CreateParamTypeWithDefaultParam(ETSChecker *checker, ir::Expression *param) 7473af6ab5fSopenharmony_ci{ 7483af6ab5fSopenharmony_ci if (!param->AsETSParameterExpression()->IsDefault()) { 7493af6ab5fSopenharmony_ci checker->LogTypeError({"Expected initializer for ", param->AsETSParameterExpression()->Ident()->Name()}, 7503af6ab5fSopenharmony_ci param->Start()); 7513af6ab5fSopenharmony_ci } 7523af6ab5fSopenharmony_ci 7533af6ab5fSopenharmony_ci ArenaVector<Type *> types(checker->Allocator()->Adapter()); 7543af6ab5fSopenharmony_ci types.push_back(InstantiateBoxedPrimitiveType( 7553af6ab5fSopenharmony_ci checker, param, param->AsETSParameterExpression()->TypeAnnotation()->GetType(checker))); 7563af6ab5fSopenharmony_ci 7573af6ab5fSopenharmony_ci if (param->AsETSParameterExpression()->Initializer()->IsUndefinedLiteral()) { 7583af6ab5fSopenharmony_ci types.push_back(checker->GlobalETSUndefinedType()); 7593af6ab5fSopenharmony_ci } 7603af6ab5fSopenharmony_ci 7613af6ab5fSopenharmony_ci return checker->CreateETSUnionType(Span<Type *const>(types)); 7623af6ab5fSopenharmony_ci} 7633af6ab5fSopenharmony_ci 7643af6ab5fSopenharmony_ciType *InstantiateBoxedPrimitiveType(ETSChecker *checker, ir::Expression *param, Type *paramType) 7653af6ab5fSopenharmony_ci{ 7663af6ab5fSopenharmony_ci if (paramType->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { 7673af6ab5fSopenharmony_ci auto node = checker->Relation()->GetNode(); 7683af6ab5fSopenharmony_ci checker->Relation()->SetNode(param); 7693af6ab5fSopenharmony_ci auto *const boxedTypeArg = checker->PrimitiveTypeAsETSBuiltinType(paramType); 7703af6ab5fSopenharmony_ci ASSERT(boxedTypeArg); 7713af6ab5fSopenharmony_ci paramType = 7723af6ab5fSopenharmony_ci boxedTypeArg->Instantiate(checker->Allocator(), checker->Relation(), checker->GetGlobalTypesHolder()); 7733af6ab5fSopenharmony_ci checker->Relation()->SetNode(node); 7743af6ab5fSopenharmony_ci } 7753af6ab5fSopenharmony_ci 7763af6ab5fSopenharmony_ci return paramType; 7773af6ab5fSopenharmony_ci} 7783af6ab5fSopenharmony_ci} // namespace ark::es2panda::checker 779