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