1/** 2 * Copyright (c) 2021-2024 - Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "boxingConverter.h" 17#include "checker/ETSchecker.h" 18#include "checker/ets/typeRelationContext.h" 19#include "checker/types/ets/etsDynamicType.h" 20#include "checker/types/ets/etsObjectType.h" 21#include "checker/types/ets/etsTupleType.h" 22#include "ir/astNode.h" 23#include "ir/typeNode.h" 24#include "ir/base/classDefinition.h" 25#include "ir/base/classElement.h" 26#include "ir/base/classProperty.h" 27#include "ir/base/classStaticBlock.h" 28#include "ir/base/methodDefinition.h" 29#include "ir/base/scriptFunction.h" 30#include "ir/ets/etsNewClassInstanceExpression.h" 31#include "ir/ets/etsTypeReference.h" 32#include "ir/ets/etsTypeReferencePart.h" 33#include "ir/ets/etsUnionType.h" 34#include "ir/expressions/assignmentExpression.h" 35#include "ir/expressions/callExpression.h" 36#include "ir/expressions/functionExpression.h" 37#include "ir/expressions/identifier.h" 38#include "ir/expressions/memberExpression.h" 39#include "ir/statements/blockStatement.h" 40#include "ir/statements/expressionStatement.h" 41#include "ir/statements/variableDeclarator.h" 42#include "ir/ts/tsClassImplements.h" 43#include "ir/ts/tsInterfaceDeclaration.h" 44#include "ir/ts/tsInterfaceHeritage.h" 45#include "ir/ts/tsTypeParameter.h" 46#include "ir/ts/tsTypeParameterDeclaration.h" 47#include "varbinder/declaration.h" 48#include "varbinder/variableFlags.h" 49#include "generated/signatures.h" 50 51namespace ark::es2panda::checker { 52ETSObjectType *ETSChecker::GetSuperType(ETSObjectType *type) 53{ 54 ComputeSuperType(type); 55 if (type == GlobalETSObjectType()) { 56 return GlobalETSObjectType(); 57 } 58 if (type->SuperType() == nullptr) { 59 return nullptr; 60 } 61 return type->SuperType(); 62} 63 64bool ETSChecker::ComputeSuperType(ETSObjectType *type) 65{ 66 if (type->HasObjectFlag(ETSObjectFlags::RESOLVED_SUPER)) { 67 return true; 68 } 69 70 ASSERT(type->Variable() && type->GetDeclNode()->IsClassDefinition()); 71 auto *classDef = type->GetDeclNode()->AsClassDefinition(); 72 73 if (classDef->Super() == nullptr) { 74 type->AddObjectFlag(ETSObjectFlags::RESOLVED_SUPER); 75 if (type != GlobalETSObjectType()) { 76 type->SetSuperType(GlobalETSObjectType()); 77 } 78 return true; 79 } 80 81 TypeStackElement tse(this, type, {"Cyclic inheritance involving ", type->Name(), "."}, classDef->Ident()->Start()); 82 if (tse.HasTypeError()) { 83 type->AddObjectFlag(ETSObjectFlags::RESOLVED_SUPER); 84 return false; 85 } 86 87 Type *superType = classDef->Super()->AsTypeNode()->GetType(this); 88 if (superType == nullptr) { 89 return true; 90 } 91 if (!superType->IsETSObjectType() || !superType->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::CLASS)) { 92 LogTypeError({"The super type of '", classDef->Ident()->Name(), "' class is not extensible."}, 93 classDef->Super()->Start()); 94 type->SetSuperType(GlobalETSObjectType()); 95 return true; 96 } 97 98 ETSObjectType *superObj = superType->AsETSObjectType(); 99 100 // struct node has class definition, too 101 if (superObj->GetDeclNode()->Parent()->IsETSStructDeclaration()) { 102 LogTypeError({"struct ", classDef->Ident()->Name(), " is not extensible."}, classDef->Super()->Start()); 103 } 104 105 if (superObj->GetDeclNode()->IsFinal()) { 106 LogTypeError("Cannot inherit with 'final' modifier.", classDef->Super()->Start()); 107 /* It still makes sense to treat superObj as the supertype in future checking */ 108 } 109 if (GetSuperType(superObj) == nullptr) { 110 superObj = GlobalETSObjectType(); 111 } 112 type->SetSuperType(superObj); 113 type->AddObjectFlag(ETSObjectFlags::RESOLVED_SUPER); 114 return true; 115} 116 117void ETSChecker::ValidateImplementedInterface(ETSObjectType *type, Type *interface, 118 std::unordered_set<Type *> *extendsSet, const lexer::SourcePosition &pos) 119{ 120 if (!interface->IsETSObjectType() || !interface->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::INTERFACE)) { 121 LogTypeError("Interface expected here.", pos); 122 return; 123 } 124 125 if (!extendsSet->insert(interface).second) { 126 LogTypeError("Repeated interface.", pos); 127 } 128 129 type->AddInterface(interface->AsETSObjectType()); 130 GetInterfaces(interface->AsETSObjectType()); 131} 132 133void ETSChecker::GetInterfacesOfClass(ETSObjectType *type) 134{ 135 if (type->HasObjectFlag(ETSObjectFlags::RESOLVED_INTERFACES)) { 136 return; 137 } 138 139 const auto *declNode = type->GetDeclNode()->AsClassDefinition(); 140 141 std::unordered_set<Type *> extendsSet; 142 for (auto *it : declNode->Implements()) { 143 ValidateImplementedInterface(type, it->Expr()->AsTypeNode()->GetType(this), &extendsSet, it->Start()); 144 } 145 type->AddObjectFlag(ETSObjectFlags::RESOLVED_INTERFACES); 146} 147 148void ETSChecker::GetInterfacesOfInterface(ETSObjectType *type) 149{ 150 if (type->HasObjectFlag(ETSObjectFlags::RESOLVED_INTERFACES)) { 151 return; 152 } 153 154 const auto *declNode = type->GetDeclNode()->AsTSInterfaceDeclaration(); 155 156 TypeStackElement tse(this, type, {"Cyclic inheritance involving ", type->Name(), "."}, declNode->Id()->Start()); 157 if (tse.HasTypeError()) { 158 type->Interfaces().clear(); 159 return; 160 } 161 162 std::unordered_set<Type *> extendsSet; 163 for (auto *it : declNode->Extends()) { 164 ValidateImplementedInterface(type, it->Expr()->AsTypeNode()->GetType(this), &extendsSet, it->Start()); 165 } 166 type->AddObjectFlag(ETSObjectFlags::RESOLVED_INTERFACES); 167} 168 169ArenaVector<ETSObjectType *> ETSChecker::GetInterfaces(ETSObjectType *type) 170{ 171 ASSERT(type->GetDeclNode()->IsClassDefinition() || type->GetDeclNode()->IsTSInterfaceDeclaration()); 172 173 if (type->GetDeclNode()->IsClassDefinition()) { 174 GetInterfacesOfClass(type); 175 } else { 176 GetInterfacesOfInterface(type); 177 } 178 179 return type->Interfaces(); 180} 181 182std::pair<ArenaVector<Type *>, bool> ETSChecker::CreateUnconstrainedTypeParameters( 183 ir::TSTypeParameterDeclaration const *typeParams) 184{ 185 bool ok = true; 186 ArenaVector<Type *> result {Allocator()->Adapter()}; 187 checker::ScopeContext scopeCtx(this, typeParams->Scope()); 188 189 // Note: we have to run pure check loop first to avoid endless loop because of possible circular dependencies 190 Type2TypeMap extends {}; 191 TypeSet typeParameterDecls {}; 192 for (auto *const typeParam : typeParams->Params()) { 193 ok &= CheckDefaultTypeParameter(typeParam, typeParameterDecls); 194 if (auto *const constraint = typeParam->Constraint(); 195 constraint != nullptr && constraint->IsETSTypeReference() && 196 constraint->AsETSTypeReference()->Part()->Name()->IsIdentifier()) { 197 ok &= CheckTypeParameterConstraint(typeParam, extends); 198 } 199 } 200 201 for (auto *const typeParam : typeParams->Params()) { 202 result.emplace_back(SetUpParameterType(typeParam)); 203 } 204 205 return {result, ok}; 206} 207 208void ETSChecker::AssignTypeParameterConstraints(ir::TSTypeParameterDeclaration const *typeParams) 209{ 210 ConstraintCheckScope ctScope(this); 211 // The type parameter might be used in the constraint, like 'K extend Comparable<K>', 212 // so we need to create their type first, then set up the constraint 213 for (auto *const param : typeParams->Params()) { 214 SetUpTypeParameterConstraint(param); 215 } 216 ctScope.TryCheckConstraints(); 217} 218 219bool ETSChecker::CheckDefaultTypeParameter(const ir::TSTypeParameter *param, TypeSet &typeParameterDecls) 220{ 221 bool ok = true; 222 const auto typeParamVar = param->Name()->Variable(); 223 if (typeParameterDecls.count(typeParamVar) != 0U) { 224 LogTypeError({"Duplicate type parameter '", param->Name()->Name().Utf8(), "'."}, param->Start()); 225 return false; 226 } 227 228 std::function<void(ir::AstNode *)> checkDefault = [&typeParameterDecls, this, &checkDefault, 229 &ok](ir::AstNode *node) { 230 if (node->IsETSTypeReferencePart()) { 231 ir::ETSTypeReferencePart *defaultTypePart = node->AsETSTypeReferencePart(); 232 if (defaultTypePart->Name()->Variable()->TsType() == nullptr && 233 (defaultTypePart->Name()->Variable()->Flags() & varbinder::VariableFlags::TYPE_PARAMETER) != 0U && 234 typeParameterDecls.count(defaultTypePart->Name()->Variable()) == 0U) { 235 LogTypeError({"Type Parameter ", defaultTypePart->Name()->AsIdentifier()->Name().Utf8(), 236 " should be defined before use."}, 237 node->Start()); 238 ok = false; 239 } 240 } 241 node->Iterate(checkDefault); 242 }; 243 244 if (param->DefaultType() != nullptr) { 245 param->DefaultType()->Iterate(checkDefault); 246 } 247 248 typeParameterDecls.emplace(typeParamVar); 249 return ok; 250} 251 252bool ETSChecker::CheckTypeParameterConstraint(ir::TSTypeParameter *param, Type2TypeMap &extends) 253{ 254 const auto typeParamVar = param->Name()->Variable(); 255 const auto constraintVar = param->Constraint()->AsETSTypeReference()->Part()->Name()->Variable(); 256 extends.emplace(typeParamVar, constraintVar); 257 auto it = extends.find(constraintVar); 258 while (it != extends.cend()) { 259 if (it->second == typeParamVar) { 260 LogTypeError({"Type parameter '", param->Name()->Name().Utf8(), "' has circular constraint dependency."}, 261 param->Constraint()->Start()); 262 return false; 263 } 264 it = extends.find(it->second); 265 } 266 267 return true; 268} 269 270void ETSChecker::SetUpTypeParameterConstraint(ir::TSTypeParameter *const param) 271{ 272 ETSTypeParameter *const paramType = param->Name()->Variable()->TsType()->AsETSTypeParameter(); 273 auto const traverseReferenced = 274 [this, scope = param->Parent()->AsTSTypeParameterDeclaration()->Scope()](ir::TypeNode *typeNode) { 275 if (!typeNode->IsETSTypeReference()) { 276 return; 277 } 278 const auto typeName = typeNode->AsETSTypeReference()->Part()->Name()->AsIdentifier()->Name(); 279 auto *const found = scope->FindLocal(typeName, varbinder::ResolveBindingOptions::BINDINGS); 280 if (found != nullptr) { 281 SetUpTypeParameterConstraint(found->Declaration()->Node()->AsTSTypeParameter()); 282 } 283 }; 284 285 if (param->Constraint() != nullptr) { 286 traverseReferenced(param->Constraint()); 287 auto *const constraint = param->Constraint()->GetType(this); 288 // invalid: T extends int[] 289 if (!constraint->IsETSObjectType() && !constraint->IsETSTypeParameter() && !constraint->IsETSUnionType()) { 290 LogTypeError("Extends constraint must be an object", param->Constraint()->Start()); 291 } 292 paramType->SetConstraintType(constraint); 293 } else { 294 paramType->SetConstraintType(GlobalETSNullishObjectType()); 295 } 296 297 if (param->DefaultType() != nullptr) { 298 traverseReferenced(param->DefaultType()); 299 // NOTE: #14993 ensure default matches constraint 300 paramType->SetDefaultType(MaybePromotedBuiltinType(param->DefaultType()->GetType(this))); 301 } 302} 303 304ETSTypeParameter *ETSChecker::SetUpParameterType(ir::TSTypeParameter *const param) 305{ 306 if (param->Name()->Variable() != nullptr && param->Name()->Variable()->TsType() != nullptr) { 307 ASSERT(param->Name()->Variable()->TsType()->IsETSTypeParameter()); 308 return param->Name()->Variable()->TsType()->AsETSTypeParameter(); 309 } 310 311 auto *const paramType = CreateTypeParameter(); 312 313 paramType->AddTypeFlag(TypeFlag::GENERIC); 314 paramType->SetDeclNode(param); 315 paramType->SetVariable(param->Variable()); 316 // NOTE: #15026 recursive type parameter workaround 317 paramType->SetConstraintType(GlobalETSNullishObjectType()); 318 319 param->Name()->Variable()->SetTsType(paramType); 320 return paramType; 321} 322 323void ETSChecker::CreateTypeForClassOrInterfaceTypeParameters(ETSObjectType *type) 324{ 325 if (type->HasObjectFlag(ETSObjectFlags::RESOLVED_TYPE_PARAMS)) { 326 return; 327 } 328 329 ir::TSTypeParameterDeclaration *typeParams = type->GetDeclNode()->IsClassDefinition() 330 ? type->GetDeclNode()->AsClassDefinition()->TypeParams() 331 : type->GetDeclNode()->AsTSInterfaceDeclaration()->TypeParams(); 332 auto [typeParamTypes, ok] = CreateUnconstrainedTypeParameters(typeParams); 333 type->SetTypeArguments(std::move(typeParamTypes)); 334 if (ok) { 335 AssignTypeParameterConstraints(typeParams); 336 } 337 type->AddObjectFlag(ETSObjectFlags::RESOLVED_TYPE_PARAMS); 338 type->AddObjectFlag(ETSObjectFlags::INCOMPLETE_INSTANTIATION); 339} 340 341ETSObjectType *ETSChecker::BuildBasicInterfaceProperties(ir::TSInterfaceDeclaration *interfaceDecl) 342{ 343 auto *var = interfaceDecl->Id()->Variable(); 344 ASSERT(var); 345 346 checker::ETSObjectType *interfaceType {}; 347 if (var->TsType() == nullptr) { 348 interfaceType = CreateETSObjectType(var->Name(), interfaceDecl, checker::ETSObjectFlags::INTERFACE); 349 interfaceType->SetVariable(var); 350 var->SetTsType(interfaceType); 351 } else { 352 interfaceType = var->TsType()->AsETSObjectType(); 353 } 354 355 ConstraintCheckScope ctScope(this); 356 if (interfaceDecl->TypeParams() != nullptr) { 357 interfaceType->AddTypeFlag(TypeFlag::GENERIC); 358 CreateTypeForClassOrInterfaceTypeParameters(interfaceType); 359 } 360 361 GetInterfaces(interfaceType); 362 interfaceType->SetSuperType(GlobalETSObjectType()); 363 ctScope.TryCheckConstraints(); 364 return interfaceType; 365} 366 367ETSObjectType *ETSChecker::BuildBasicClassProperties(ir::ClassDefinition *classDef) 368{ 369 if (classDef->IsFinal() && classDef->IsAbstract()) { 370 LogTypeError("Cannot use both 'final' and 'abstract' modifiers.", classDef->Start()); 371 } 372 373 auto *var = classDef->Ident()->Variable(); 374 ASSERT(var); 375 376 const util::StringView &className = classDef->Ident()->Name(); 377 378 checker::ETSObjectType *classType {}; 379 if (var->TsType() == nullptr) { 380 classType = CreateETSObjectType(className, classDef, checker::ETSObjectFlags::CLASS); 381 classType->SetVariable(var); 382 var->SetTsType(classType); 383 if (classDef->IsAbstract()) { 384 classType->AddObjectFlag(checker::ETSObjectFlags::ABSTRACT); 385 } 386 } else { 387 classType = var->TsType()->AsETSObjectType(); 388 } 389 390 classDef->SetTsType(classType); 391 392 ConstraintCheckScope ctScope(this); 393 if (classDef->TypeParams() != nullptr) { 394 classType->AddTypeFlag(TypeFlag::GENERIC); 395 CreateTypeForClassOrInterfaceTypeParameters(classType); 396 } 397 398 auto *enclosingClass = Context().ContainingClass(); 399 classType->SetEnclosingType(enclosingClass); 400 CheckerStatus newStatus = CheckerStatus::IN_CLASS; 401 402 if (classDef->IsInner()) { 403 newStatus |= CheckerStatus::INNER_CLASS; 404 classType->AddObjectFlag(checker::ETSObjectFlags::INNER); 405 } 406 407 auto savedContext = checker::SavedCheckerContext(this, newStatus, classType); 408 409 if (!classType->HasObjectFlag(ETSObjectFlags::RESOLVED_SUPER)) { 410 GetSuperType(classType); 411 GetInterfaces(classType); 412 } 413 ctScope.TryCheckConstraints(); 414 return classType; 415} 416 417ETSObjectType *ETSChecker::BuildAnonymousClassProperties(ir::ClassDefinition *classDef, ETSObjectType *superType) 418{ 419 auto classType = CreateETSObjectType(classDef->Ident()->Name(), classDef, checker::ETSObjectFlags::CLASS); 420 classDef->SetTsType(classType); 421 classType->SetSuperType(superType); 422 classType->AddObjectFlag(checker::ETSObjectFlags::RESOLVED_SUPER); 423 424 return classType; 425} 426 427static void ResolveDeclaredFieldsOfObject(ETSChecker *checker, const ETSObjectType *type, varbinder::ClassScope *scope) 428{ 429 for (auto &[_, it] : scope->InstanceFieldScope()->Bindings()) { 430 (void)_; 431 ASSERT(it->Declaration()->Node()->IsClassProperty()); 432 auto *classProp = it->Declaration()->Node()->AsClassProperty(); 433 it->AddFlag(checker->GetAccessFlagFromNode(classProp)); 434 type->AddProperty<PropertyType::INSTANCE_FIELD>(it->AsLocalVariable()); 435 } 436 437 for (auto &[_, it] : scope->StaticFieldScope()->Bindings()) { 438 (void)_; 439 ASSERT(it->Declaration()->Node()->IsClassProperty()); 440 auto *classProp = it->Declaration()->Node()->AsClassProperty(); 441 it->AddFlag(checker->GetAccessFlagFromNode(classProp)); 442 type->AddProperty<PropertyType::STATIC_FIELD>(it->AsLocalVariable()); 443 } 444} 445 446static void ResolveDeclaredMethodsOfObject(ETSChecker *checker, const ETSObjectType *type, varbinder::ClassScope *scope) 447{ 448 for (auto &[_, it] : scope->InstanceMethodScope()->Bindings()) { 449 (void)_; 450 auto *method = it->Declaration()->Node()->AsMethodDefinition(); 451 auto *function = method->Function(); 452 453 if (function->IsProxy()) { 454 continue; 455 } 456 457 it->AddFlag(checker->GetAccessFlagFromNode(method)); 458 auto *funcType = checker->BuildMethodSignature(method); 459 it->SetTsType(funcType); 460 funcType->SetVariable(it); 461 method->SetTsType(funcType); 462 type->AddProperty<PropertyType::INSTANCE_METHOD>(it->AsLocalVariable()); 463 } 464 465 for (auto &[_, it] : scope->StaticMethodScope()->Bindings()) { 466 (void)_; 467 if (!it->Declaration()->Node()->IsMethodDefinition()) { 468 continue; 469 } 470 471 auto *method = it->Declaration()->Node()->AsMethodDefinition(); 472 auto *function = method->Function(); 473 474 if (function->IsProxy()) { 475 continue; 476 } 477 478 it->AddFlag(checker->GetAccessFlagFromNode(method)); 479 auto *funcType = checker->BuildMethodSignature(method); 480 it->SetTsType(funcType); 481 funcType->SetVariable(it); 482 method->SetTsType(funcType); 483 484 if (method->IsConstructor()) { 485 type->AddConstructSignature(funcType->CallSignatures()); 486 continue; 487 } 488 489 type->AddProperty<PropertyType::STATIC_METHOD>(it->AsLocalVariable()); 490 } 491} 492 493static void ResolveDeclaredDeclsOfObject(ETSChecker *checker, const ETSObjectType *type, varbinder::ClassScope *scope) 494{ 495 for (auto &[_, it] : scope->InstanceDeclScope()->Bindings()) { 496 (void)_; 497 it->AddFlag(checker->GetAccessFlagFromNode(it->Declaration()->Node())); 498 type->AddProperty<PropertyType::INSTANCE_DECL>(it->AsLocalVariable()); 499 } 500 501 for (auto &[_, it] : scope->StaticDeclScope()->Bindings()) { 502 (void)_; 503 it->AddFlag(checker->GetAccessFlagFromNode(it->Declaration()->Node())); 504 type->AddProperty<PropertyType::STATIC_DECL>(it->AsLocalVariable()); 505 } 506} 507 508void ETSChecker::ResolveDeclaredMembersOfObject(const ETSObjectType *type) 509{ 510 if (type->IsPropertiesInstantiated()) { 511 return; 512 } 513 514 auto *declNode = type->GetDeclNode(); 515 516 if (declNode == nullptr || !(declNode->IsClassDefinition() || declNode->IsTSInterfaceDeclaration())) { 517 return; 518 } 519 520 if (type->IsGeneric() && type != type->GetOriginalBaseType()) { 521 const auto *baseType = type->GetOriginalBaseType(); 522 auto *baseDeclNode = baseType->GetDeclNode(); 523 checker::CheckerStatus baseStatus = baseDeclNode->IsTSInterfaceDeclaration() 524 ? checker::CheckerStatus::IN_INTERFACE 525 : checker::CheckerStatus::IN_CLASS; 526 auto baseScope = baseDeclNode->IsTSInterfaceDeclaration() ? baseDeclNode->AsTSInterfaceDeclaration()->Scope() 527 : baseDeclNode->AsClassDefinition()->Scope(); 528 auto savedContext = checker::SavedCheckerContext(this, baseStatus, baseType); 529 checker::ScopeContext scopeCtx(this, baseScope); 530 ResolveDeclaredMembersOfObject(baseType); 531 return; 532 } 533 534 checker::CheckerStatus status = 535 declNode->IsTSInterfaceDeclaration() ? checker::CheckerStatus::IN_INTERFACE : checker::CheckerStatus::IN_CLASS; 536 auto *scope = declNode->IsTSInterfaceDeclaration() ? declNode->AsTSInterfaceDeclaration()->Scope() 537 : declNode->AsClassDefinition()->Scope(); 538 auto savedContext = checker::SavedCheckerContext(this, status, type); 539 checker::ScopeContext scopeCtx(this, scope); 540 541 ResolveDeclaredFieldsOfObject(this, type, scope->AsClassScope()); 542 ResolveDeclaredMethodsOfObject(this, type, scope->AsClassScope()); 543 ResolveDeclaredDeclsOfObject(this, type, scope->AsClassScope()); 544} 545 546bool ETSChecker::HasETSFunctionType(ir::TypeNode *typeAnnotation) 547{ 548 if (typeAnnotation->IsETSFunctionType()) { 549 return true; 550 } 551 std::unordered_set<ir::TypeNode *> childrenSet; 552 553 if (!typeAnnotation->IsETSTypeReference()) { 554 return false; 555 } 556 557 auto const addTypeAlias = [&childrenSet, &typeAnnotation](varbinder::Decl *typeDecl) { 558 typeAnnotation = typeDecl->Node()->AsTSTypeAliasDeclaration()->TypeAnnotation(); 559 if (!typeAnnotation->IsETSUnionType()) { 560 childrenSet.insert(typeAnnotation); 561 return; 562 } 563 for (auto *type : typeAnnotation->AsETSUnionType()->Types()) { 564 if (type->IsETSTypeReference()) { 565 childrenSet.insert(type); 566 } 567 } 568 }; 569 570 auto *typeDecl = typeAnnotation->AsETSTypeReference()->Part()->Name()->AsIdentifier()->Variable()->Declaration(); 571 if (typeDecl != nullptr && typeDecl->IsTypeAliasDecl()) { 572 addTypeAlias(typeDecl); 573 } 574 575 for (auto *child : childrenSet) { 576 if (HasETSFunctionType(child)) { 577 return true; 578 } 579 } 580 return false; 581} 582 583std::vector<Signature *> ETSChecker::CollectAbstractSignaturesFromObject(const ETSObjectType *objType) 584{ 585 std::vector<Signature *> abstracts; 586 for (const auto &prop : objType->Methods()) { 587 GetTypeOfVariable(prop); 588 589 if (!prop->TsType()->IsETSFunctionType()) { 590 continue; 591 } 592 593 for (auto *sig : prop->TsType()->AsETSFunctionType()->CallSignatures()) { 594 if (sig->HasSignatureFlag(SignatureFlags::ABSTRACT) && !sig->HasSignatureFlag(SignatureFlags::PRIVATE)) { 595 abstracts.push_back(sig); 596 } 597 } 598 } 599 600 return abstracts; 601} 602 603void ETSChecker::CreateFunctionTypesFromAbstracts(const std::vector<Signature *> &abstracts, 604 ArenaVector<ETSFunctionType *> *target) 605{ 606 for (auto *it : abstracts) { 607 auto name = it->Function()->Id()->Name(); 608 auto *found = FindFunctionInVectorGivenByName(name, *target); 609 if (found != nullptr) { 610 found->AddCallSignature(it); 611 continue; 612 } 613 614 auto *created = CreateETSFunctionType(it); 615 target->push_back(created); 616 } 617} 618 619void ETSChecker::ComputeAbstractsFromInterface(ETSObjectType *interfaceType) 620{ 621 auto cached = cachedComputedAbstracts_.find(interfaceType); 622 if (cached != cachedComputedAbstracts_.end()) { 623 return; 624 } 625 626 for (auto *it : interfaceType->Interfaces()) { 627 ComputeAbstractsFromInterface(it); 628 } 629 630 ArenaVector<ETSFunctionType *> merged(Allocator()->Adapter()); 631 CreateFunctionTypesFromAbstracts(CollectAbstractSignaturesFromObject(interfaceType), &merged); 632 std::unordered_set<ETSObjectType *> abstractInheritanceTarget; 633 634 for (auto *interface : interfaceType->Interfaces()) { 635 auto found = cachedComputedAbstracts_.find(interface); 636 ASSERT(found != cachedComputedAbstracts_.end()); 637 638 if (!abstractInheritanceTarget.insert(found->first).second) { 639 continue; 640 } 641 642 MergeComputedAbstracts(merged, found->second.first); 643 644 for (auto *base : found->second.second) { 645 abstractInheritanceTarget.insert(base); 646 } 647 } 648 649 cachedComputedAbstracts_.insert({interfaceType, {merged, abstractInheritanceTarget}}); 650} 651 652ArenaVector<ETSFunctionType *> &ETSChecker::GetAbstractsForClass(ETSObjectType *classType) 653{ 654 ArenaVector<ETSFunctionType *> merged(Allocator()->Adapter()); 655 CreateFunctionTypesFromAbstracts(CollectAbstractSignaturesFromObject(classType), &merged); 656 657 std::unordered_set<ETSObjectType *> abstractInheritanceTarget; 658 if (classType->SuperType() != nullptr) { 659 auto base = cachedComputedAbstracts_.find(classType->SuperType()); 660 ASSERT(base != cachedComputedAbstracts_.end()); 661 MergeComputedAbstracts(merged, base->second.first); 662 663 abstractInheritanceTarget.insert(base->first); 664 for (auto *it : base->second.second) { 665 abstractInheritanceTarget.insert(it); 666 } 667 } 668 669 for (auto *it : classType->Interfaces()) { 670 ComputeAbstractsFromInterface(it); 671 auto found = cachedComputedAbstracts_.find(it); 672 ASSERT(found != cachedComputedAbstracts_.end()); 673 674 if (!abstractInheritanceTarget.insert(found->first).second) { 675 continue; 676 } 677 678 MergeComputedAbstracts(merged, found->second.first); 679 680 for (auto *interface : found->second.second) { 681 abstractInheritanceTarget.insert(interface); 682 } 683 } 684 685 return cachedComputedAbstracts_.insert({classType, {merged, abstractInheritanceTarget}}).first->second.first; 686} 687 688static bool DoObjectImplementInterface(const ETSObjectType *interfaceType, const ETSObjectType *target) 689{ 690 return std::any_of(interfaceType->Interfaces().begin(), interfaceType->Interfaces().end(), 691 [&target](auto *it) { return it == target || DoObjectImplementInterface(it, target); }); 692} 693 694static bool CheckIfInterfaceCanBeFoundOnDifferentPaths(const ETSObjectType *classType, 695 const ETSObjectType *interfaceType) 696{ 697 return std::count_if(classType->Interfaces().begin(), classType->Interfaces().end(), 698 [&interfaceType](auto *it) { return DoObjectImplementInterface(it, interfaceType); }) == 1; 699} 700 701static void GetInterfacesOfClass(ETSObjectType *type, ArenaVector<ETSObjectType *> &interfaces) 702{ 703 for (auto &classInterface : type->Interfaces()) { 704 if (std::find(interfaces.begin(), interfaces.end(), classInterface) == interfaces.end()) { 705 interfaces.emplace_back(classInterface); 706 GetInterfacesOfClass(classInterface, interfaces); 707 } 708 } 709} 710 711void ETSChecker::CheckIfOverrideIsValidInInterface(const ETSObjectType *classType, Signature *sig, 712 ir::ScriptFunction *func) 713{ 714 if (AreOverrideEquivalent(func->Signature(), sig) && func->IsStatic() == sig->Function()->IsStatic()) { 715 if (CheckIfInterfaceCanBeFoundOnDifferentPaths(classType, func->Signature()->Owner()) && 716 (Relation()->IsSupertypeOf(func->Signature()->Owner(), sig->Owner()) || 717 Relation()->IsSupertypeOf(sig->Owner(), func->Signature()->Owner()))) { 718 return; 719 } 720 721 LogTypeError({"Method '", sig->Function()->Id()->Name(), "' is declared in ", sig->Owner()->Name(), " and ", 722 func->Signature()->Owner()->Name(), " interfaces."}, 723 classType->GetDeclNode()->Start()); 724 } 725} 726 727void ETSChecker::CheckFunctionRedeclarationInInterface(const ETSObjectType *classType, 728 ArenaVector<Signature *> &similarSignatures, 729 ir::ScriptFunction *func) 730{ 731 for (auto *const sig : similarSignatures) { 732 if (sig != func->Signature() && func->HasBody()) { 733 if (classType == sig->Owner()) { 734 return; 735 } 736 737 CheckIfOverrideIsValidInInterface(classType, sig, func); 738 } 739 } 740 741 similarSignatures.push_back(func->Signature()); 742} 743 744void ETSChecker::CheckInterfaceFunctions(ETSObjectType *classType) 745{ 746 ArenaVector<ETSObjectType *> interfaces(Allocator()->Adapter()); 747 ArenaVector<Signature *> similarSignatures(Allocator()->Adapter()); 748 interfaces.emplace_back(classType); 749 checker::GetInterfacesOfClass(classType, interfaces); 750 751 for (auto *const &interface : interfaces) { 752 for (auto *const &prop : interface->Methods()) { 753 if (auto *const func = prop->Declaration()->Node()->AsMethodDefinition()->Function(); 754 func->Body() != nullptr) { 755 CheckFunctionRedeclarationInInterface(classType, similarSignatures, func); 756 } 757 } 758 } 759} 760 761/// Traverse the interface inheritance tree and collects implemented methods 762void ETSChecker::CollectImplementedMethodsFromInterfaces(ETSObjectType *classType, 763 std::vector<Signature *> *implementedSignatures, 764 const ArenaVector<ETSFunctionType *> &abstractsToBeImplemented) 765{ 766 std::vector<ETSObjectType *> collectedInterfaces; 767 768 for (auto &classInterface : classType->Interfaces()) { 769 collectedInterfaces.emplace_back(classInterface); 770 } 771 772 size_t index = 0; 773 774 while (index < collectedInterfaces.size()) { 775 for (auto &it : abstractsToBeImplemented) { 776 for (const auto &prop : collectedInterfaces[index]->Methods()) { 777 GetTypeOfVariable(prop); 778 AddImplementedSignature(implementedSignatures, prop, it); 779 } 780 } 781 782 for (auto ¤tInterfaceChild : collectedInterfaces[index]->Interfaces()) { 783 collectedInterfaces.emplace_back(currentInterfaceChild); 784 } 785 786 index++; 787 } 788} 789 790void ETSChecker::ValidateAbstractSignature(ArenaVector<ETSFunctionType *>::iterator &it, 791 ArenaVector<ETSFunctionType *> &abstractsToBeImplemented, 792 const std::vector<Signature *> &implementedSignatures, 793 bool &functionOverridden, Accessor &isGetSetExternal) 794{ 795 for (auto abstractSignature = (*it)->CallSignatures().begin(); 796 abstractSignature != (*it)->CallSignatures().end();) { 797 bool foundSignature = false; 798 isGetSetExternal.isGetter = (*abstractSignature)->HasSignatureFlag(SignatureFlags::GETTER); 799 isGetSetExternal.isSetter = (*abstractSignature)->HasSignatureFlag(SignatureFlags::SETTER); 800 isGetSetExternal.isExternal = (*abstractSignature)->Function()->IsExternal(); 801 for (auto *const implemented : implementedSignatures) { 802 if (implemented->HasSignatureFlag(SignatureFlags::NEED_RETURN_TYPE)) { 803 implemented->OwnerVar()->Declaration()->Node()->Check(this); 804 } 805 Signature *substImplemented = AdjustForTypeParameters(*abstractSignature, implemented); 806 807 if (substImplemented == nullptr) { 808 continue; 809 } 810 811 if (!AreOverrideEquivalent(*abstractSignature, substImplemented) || 812 !IsReturnTypeSubstitutable(substImplemented, *abstractSignature)) { 813 continue; 814 } 815 816 if ((*it)->CallSignatures().size() > 1) { 817 abstractSignature = (*it)->CallSignatures().erase(abstractSignature); 818 foundSignature = true; 819 } else { 820 it = abstractsToBeImplemented.erase(it); 821 functionOverridden = true; 822 } 823 824 break; 825 } 826 827 if (functionOverridden) { 828 break; 829 } 830 831 if (!foundSignature) { 832 ++abstractSignature; 833 } 834 } 835} 836 837void ETSChecker::ValidateNonOverriddenFunction(ETSObjectType *classType, ArenaVector<ETSFunctionType *>::iterator &it, 838 ArenaVector<ETSFunctionType *> &abstractsToBeImplemented, 839 bool &functionOverridden, const Accessor &isGetSet) 840{ 841 auto superClassType = classType->SuperType(); 842 while (!functionOverridden && superClassType != nullptr) { 843 for (auto *field : superClassType->Fields()) { 844 if (field->Name() == (*it)->Name()) { 845 auto *newProp = 846 field->Declaration()->Node()->Clone(Allocator(), classType->GetDeclNode())->AsClassProperty(); 847 newProp->AddModifier(ir::ModifierFlags::SUPER_OWNER); 848 newProp->AddModifier(isGetSet.isGetter && isGetSet.isSetter ? ir::ModifierFlags::GETTER_SETTER 849 : isGetSet.isGetter ? ir::ModifierFlags::GETTER 850 : ir::ModifierFlags::SETTER); 851 auto *newFieldDecl = Allocator()->New<varbinder::LetDecl>(newProp->Key()->AsIdentifier()->Name()); 852 newFieldDecl->BindNode(newProp); 853 854 auto newFieldVar = classType->GetDeclNode() 855 ->Scope() 856 ->AsClassScope() 857 ->InstanceFieldScope() 858 ->AddDecl(Allocator(), newFieldDecl, ScriptExtension::ETS) 859 ->AsLocalVariable(); 860 newFieldVar->AddFlag(varbinder::VariableFlags::PROPERTY); 861 newFieldVar->AddFlag(varbinder::VariableFlags::PUBLIC); 862 classType->AddProperty<PropertyType::INSTANCE_FIELD>(newFieldVar); 863 it = abstractsToBeImplemented.erase(it); 864 functionOverridden = true; 865 break; 866 } 867 } 868 869 superClassType = superClassType->SuperType(); 870 } 871} 872 873void ETSChecker::ApplyModifiersAndRemoveImplementedAbstracts(ArenaVector<ETSFunctionType *>::iterator &it, 874 ArenaVector<ETSFunctionType *> &abstractsToBeImplemented, 875 ETSObjectType *classType, bool &functionOverridden, 876 const Accessor &isGetSetExternal) 877{ 878 for (auto *field : classType->Fields()) { 879 if (field->Name() == (*it)->Name()) { 880 field->Declaration()->Node()->AddModifier(isGetSetExternal.isGetter && isGetSetExternal.isSetter 881 ? ir::ModifierFlags::GETTER_SETTER 882 : isGetSetExternal.isGetter ? ir::ModifierFlags::GETTER 883 : ir::ModifierFlags::SETTER); 884 it = abstractsToBeImplemented.erase(it); 885 functionOverridden = true; 886 break; 887 } 888 } 889} 890 891void ETSChecker::ValidateAbstractMethodsToBeImplemented(ArenaVector<ETSFunctionType *> &abstractsToBeImplemented, 892 ETSObjectType *classType, 893 const std::vector<Signature *> &implementedSignatures) 894{ 895 SavedTypeRelationFlagsContext savedFlagsCtx(Relation(), TypeRelationFlag::NO_RETURN_TYPE_CHECK); 896 for (auto it = abstractsToBeImplemented.begin(); it != abstractsToBeImplemented.end();) { 897 bool functionOverridden = false; 898 Accessor isGetSetExternal; 899 900 ValidateAbstractSignature(it, abstractsToBeImplemented, implementedSignatures, functionOverridden, 901 isGetSetExternal); 902 903 if (functionOverridden) { 904 continue; 905 } 906 907 if (!isGetSetExternal.isGetter && !isGetSetExternal.isSetter) { 908 it++; 909 continue; 910 } 911 912 ApplyModifiersAndRemoveImplementedAbstracts(it, abstractsToBeImplemented, classType, functionOverridden, 913 isGetSetExternal); 914 915 if (functionOverridden) { 916 continue; 917 } 918 919 ValidateNonOverriddenFunction(classType, it, abstractsToBeImplemented, functionOverridden, isGetSetExternal); 920 921 if (!functionOverridden) { 922 it++; 923 } 924 } 925} 926 927void ETSChecker::MaybeReportErrorsForOverridingValidation(ArenaVector<ETSFunctionType *> &abstractsToBeImplemented, 928 ETSObjectType *classType, const lexer::SourcePosition &pos, 929 bool reportError) 930{ 931 if (!abstractsToBeImplemented.empty() && reportError) { 932 auto unimplementedSignature = abstractsToBeImplemented.front()->CallSignatures().front(); 933 auto containingObjectName = GetContainingObjectNameFromSignature(unimplementedSignature); 934 if (unimplementedSignature->HasSignatureFlag(SignatureFlags::GETTER)) { 935 LogTypeError({classType->Name(), " is not abstract and does not implement getter for ", 936 unimplementedSignature->Function()->Id()->Name(), " property in ", containingObjectName}, 937 pos); 938 return; 939 } 940 if (unimplementedSignature->HasSignatureFlag(SignatureFlags::SETTER)) { 941 LogTypeError({classType->Name(), " is not abstract and does not implement setter for ", 942 unimplementedSignature->Function()->Id()->Name(), " property in ", containingObjectName}, 943 pos); 944 return; 945 } 946 LogTypeError({classType->Name(), " is not abstract and does not override abstract method ", 947 unimplementedSignature->Function()->Id()->Name(), unimplementedSignature, " in ", 948 containingObjectName}, 949 pos); 950 } 951} 952 953void ETSChecker::ValidateOverriding(ETSObjectType *classType, const lexer::SourcePosition &pos) 954{ 955 if (classType->HasObjectFlag(ETSObjectFlags::CHECKED_COMPATIBLE_ABSTRACTS)) { 956 return; 957 } 958 959 bool throwError = true; 960 if (classType->HasObjectFlag(ETSObjectFlags::ABSTRACT)) { 961 throwError = false; 962 } 963 964 if (classType->SuperType() != nullptr) { 965 ValidateOverriding(classType->SuperType(), classType->SuperType()->GetDeclNode()->Start()); 966 } 967 968 auto &abstractsToBeImplemented = GetAbstractsForClass(classType); 969 std::vector<Signature *> implementedSignatures; 970 971 // Since interfaces can define function bodies we have to collect the implemented ones first 972 CollectImplementedMethodsFromInterfaces(classType, &implementedSignatures, abstractsToBeImplemented); 973 CheckInterfaceFunctions(classType); 974 975 auto *superIter = classType; 976 do { 977 for (auto &it : abstractsToBeImplemented) { 978 for (const auto &prop : superIter->Methods()) { 979 GetTypeOfVariable(prop); 980 AddImplementedSignature(&implementedSignatures, prop, it); 981 } 982 } 983 superIter = superIter->SuperType(); 984 } while (superIter != nullptr); 985 ValidateAbstractMethodsToBeImplemented(abstractsToBeImplemented, classType, implementedSignatures); 986 MaybeReportErrorsForOverridingValidation(abstractsToBeImplemented, classType, pos, throwError); 987 988 classType->AddObjectFlag(ETSObjectFlags::CHECKED_COMPATIBLE_ABSTRACTS); 989} 990 991void ETSChecker::AddImplementedSignature(std::vector<Signature *> *implementedSignatures, 992 varbinder::LocalVariable *function, ETSFunctionType *it) 993{ 994 if (!function->TsType()->IsETSFunctionType()) { 995 return; 996 } 997 998 for (auto signature : function->TsType()->AsETSFunctionType()->CallSignatures()) { 999 if (signature->Function()->IsAbstract() || signature->Function()->IsStatic()) { 1000 continue; 1001 } 1002 1003 if (signature->Function()->Id()->Name() == it->Name()) { 1004 implementedSignatures->emplace_back(signature); 1005 } 1006 } 1007} 1008 1009void ETSChecker::CheckLocalClass(ir::ClassDefinition *classDef, CheckerStatus &checkerStatus) 1010{ 1011 if (classDef->IsLocal()) { 1012 checkerStatus |= CheckerStatus::IN_LOCAL_CLASS; 1013 if (!classDef->Parent()->Parent()->IsBlockStatement()) { 1014 LogTypeError("Local classes must be defined between balanced braces", classDef->Start()); 1015 } 1016 } 1017} 1018 1019void ETSChecker::CheckClassDefinition(ir::ClassDefinition *classDef) 1020{ 1021 classDef->SetClassDefinitionChecked(); 1022 auto *classType = classDef->TsTypeOrError()->AsETSObjectType(); 1023 if (classType->SuperType() != nullptr) { 1024 classType->SuperType()->GetDeclNode()->Check(this); 1025 } 1026 1027 auto newStatus = checker::CheckerStatus::IN_CLASS; 1028 if (Context().ContainingClass() != classType) { 1029 classType->SetEnclosingType(Context().ContainingClass()); 1030 } 1031 1032 if (classDef->IsInner()) { 1033 newStatus |= CheckerStatus::INNER_CLASS; 1034 classType->AddObjectFlag(checker::ETSObjectFlags::INNER); 1035 } 1036 1037 classDef->IsGlobal() ? classType->AddObjectFlag(checker::ETSObjectFlags::GLOBAL) 1038 : CheckLocalClass(classDef, newStatus); 1039 1040 checker::ScopeContext scopeCtx(this, classDef->Scope()); 1041 auto savedContext = SavedCheckerContext(this, newStatus, classType); 1042 1043 ResolveDeclaredMembersOfObject(classType); 1044 1045 if (classDef->IsAbstract()) { 1046 AddStatus(checker::CheckerStatus::IN_ABSTRACT); 1047 classType->AddObjectFlag(checker::ETSObjectFlags::ABSTRACT); 1048 } 1049 1050 if (classDef->IsStatic() && !Context().ContainingClass()->HasObjectFlag(ETSObjectFlags::GLOBAL)) { 1051 AddStatus(checker::CheckerStatus::IN_STATIC_CONTEXT); 1052 } 1053 1054 // NOTE(gogabr): temporary, until we have proper bridges, see #16485 1055 // Don't check overriding for synthetic functional classes. 1056 if ((static_cast<ir::AstNode *>(classDef)->Modifiers() & ir::ModifierFlags::FUNCTIONAL) == 0) { 1057 ValidateOverriding(classType, classDef->Start()); 1058 } 1059 // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 1060 TransformProperties(classType); 1061 1062 for (auto *it : classDef->Body()) { 1063 if (it->IsClassProperty()) { 1064 it->Check(this); 1065 } 1066 } 1067 1068 for (auto *it : classDef->Body()) { 1069 if (!it->IsClassProperty()) { 1070 it->Check(this); 1071 } 1072 } 1073 1074 if (classDef->IsGlobal() || classType->SuperType() == nullptr) { 1075 return; 1076 } 1077 1078 CheckConstructors(classDef, classType); 1079 CheckValidInheritance(classType, classDef); 1080 CheckConstFields(classType); 1081 CheckGetterSetterProperties(classType); 1082 CheckInvokeMethodsLegitimacy(classType); 1083} 1084 1085void ETSChecker::CheckConstructors(ir::ClassDefinition *classDef, ETSObjectType *classType) 1086{ 1087 if (!classDef->IsDeclare()) { 1088 for (auto *it : classType->ConstructSignatures()) { 1089 CheckCyclicConstructorCall(it); 1090 CheckImplicitSuper(classType, it); 1091 CheckThisOrSuperCallInConstructor(classType, it); 1092 } 1093 } 1094} 1095 1096bool IsAsyncMethod(ir::AstNode *node) 1097{ 1098 if (!node->IsMethodDefinition()) { 1099 return false; 1100 } 1101 auto *method = node->AsMethodDefinition(); 1102 return method->Function()->IsAsyncFunc() && !method->Function()->IsProxy(); 1103} 1104 1105void ETSChecker::CreateAsyncProxyMethods(ir::ClassDefinition *classDef) 1106{ 1107 ArenaVector<ir::MethodDefinition *> asyncImpls(Allocator()->Adapter()); 1108 1109 for (auto *it : classDef->Body()) { 1110 if (!IsAsyncMethod(it)) { 1111 continue; 1112 } 1113 1114 auto *asyncMethod = it->AsMethodDefinition(); 1115 auto *proxy = CreateAsyncProxy(asyncMethod, classDef); 1116 asyncImpls.push_back(proxy); 1117 1118 for (auto *overload : asyncMethod->Overloads()) { 1119 if (!IsAsyncMethod(overload)) { 1120 continue; 1121 } 1122 1123 auto *impl = CreateAsyncProxy(overload, classDef, false); 1124 impl->Function()->Id()->SetVariable(proxy->Function()->Id()->Variable()); 1125 proxy->AddOverload(impl); 1126 } 1127 } 1128 1129 for (auto *it : asyncImpls) { 1130 it->SetParent(classDef); 1131 it->Check(this); 1132 classDef->Body().push_back(it); 1133 } 1134} 1135 1136void ETSChecker::CheckImplicitSuper(ETSObjectType *classType, Signature *ctorSig) 1137{ 1138 if (classType == GlobalETSObjectType()) { 1139 return; 1140 } 1141 1142 auto &stmts = ctorSig->Function()->Body()->AsBlockStatement()->Statements(); 1143 const auto thisCall = std::find_if(stmts.begin(), stmts.end(), [](const ir::Statement *stmt) { 1144 return stmt->IsExpressionStatement() && stmt->AsExpressionStatement()->GetExpression()->IsCallExpression() && 1145 stmt->AsExpressionStatement()->GetExpression()->AsCallExpression()->Callee()->IsThisExpression(); 1146 }); 1147 // There is an alternate constructor invocation, no need for super constructor invocation 1148 if (thisCall != stmts.end()) { 1149 return; 1150 } 1151 1152 const auto superExpr = std::find_if(stmts.begin(), stmts.end(), [](const ir::Statement *stmt) { 1153 return stmt->IsExpressionStatement() && stmt->AsExpressionStatement()->GetExpression()->IsCallExpression() && 1154 stmt->AsExpressionStatement()->GetExpression()->AsCallExpression()->Callee()->IsSuperExpression(); 1155 }); 1156 // There is no super expression 1157 if (superExpr == stmts.end()) { 1158 const auto superTypeCtorSigs = classType->SuperType()->ConstructSignatures(); 1159 const auto superTypeCtorSig = std::find_if(superTypeCtorSigs.begin(), superTypeCtorSigs.end(), 1160 [](const Signature *sig) { return sig->Params().empty(); }); 1161 // Super type has no parameterless ctor 1162 if (superTypeCtorSig == superTypeCtorSigs.end()) { 1163 LogTypeError("Must call super constructor", ctorSig->Function()->Start()); 1164 } 1165 1166 ctorSig->Function()->AddFlag(ir::ScriptFunctionFlags::IMPLICIT_SUPER_CALL_NEEDED); 1167 } 1168} 1169 1170void ETSChecker::CheckThisOrSuperCallInConstructor(ETSObjectType *classType, Signature *ctorSig) 1171{ 1172 if (classType == GlobalETSObjectType()) { 1173 return; 1174 } 1175 1176 for (auto it : ctorSig->Function()->Body()->AsBlockStatement()->Statements()) { 1177 if (it->IsExpressionStatement() && it->AsExpressionStatement()->GetExpression()->IsCallExpression() && 1178 (it->AsExpressionStatement()->GetExpression()->AsCallExpression()->Callee()->IsThisExpression() || 1179 it->AsExpressionStatement()->GetExpression()->AsCallExpression()->Callee()->IsSuperExpression())) { 1180 ArenaVector<const ir::Expression *> expressions = 1181 ArenaVector<const ir::Expression *>(Allocator()->Adapter()); 1182 expressions.insert(expressions.end(), 1183 it->AsExpressionStatement()->GetExpression()->AsCallExpression()->Arguments().begin(), 1184 it->AsExpressionStatement()->GetExpression()->AsCallExpression()->Arguments().end()); 1185 CheckExpressionsInConstructor(expressions); 1186 } 1187 } 1188} 1189 1190void ETSChecker::CheckExpressionsInConstructor(const ArenaVector<const ir::Expression *> &arguments) 1191{ 1192 for (auto *arg : arguments) { 1193 auto expressions = CheckMemberOrCallOrObjectExpressionInConstructor(arg); 1194 1195 if (arg->IsETSNewClassInstanceExpression()) { 1196 expressions.insert(expressions.end(), arg->AsETSNewClassInstanceExpression()->GetArguments().begin(), 1197 arg->AsETSNewClassInstanceExpression()->GetArguments().end()); 1198 } else if (arg->IsArrayExpression()) { 1199 expressions.insert(expressions.end(), arg->AsArrayExpression()->Elements().begin(), 1200 arg->AsArrayExpression()->Elements().end()); 1201 } else if (arg->IsBinaryExpression()) { 1202 expressions.push_back(arg->AsBinaryExpression()->Left()); 1203 expressions.push_back(arg->AsBinaryExpression()->Right()); 1204 } else if (arg->IsAssignmentExpression()) { 1205 expressions.push_back(arg->AsAssignmentExpression()->Left()); 1206 expressions.push_back(arg->AsAssignmentExpression()->Right()); 1207 } else if (arg->IsTSAsExpression()) { 1208 expressions.push_back(arg->AsTSAsExpression()->Expr()); 1209 } else if (arg->IsConditionalExpression()) { 1210 expressions.push_back(arg->AsConditionalExpression()->Test()); 1211 expressions.push_back(arg->AsConditionalExpression()->Consequent()); 1212 expressions.push_back(arg->AsConditionalExpression()->Alternate()); 1213 } else if (arg->IsTypeofExpression()) { 1214 expressions.push_back(arg->AsTypeofExpression()->Argument()); 1215 } else if (arg->IsTSNonNullExpression()) { 1216 expressions.push_back(arg->AsTSNonNullExpression()->Expr()); 1217 } else if (arg->IsUnaryExpression()) { 1218 expressions.push_back(arg->AsUnaryExpression()->Argument()); 1219 } else if (arg->IsUpdateExpression()) { 1220 expressions.push_back(arg->AsUpdateExpression()->Argument()); 1221 } 1222 1223 if (!expressions.empty()) { 1224 CheckExpressionsInConstructor(expressions); 1225 } 1226 } 1227} 1228 1229ArenaVector<const ir::Expression *> ETSChecker::CheckMemberOrCallOrObjectExpressionInConstructor( 1230 const ir::Expression *arg) 1231{ 1232 ArenaVector<const ir::Expression *> expressions = ArenaVector<const ir::Expression *>(Allocator()->Adapter()); 1233 1234 if (arg->IsMemberExpression()) { 1235 if ((arg->AsMemberExpression()->Object()->IsSuperExpression() || 1236 arg->AsMemberExpression()->Object()->IsThisExpression())) { 1237 std::stringstream ss; 1238 ss << "Using " << (arg->AsMemberExpression()->Object()->IsSuperExpression() ? "super" : "this") 1239 << " is not allowed in constructor"; 1240 LogTypeError(ss.str(), arg->Start()); 1241 } 1242 1243 expressions.push_back(arg->AsMemberExpression()->Property()); 1244 expressions.push_back(arg->AsMemberExpression()->Object()); 1245 } else if (arg->IsCallExpression()) { 1246 expressions.insert(expressions.end(), arg->AsCallExpression()->Arguments().begin(), 1247 arg->AsCallExpression()->Arguments().end()); 1248 1249 if (arg->AsCallExpression()->Callee()->IsMemberExpression() && 1250 (arg->AsCallExpression()->Callee()->AsMemberExpression()->Object()->IsSuperExpression() || 1251 arg->AsCallExpression()->Callee()->AsMemberExpression()->Object()->IsThisExpression()) && 1252 !arg->AsCallExpression()->Callee()->AsMemberExpression()->Property()->IsStatic()) { 1253 std::stringstream ss; 1254 ss << "Using " 1255 << (arg->AsCallExpression()->Callee()->AsMemberExpression()->IsSuperExpression() ? "super" : "this") 1256 << " is not allowed in constructor"; 1257 LogTypeError(ss.str(), arg->Start()); 1258 } 1259 } else if (arg->IsObjectExpression()) { 1260 for (auto *prop : arg->AsObjectExpression()->Properties()) { 1261 expressions.push_back(prop->AsProperty()->Value()); 1262 } 1263 } 1264 1265 return expressions; 1266} 1267 1268void ETSChecker::CheckConstFields(const ETSObjectType *classType) 1269{ 1270 for (const auto &prop : classType->Fields()) { 1271 if (!(prop->Declaration()->IsConstDecl() || prop->Declaration()->IsReadonlyDecl()) || 1272 !prop->HasFlag(varbinder::VariableFlags::EXPLICIT_INIT_REQUIRED)) { 1273 continue; 1274 } 1275 CheckConstFieldInitialized(classType, prop); 1276 } 1277} 1278 1279void ETSChecker::CheckConstFieldInitialized(const ETSObjectType *classType, varbinder::LocalVariable *classVar) 1280{ 1281 const bool classVarStatic = classVar->Declaration()->Node()->AsClassProperty()->IsStatic(); 1282 for (const auto &prop : classType->Methods()) { 1283 if (!prop->TsType()->IsETSFunctionType()) { 1284 continue; 1285 } 1286 1287 const auto &callSigs = prop->TsType()->AsETSFunctionType()->CallSignatures(); 1288 for (const auto *signature : callSigs) { 1289 if ((signature->Function()->IsConstructor() && !classVarStatic) || 1290 (signature->Function()->IsStaticBlock() && classVarStatic)) { 1291 CheckConstFieldInitialized(signature, classVar); 1292 } 1293 } 1294 } 1295} 1296 1297void ETSChecker::FindAssignment(const ir::AstNode *node, const varbinder::LocalVariable *classVar, bool &initialized) 1298{ 1299 if (node->IsAssignmentExpression() && node->AsAssignmentExpression()->Target() == classVar) { 1300 if (initialized) { 1301 LogTypeError({"Variable '", classVar->Declaration()->Name(), "' might already have been initialized"}, 1302 node->Start()); 1303 } 1304 1305 initialized = true; 1306 return; 1307 } 1308 1309 FindAssignments(node, classVar, initialized); 1310} 1311 1312void ETSChecker::FindAssignments(const ir::AstNode *node, const varbinder::LocalVariable *classVar, bool &initialized) 1313{ 1314 node->Iterate( 1315 [this, classVar, &initialized](ir::AstNode *childNode) { FindAssignment(childNode, classVar, initialized); }); 1316} 1317 1318void ETSChecker::CheckConstFieldInitialized(const Signature *signature, varbinder::LocalVariable *classVar) 1319{ 1320 bool initialized = false; 1321 const auto &stmts = signature->Function()->Body()->AsBlockStatement()->Statements(); 1322 const auto it = stmts.begin(); 1323 if (it != stmts.end()) { 1324 if (const auto *first = *it; 1325 first->IsExpressionStatement() && first->AsExpressionStatement()->GetExpression()->IsCallExpression() && 1326 first->AsExpressionStatement()->GetExpression()->AsCallExpression()->Callee()->IsThisExpression()) { 1327 initialized = true; 1328 } 1329 } 1330 1331 // NOTE: szd. control flow 1332 FindAssignments(signature->Function()->Body(), classVar, initialized); 1333 if (!initialized) { 1334 LogTypeError({"Variable '", classVar->Declaration()->Name(), "' might not have been initialized"}, 1335 signature->Function()->End()); 1336 } 1337 1338 classVar->RemoveFlag(varbinder::VariableFlags::EXPLICIT_INIT_REQUIRED); 1339} 1340 1341void ETSChecker::CheckInnerClassMembers(const ETSObjectType *classType) 1342{ 1343 for (const auto &[_, it] : classType->StaticMethods()) { 1344 (void)_; 1345 LogTypeError("Inner class cannot have static methods", it->Declaration()->Node()->Start()); 1346 } 1347 1348 for (const auto &[_, it] : classType->StaticFields()) { 1349 (void)_; 1350 if (!it->Declaration()->IsReadonlyDecl()) { 1351 LogTypeError("Inner class cannot have non-readonly static properties", it->Declaration()->Node()->Start()); 1352 } 1353 } 1354} 1355 1356bool ETSChecker::ValidateArrayIndex(ir::Expression *const expr, bool relaxed) 1357{ 1358 auto *const expressionType = expr->Check(this); 1359 auto const *const unboxedExpressionType = ETSBuiltinTypeAsPrimitiveType(expressionType); 1360 1361 Type const *const indexType = ApplyUnaryOperatorPromotion(expressionType); 1362 1363 if (expressionType->IsETSObjectType() && (unboxedExpressionType != nullptr)) { 1364 expr->AddBoxingUnboxingFlags(GetUnboxingFlag(unboxedExpressionType)); 1365 } 1366 1367 if (relaxed && indexType != nullptr && indexType->HasTypeFlag(TypeFlag::ETS_FLOATING_POINT)) { 1368 if (!expr->IsNumberLiteral()) { 1369 return true; 1370 } 1371 1372 auto num = expr->AsNumberLiteral()->Number(); 1373 ASSERT(num.IsReal()); 1374 double value = num.GetDouble(); 1375 double intpart; 1376 if (std::modf(value, &intpart) != 0.0) { 1377 LogTypeError("Index fractional part should be zero.", expr->Start()); 1378 return false; 1379 } 1380 return true; 1381 } 1382 1383 if (indexType == nullptr || !indexType->HasTypeFlag(TypeFlag::ETS_ARRAY_INDEX)) { 1384 std::stringstream message(""); 1385 if (expressionType->IsNonPrimitiveType()) { 1386 message << expressionType->Variable()->Name(); 1387 } else { 1388 expressionType->ToString(message); 1389 } 1390 1391 LogTypeError( 1392 "Type '" + message.str() + 1393 "' cannot be used as an index type. Only primitive or unboxable integral types can be used as index.", 1394 expr->Start()); 1395 return false; 1396 } 1397 1398 return true; 1399} 1400 1401std::optional<int32_t> ETSChecker::GetTupleElementAccessValue(const Type *const type, const lexer::SourcePosition &pos) 1402{ 1403 ASSERT(type->HasTypeFlag(TypeFlag::CONSTANT | TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC)); 1404 1405 switch (ETSType(type)) { 1406 case TypeFlag::BYTE: { 1407 return type->AsByteType()->GetValue(); 1408 } 1409 case TypeFlag::SHORT: { 1410 return type->AsShortType()->GetValue(); 1411 } 1412 case TypeFlag::INT: { 1413 return type->AsIntType()->GetValue(); 1414 } 1415 case TypeFlag::LONG: { 1416 if (auto val = type->AsLongType()->GetValue(); 1417 val <= std::numeric_limits<int32_t>::max() && val >= std::numeric_limits<int32_t>::min()) { 1418 return static_cast<int32_t>(val); 1419 } 1420 1421 LogTypeError("Element accessor value is out of tuple size bounds.", pos); 1422 return std::nullopt; 1423 } 1424 default: { 1425 UNREACHABLE(); 1426 } 1427 } 1428} 1429 1430bool ETSChecker::ValidateTupleIndex(const ETSTupleType *const tuple, ir::MemberExpression *const expr) 1431{ 1432 auto *const expressionType = expr->Property()->Check(this); 1433 auto const *const unboxedExpressionType = ETSBuiltinTypeAsPrimitiveType(expressionType); 1434 1435 if (expressionType->IsETSObjectType() && (unboxedExpressionType != nullptr)) { 1436 expr->AddBoxingUnboxingFlags(GetUnboxingFlag(unboxedExpressionType)); 1437 } 1438 1439 const auto *const exprType = expr->Property()->TsType(); 1440 ASSERT(exprType != nullptr); 1441 1442 if (!exprType->HasTypeFlag(TypeFlag::CONSTANT) && !tuple->HasSpreadType()) { 1443 LogTypeError("Only constant expression allowed for element access on tuples.", expr->Property()->Start()); 1444 return false; 1445 } 1446 1447 if (!exprType->HasTypeFlag(TypeFlag::ETS_ARRAY_INDEX | TypeFlag::LONG)) { 1448 LogTypeError("Only integer type allowed for element access on tuples.", expr->Property()->Start()); 1449 return false; 1450 } 1451 1452 auto exprValue = GetTupleElementAccessValue(exprType, expr->Property()->Start()); 1453 if (!exprValue.has_value()) { 1454 return false; // spread the error 1455 } 1456 if (((*exprValue >= tuple->GetTupleSize()) && !tuple->HasSpreadType()) || (*exprValue < 0)) { 1457 LogTypeError("Element accessor value is out of tuple size bounds.", expr->Property()->Start()); 1458 return false; 1459 } 1460 1461 return true; 1462} 1463 1464ETSObjectType *ETSChecker::CheckThisOrSuperAccess(ir::Expression *node, ETSObjectType *classType, std::string_view msg) 1465{ 1466 if ((Context().Status() & CheckerStatus::IGNORE_VISIBILITY) != 0U) { 1467 return classType; 1468 } 1469 1470 if (node->Parent()->IsCallExpression() && (node->Parent()->AsCallExpression()->Callee() == node)) { 1471 if (Context().ContainingSignature() == nullptr) { 1472 LogTypeError({"Call to '", msg, "' must be first statement in constructor"}, node->Start()); 1473 return classType; 1474 } 1475 1476 auto *sig = Context().ContainingSignature(); 1477 ASSERT(sig->Function()->Body() && sig->Function()->Body()->IsBlockStatement()); 1478 1479 if (!sig->HasSignatureFlag(checker::SignatureFlags::CONSTRUCT)) { 1480 LogTypeError({"Call to '", msg, "' must be first statement in constructor"}, node->Start()); 1481 return classType; 1482 } 1483 1484 if (sig->Function()->Body()->AsBlockStatement()->Statements().front() != node->Parent()->Parent()) { 1485 LogTypeError({"Call to '", msg, "' must be first statement in constructor"}, node->Start()); 1486 return classType; 1487 } 1488 } 1489 1490 if (HasStatus(checker::CheckerStatus::IN_STATIC_CONTEXT)) { 1491 LogTypeError({"'", msg, "' cannot be referenced from a static context"}, node->Start()); 1492 return classType; 1493 } 1494 1495 if (classType->GetDeclNode()->IsClassDefinition() && classType->GetDeclNode()->AsClassDefinition()->IsGlobal()) { 1496 LogTypeError({"Cannot reference '", msg, "' in this context."}, node->Start()); 1497 return classType; 1498 } 1499 1500 return classType; 1501} 1502 1503void ETSChecker::CheckCyclicConstructorCall(Signature *signature) 1504{ 1505 ASSERT(signature->Function()); 1506 1507 if (signature->Function()->Body() == nullptr || signature->Function()->IsExternal()) { 1508 return; 1509 } 1510 1511 auto *funcBody = signature->Function()->Body()->AsBlockStatement(); 1512 1513 TypeStackElement tse(this, signature, "Recursive constructor invocation", signature->Function()->Start()); 1514 if (tse.HasTypeError()) { 1515 return; 1516 } 1517 1518 if (!funcBody->Statements().empty() && funcBody->Statements()[0]->IsExpressionStatement() && 1519 funcBody->Statements()[0]->AsExpressionStatement()->GetExpression()->IsCallExpression() && 1520 funcBody->Statements()[0] 1521 ->AsExpressionStatement() 1522 ->GetExpression() 1523 ->AsCallExpression() 1524 ->Callee() 1525 ->IsThisExpression()) { 1526 auto *constructorCall = funcBody->Statements()[0]->AsExpressionStatement()->GetExpression()->AsCallExpression(); 1527 ASSERT(constructorCall->Signature()); 1528 CheckCyclicConstructorCall(constructorCall->Signature()); 1529 } 1530} 1531 1532ETSObjectType *ETSChecker::CheckExceptionOrErrorType(checker::Type *type, const lexer::SourcePosition pos) 1533{ 1534 if (!type->IsETSObjectType() || (!Relation()->IsAssignableTo(type, GlobalBuiltinExceptionType()) && 1535 !Relation()->IsAssignableTo(type, GlobalBuiltinErrorType()))) { 1536 LogTypeError({"Argument must be an instance of '", compiler::Signatures::BUILTIN_EXCEPTION_CLASS, "' or '", 1537 compiler::Signatures::BUILTIN_ERROR_CLASS, "'"}, 1538 pos); 1539 return GlobalETSObjectType(); 1540 } 1541 1542 return type->AsETSObjectType(); 1543} 1544 1545Type *ETSChecker::TryToInstantiate(Type *const type, ArenaAllocator *const allocator, TypeRelation *const relation, 1546 GlobalTypesHolder *const globalTypes) 1547{ 1548 // NOTE: Handle generic functions 1549 auto *returnType = type; 1550 const bool isIncomplete = 1551 type->IsETSObjectType() && type->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::INCOMPLETE_INSTANTIATION); 1552 if (const bool isFunctionType = type->IsETSFunctionType(); isFunctionType || isIncomplete) { 1553 returnType = type->Instantiate(allocator, relation, globalTypes); 1554 } 1555 1556 return returnType; 1557} 1558 1559void ETSChecker::ValidateResolvedProperty(varbinder::LocalVariable **property, const ETSObjectType *const target, 1560 const ir::Identifier *const ident, const PropertySearchFlags flags) 1561{ 1562 if (*property != nullptr) { 1563 return; 1564 } 1565 1566 using Utype = std::underlying_type_t<PropertySearchFlags>; 1567 static constexpr uint32_t CORRECT_PROPERTY_SEARCH_ORDER_INSTANCE = 7U; 1568 static_assert(static_cast<Utype>(PropertySearchFlags::SEARCH_INSTANCE) == CORRECT_PROPERTY_SEARCH_ORDER_INSTANCE, 1569 "PropertySearchFlags order changed"); 1570 static constexpr uint32_t CORRECT_PROPERTY_SEARCH_ORDER_STATIC = 56U; 1571 static_assert(static_cast<Utype>(PropertySearchFlags::SEARCH_STATIC) == CORRECT_PROPERTY_SEARCH_ORDER_STATIC, 1572 "PropertySearchFlags order changed"); 1573 const auto flagsNum = static_cast<Utype>(flags); 1574 // This algorithm swaps the first 3 bits of a number with it's consecutive 3 bits, example: 0b110001 -> 0b001110 1575 // Effectively it changes PropertySearchFlags to search for the appropriate declarations 1576 const Utype x = (flagsNum ^ (flagsNum >> 3U)) & 7U; 1577 const auto newFlags = PropertySearchFlags {flagsNum ^ (x | (x << 3U))}; 1578 1579 auto *const newProp = target->GetProperty(ident->Name(), newFlags); 1580 if (newProp == nullptr) { 1581 LogTypeError({"Property '", ident->Name(), "' does not exist on type '", target->Name(), "'"}, ident->Start()); 1582 return; 1583 } 1584 1585 *property = newProp; // trying to recover as much as possible; log the error but treat the property as legal 1586 1587 if (IsVariableStatic(newProp)) { 1588 LogTypeError({"'", ident->Name(), "' is a static property of '", target->Name(), "'"}, ident->Start()); 1589 return; 1590 } 1591 1592 LogTypeError({"'", ident->Name(), "' is an instance property of '", target->Name(), "'"}, ident->Start()); 1593} 1594 1595varbinder::Variable *ETSChecker::ResolveInstanceExtension(const ir::MemberExpression *const memberExpr) 1596{ 1597 // clang-format off 1598 auto *globalFunctionVar = Scope() 1599 ->FindInGlobal(memberExpr->Property()->AsIdentifier()->Name(), 1600 varbinder::ResolveBindingOptions::STATIC_METHODS) 1601 .variable; 1602 // clang-format on 1603 1604 if (globalFunctionVar == nullptr || !ExtensionETSFunctionType(this->GetTypeOfVariable(globalFunctionVar))) { 1605 return nullptr; 1606 } 1607 1608 return globalFunctionVar; 1609} 1610 1611PropertySearchFlags ETSChecker::GetInitialSearchFlags(const ir::MemberExpression *const memberExpr) 1612{ 1613 constexpr auto FUNCTIONAL_FLAGS = 1614 PropertySearchFlags::SEARCH_METHOD | PropertySearchFlags::IS_FUNCTIONAL | PropertySearchFlags::SEARCH_FIELD; 1615 constexpr auto GETTER_FLAGS = PropertySearchFlags::SEARCH_METHOD | PropertySearchFlags::IS_GETTER; 1616 constexpr auto SETTER_FLAGS = PropertySearchFlags::SEARCH_METHOD | PropertySearchFlags::IS_SETTER; 1617 1618 switch (memberExpr->Parent()->Type()) { 1619 case ir::AstNodeType::CALL_EXPRESSION: { 1620 if (memberExpr->Parent()->AsCallExpression()->Callee() == memberExpr) { 1621 return FUNCTIONAL_FLAGS; 1622 } 1623 1624 break; 1625 } 1626 case ir::AstNodeType::ETS_NEW_CLASS_INSTANCE_EXPRESSION: { 1627 if (memberExpr->Parent()->AsETSNewClassInstanceExpression()->GetTypeRef() == memberExpr) { 1628 return PropertySearchFlags::SEARCH_DECL; 1629 } 1630 break; 1631 } 1632 case ir::AstNodeType::MEMBER_EXPRESSION: { 1633 return PropertySearchFlags::SEARCH_FIELD | PropertySearchFlags::SEARCH_DECL | GETTER_FLAGS; 1634 } 1635 case ir::AstNodeType::UPDATE_EXPRESSION: 1636 case ir::AstNodeType::UNARY_EXPRESSION: 1637 case ir::AstNodeType::BINARY_EXPRESSION: { 1638 return PropertySearchFlags::SEARCH_FIELD | GETTER_FLAGS; 1639 } 1640 case ir::AstNodeType::ASSIGNMENT_EXPRESSION: { 1641 const auto *const assignmentExpr = memberExpr->Parent()->AsAssignmentExpression(); 1642 1643 if (assignmentExpr->Left() == memberExpr) { 1644 if (assignmentExpr->OperatorType() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { 1645 return PropertySearchFlags::SEARCH_FIELD | SETTER_FLAGS; 1646 } 1647 return PropertySearchFlags::SEARCH_FIELD | GETTER_FLAGS | SETTER_FLAGS; 1648 } 1649 1650 auto const *targetType = assignmentExpr->Left()->TsTypeOrError(); 1651 if (targetType->IsETSObjectType() && 1652 targetType->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::FUNCTIONAL)) { 1653 return FUNCTIONAL_FLAGS; 1654 } 1655 1656 return PropertySearchFlags::SEARCH_FIELD | GETTER_FLAGS; 1657 } 1658 default: { 1659 break; 1660 } 1661 } 1662 1663 return PropertySearchFlags::SEARCH_FIELD | FUNCTIONAL_FLAGS | GETTER_FLAGS; 1664} 1665 1666PropertySearchFlags ETSChecker::GetSearchFlags(const ir::MemberExpression *const memberExpr, 1667 const varbinder::Variable *targetRef) 1668{ 1669 auto searchFlag = GetInitialSearchFlags(memberExpr); 1670 searchFlag |= PropertySearchFlags::SEARCH_IN_BASE | PropertySearchFlags::SEARCH_IN_INTERFACES; 1671 if (targetRef != nullptr && 1672 (targetRef->HasFlag(varbinder::VariableFlags::CLASS_OR_INTERFACE) || 1673 (targetRef->HasFlag(varbinder::VariableFlags::TYPE_ALIAS) && 1674 targetRef->TsType()->Variable()->HasFlag(varbinder::VariableFlags::CLASS_OR_INTERFACE)))) { 1675 searchFlag &= ~PropertySearchFlags::SEARCH_INSTANCE; 1676 } else if (memberExpr->Object()->IsThisExpression() || 1677 (targetRef != nullptr && targetRef->Declaration() != nullptr && 1678 targetRef->Declaration()->IsLetOrConstDecl()) || 1679 (memberExpr->Object()->IsIdentifier() && memberExpr->ObjType()->GetDeclNode() != nullptr && 1680 memberExpr->ObjType()->GetDeclNode()->IsTSInterfaceDeclaration())) { 1681 searchFlag &= ~PropertySearchFlags::SEARCH_STATIC; 1682 } 1683 return searchFlag; 1684} 1685 1686const varbinder::Variable *ETSChecker::GetTargetRef(const ir::MemberExpression *const memberExpr) 1687{ 1688 if (memberExpr->Object()->IsIdentifier()) { 1689 return memberExpr->Object()->AsIdentifier()->Variable(); 1690 } 1691 if (memberExpr->Object()->IsMemberExpression()) { 1692 return memberExpr->Object()->AsMemberExpression()->PropVar(); 1693 } 1694 return nullptr; 1695} 1696 1697void ETSChecker::ValidateReadonlyProperty(const ir::MemberExpression *const memberExpr, const ETSFunctionType *propType, 1698 const lexer::SourcePosition sourcePos) 1699{ 1700 ir::ClassProperty *classProp = nullptr; 1701 ETSObjectType *currentObj = memberExpr->ObjType(); 1702 bool foundInThis = false; 1703 while (classProp == nullptr && currentObj != nullptr) { 1704 classProp = FindClassProperty(currentObj, propType); 1705 if (classProp != nullptr && currentObj == memberExpr->ObjType()) { 1706 foundInThis = true; 1707 } 1708 1709 currentObj = currentObj->SuperType(); 1710 } 1711 1712 if (classProp != nullptr && this->Context().ContainingSignature() != nullptr && classProp->IsReadonly()) { 1713 if (!foundInThis || (!this->Context().ContainingSignature()->Function()->IsConstructor())) { 1714 LogTypeError("Cannot assign to this property because it is readonly.", sourcePos); 1715 return; 1716 } 1717 1718 if (IsInitializedProperty(memberExpr->ObjType()->GetDeclNode()->AsClassDefinition(), classProp)) { 1719 LogTypeError("Readonly field already initialized at declaration.", sourcePos); 1720 } 1721 } 1722} 1723 1724void ETSChecker::ValidateGetterSetter(const ir::MemberExpression *const memberExpr, 1725 const varbinder::LocalVariable *const prop, PropertySearchFlags searchFlag) 1726{ 1727 auto *propType = prop->TsType()->AsETSFunctionType(); 1728 ASSERT((propType->FindGetter() != nullptr) == propType->HasTypeFlag(TypeFlag::GETTER)); 1729 ASSERT((propType->FindSetter() != nullptr) == propType->HasTypeFlag(TypeFlag::SETTER)); 1730 1731 auto const &sourcePos = memberExpr->Property()->Start(); 1732 auto callExpr = memberExpr->Parent()->IsCallExpression() ? memberExpr->Parent()->AsCallExpression() : nullptr; 1733 1734 if ((searchFlag & PropertySearchFlags::IS_GETTER) != 0) { 1735 if (!propType->HasTypeFlag(TypeFlag::GETTER)) { 1736 LogTypeError("Cannot read from this property because it is writeonly.", sourcePos); 1737 return; 1738 } 1739 ValidateSignatureAccessibility(memberExpr->ObjType(), callExpr, propType->FindGetter(), sourcePos); 1740 } 1741 1742 if ((searchFlag & PropertySearchFlags::IS_SETTER) != 0) { 1743 ValidateReadonlyProperty(memberExpr, propType, sourcePos); 1744 ValidateSignatureAccessibility(memberExpr->ObjType(), callExpr, propType->FindSetter(), sourcePos); 1745 } 1746} 1747 1748ir::ClassProperty *ETSChecker::FindClassProperty(const ETSObjectType *const objectType, const ETSFunctionType *propType) 1749{ 1750 auto propName = 1751 util::UString(std::string(compiler::Signatures::PROPERTY) + propType->Name().Mutf8(), Allocator()).View(); 1752 1753 ir::ClassProperty *classProp = nullptr; 1754 if (objectType->GetDeclNode()->IsClassDefinition()) { 1755 auto body = objectType->GetDeclNode()->AsClassDefinition()->Body(); 1756 auto foundValue = std::find_if(body.begin(), body.end(), [propName](ir::AstNode *node) { 1757 return node->IsClassProperty() && node->AsClassProperty()->Key()->AsIdentifier()->Name() == propName; 1758 }); 1759 if (foundValue != body.end()) { 1760 classProp = (*foundValue)->AsClassProperty(); 1761 } 1762 } 1763 1764 return classProp; 1765} 1766 1767bool ETSChecker::IsInitializedProperty(const ir::ClassDefinition *classDefinition, const ir::ClassProperty *prop) 1768{ 1769 std::string targetName = prop->Key()->AsIdentifier()->Name().Mutf8(); 1770 if (targetName.find(compiler::Signatures::PROPERTY) == 0) { 1771 targetName = targetName.substr(compiler::Signatures::PROPERTY.size()); 1772 } 1773 1774 for (auto *it : classDefinition->Body()) { 1775 if (it->IsClassProperty() && it->AsClassProperty()->Value() != nullptr) { 1776 return FindPropertyInAssignment(it, targetName); 1777 } 1778 } 1779 1780 return false; 1781} 1782 1783bool ETSChecker::FindPropertyInAssignment(const ir::AstNode *it, const std::string &targetName) 1784{ 1785 return it->AsClassProperty()->Value()->FindChild([&targetName](ir::AstNode *node) { 1786 return node->IsIdentifier() && node->AsIdentifier()->Name().Is(targetName) && node->Parent() != nullptr && 1787 node->Parent()->IsMemberExpression(); 1788 }) != nullptr; 1789} 1790 1791void ETSChecker::ValidateVarDeclaratorOrClassProperty(const ir::MemberExpression *const memberExpr, 1792 varbinder::LocalVariable *const prop) 1793{ 1794 const auto [target_ident, 1795 type_annotation] = [memberExpr]() -> std::pair<const ir::Identifier *, const ir::TypeNode *> { 1796 if (memberExpr->Parent()->IsVariableDeclarator()) { 1797 const auto *const ident = memberExpr->Parent()->AsVariableDeclarator()->Id()->AsIdentifier(); 1798 return {ident, ident->TypeAnnotation()}; 1799 } 1800 return {memberExpr->Parent()->AsClassProperty()->Key()->AsIdentifier(), 1801 memberExpr->Parent()->AsClassProperty()->TypeAnnotation()}; 1802 }(); 1803 1804 GetTypeOfVariable(prop); 1805 1806 if (prop->TsType()->IsETSFunctionType() && !IsVariableGetterSetter(prop)) { 1807 if (type_annotation == nullptr) { 1808 LogTypeError({"Cannot infer type for ", target_ident->Name(), 1809 " because method reference needs an explicit target type"}, 1810 target_ident->Start()); 1811 return; 1812 } 1813 1814 auto *targetType = GetTypeOfVariable(target_ident->Variable()); 1815 ASSERT(targetType != nullptr); 1816 1817 if (!targetType->IsETSObjectType() || 1818 !targetType->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::FUNCTIONAL)) { 1819 LogTypeError({"Method ", memberExpr->Property()->AsIdentifier()->Name(), " does not exist on this type."}, 1820 memberExpr->Property()->Start()); 1821 } 1822 } 1823} 1824 1825// NOLINTNEXTLINE(readability-function-size) 1826std::vector<ResolveResult *> ETSChecker::ResolveMemberReference(const ir::MemberExpression *const memberExpr, 1827 const ETSObjectType *const target) 1828{ 1829 std::vector<ResolveResult *> resolveRes {}; 1830 1831 if (target->IsETSDynamicType() && !target->AsETSDynamicType()->HasDecl()) { 1832 auto propName = memberExpr->Property()->AsIdentifier()->Name(); 1833 varbinder::LocalVariable *propVar = target->AsETSDynamicType()->GetPropertyDynamic(propName, this); 1834 resolveRes.emplace_back(Allocator()->New<ResolveResult>(propVar, ResolvedKind::PROPERTY)); 1835 return resolveRes; 1836 } 1837 1838 varbinder::Variable *globalFunctionVar = nullptr; 1839 1840 if (memberExpr->Parent()->IsCallExpression() && memberExpr->Parent()->AsCallExpression()->Callee() == memberExpr) { 1841 globalFunctionVar = ResolveInstanceExtension(memberExpr); 1842 } else if (target->GetDeclNode() != nullptr && target->GetDeclNode()->IsClassDefinition() && 1843 !target->GetDeclNode()->AsClassDefinition()->IsClassDefinitionChecked()) { 1844 this->CheckClassDefinition(target->GetDeclNode()->AsClassDefinition()); 1845 } 1846 const auto *const targetRef = GetTargetRef(memberExpr); 1847 auto searchFlag = GetSearchFlags(memberExpr, targetRef); 1848 if (target->HasTypeFlag(TypeFlag::GENERIC) && (searchFlag & PropertySearchFlags::SEARCH_STATIC) != 0) { 1849 searchFlag |= PropertySearchFlags::SEARCH_ALL; 1850 } 1851 1852 auto searchName = target->GetReExportAliasValue(memberExpr->Property()->AsIdentifier()->Name()); 1853 auto *prop = target->GetProperty(searchName, searchFlag); 1854 1855 if (memberExpr->Parent()->IsCallExpression() && memberExpr->Parent()->AsCallExpression()->Callee() == memberExpr) { 1856 globalFunctionVar = ResolveInstanceExtension(memberExpr); 1857 } 1858 1859 if (globalFunctionVar == nullptr || 1860 (targetRef != nullptr && targetRef->HasFlag(varbinder::VariableFlags::CLASS_OR_INTERFACE))) { 1861 /* 1862 Instance extension function can only be called by class instance, if a property is accessed by 1863 CLASS or INTERFACE type, it couldn't be an instance extension function call 1864 1865 Example code: 1866 class A {} 1867 static function A.xxx() {} 1868 function main() { 1869 A.xxx() 1870 } 1871 1872 !NB: When supporting static extension function, the above code case would be supported 1873 */ 1874 ValidateResolvedProperty(&prop, target, memberExpr->Property()->AsIdentifier(), searchFlag); 1875 if (prop == nullptr) { 1876 return resolveRes; 1877 } 1878 } else { 1879 resolveRes.emplace_back( 1880 Allocator()->New<ResolveResult>(globalFunctionVar, ResolvedKind::INSTANCE_EXTENSION_FUNCTION)); 1881 1882 if (prop == nullptr) { 1883 // No matched property, but have possible matched global extension function 1884 return resolveRes; 1885 } 1886 } 1887 1888 resolveRes.emplace_back(Allocator()->New<ResolveResult>(prop, ResolvedKind::PROPERTY)); 1889 1890 ResolveMemberReferenceValidate(prop, searchFlag, memberExpr); 1891 1892 return resolveRes; 1893} 1894 1895void ETSChecker::ResolveMemberReferenceValidate(varbinder::LocalVariable *const prop, 1896 PropertySearchFlags const searchFlag, 1897 const ir::MemberExpression *const memberExpr) 1898{ 1899 if (prop->HasFlag(varbinder::VariableFlags::METHOD) && !IsVariableGetterSetter(prop) && 1900 (searchFlag & PropertySearchFlags::IS_FUNCTIONAL) == 0) { 1901 LogTypeError("Method used in wrong context", memberExpr->Property()->Start()); 1902 return; 1903 } 1904 1905 if (IsVariableGetterSetter(prop)) { 1906 ValidateGetterSetter(memberExpr, prop, searchFlag); 1907 } 1908 1909 // Before returning the computed property variable, we have to validate the special case where we are in a variable 1910 // declaration, and the properties type is a function type but the currently declared variable doesn't have a type 1911 // annotation 1912 if (memberExpr->Parent()->IsVariableDeclarator() || memberExpr->Parent()->IsClassProperty()) { 1913 ValidateVarDeclaratorOrClassProperty(memberExpr, prop); 1914 } 1915} 1916 1917void ETSChecker::CheckValidInheritance(ETSObjectType *classType, ir::ClassDefinition *classDef) 1918{ 1919 if (classType->SuperType() == nullptr) { 1920 return; 1921 } 1922 1923 if (classDef->TypeParams() != nullptr && 1924 (Relation()->IsAssignableTo(classType->SuperType(), GlobalBuiltinExceptionType()) || 1925 Relation()->IsAssignableTo(classType->SuperType(), GlobalBuiltinErrorType()))) { 1926 LogTypeError({"Generics are not allowed as '", compiler::Signatures::BUILTIN_EXCEPTION_CLASS, "' or '", 1927 compiler::Signatures::BUILTIN_ERROR_CLASS, "' subclasses."}, 1928 classDef->TypeParams()->Start()); 1929 } 1930 1931 const auto &allProps = classType->GetAllProperties(); 1932 1933 for (auto *it : allProps) { 1934 const auto searchFlag = PropertySearchFlags::SEARCH_ALL | PropertySearchFlags::SEARCH_IN_BASE | 1935 PropertySearchFlags::SEARCH_IN_INTERFACES | 1936 PropertySearchFlags::DISALLOW_SYNTHETIC_METHOD_CREATION; 1937 auto *foundInSuper = classType->SuperType()->GetProperty(it->Name(), searchFlag); 1938 1939 ETSObjectType *interfaceFound = nullptr; 1940 if (foundInSuper != nullptr) { 1941 CheckProperties(classType, classDef, it, foundInSuper, interfaceFound); 1942 } 1943 1944 auto interfaceList = GetInterfaces(classType); 1945 varbinder::LocalVariable *foundInInterface = nullptr; 1946 for (auto *interface : interfaceList) { 1947 auto *propertyFound = interface->GetProperty(it->Name(), searchFlag); 1948 if (propertyFound == nullptr) { 1949 continue; 1950 } 1951 foundInInterface = propertyFound; 1952 interfaceFound = interface; 1953 break; 1954 } 1955 if (foundInInterface == nullptr) { 1956 continue; 1957 } 1958 1959 CheckProperties(classType, classDef, it, foundInInterface, interfaceFound); 1960 } 1961} 1962 1963void ETSChecker::CheckProperties(ETSObjectType *classType, ir::ClassDefinition *classDef, varbinder::LocalVariable *it, 1964 varbinder::LocalVariable *found, ETSObjectType *interfaceFound) 1965{ 1966 if (found->TsType() == nullptr) { 1967 GetTypeOfVariable(found); 1968 } 1969 1970 if (!IsSameDeclarationType(it, found)) { 1971 if (IsVariableStatic(it) != IsVariableStatic(found)) { 1972 return; 1973 } 1974 1975 if (it->TsType()->IsETSFunctionType()) { 1976 auto getter = it->TsType()->AsETSFunctionType()->FindGetter(); 1977 if (getter != nullptr && getter->ReturnType() == found->TsType()) { 1978 return; 1979 } 1980 auto setter = it->TsType()->AsETSFunctionType()->FindSetter(); 1981 if (setter != nullptr && setter->Params().front()->TsType() == found->TsType()) { 1982 return; 1983 } 1984 } 1985 1986 const char *targetType {}; 1987 1988 if (it->HasFlag(varbinder::VariableFlags::PROPERTY)) { 1989 targetType = "field"; 1990 } else if (it->HasFlag(varbinder::VariableFlags::METHOD)) { 1991 targetType = "method"; 1992 } else if (it->HasFlag(varbinder::VariableFlags::CLASS)) { 1993 targetType = "class"; 1994 } else if (it->HasFlag(varbinder::VariableFlags::INTERFACE)) { 1995 targetType = "interface"; 1996 } else { 1997 targetType = "enum"; 1998 } 1999 2000 if (interfaceFound != nullptr) { 2001 LogTypeError({"Cannot inherit from interface ", interfaceFound->Name(), " because ", targetType, " ", 2002 it->Name(), " is inherited with a different declaration type"}, 2003 interfaceFound->GetDeclNode()->Start()); 2004 return; 2005 } 2006 LogTypeError({"Cannot inherit from class ", classType->SuperType()->Name(), ", because ", targetType, " ", 2007 it->Name(), " is inherited with a different declaration type"}, 2008 classDef->Super()->Start()); 2009 } 2010} 2011 2012void ETSChecker::TransformProperties(ETSObjectType *classType) 2013{ 2014 auto propertyList = classType->Fields(); 2015 auto *const classDef = classType->GetDeclNode()->AsClassDefinition(); 2016 2017 for (auto *const field : propertyList) { 2018 ASSERT(field->Declaration()->Node()->IsClassProperty()); 2019 auto *const originalProp = field->Declaration()->Node()->AsClassProperty(); 2020 2021 if ((originalProp->Modifiers() & ir::ModifierFlags::GETTER_SETTER) == 0U) { 2022 continue; 2023 } 2024 2025 if (!field->HasFlag(varbinder::VariableFlags::PUBLIC)) { 2026 LogTypeError("Interface property implementation cannot be generated as non-public", 2027 field->Declaration()->Node()->Start()); 2028 } 2029 classType->RemoveProperty<checker::PropertyType::INSTANCE_FIELD>(field); 2030 GenerateGetterSetterPropertyAndMethod(originalProp, classType); 2031 } 2032 2033 for (auto it = classDef->Body().begin(); it != classDef->Body().end(); ++it) { 2034 if ((*it)->IsClassProperty() && ((*it)->Modifiers() & ir::ModifierFlags::GETTER_SETTER) != 0U) { 2035 classDef->Body().erase(it); 2036 } 2037 } 2038} 2039 2040void ETSChecker::CheckGetterSetterProperties(ETSObjectType *classType) 2041{ 2042 auto const checkGetterSetter = [this](varbinder::LocalVariable *var, util::StringView name) { 2043 auto const *type = var->TsType()->AsETSFunctionType(); 2044 auto const *sigGetter = type->FindGetter(); 2045 auto const *sigSetter = type->FindSetter(); 2046 2047 for (auto const *sig : type->CallSignatures()) { 2048 if (!sig->Function()->IsGetter() && !sig->Function()->IsSetter()) { 2049 LogTypeError({"Method cannot use the same name as ", name, " accessor property"}, 2050 sig->Function()->Start()); 2051 return; 2052 } 2053 if (sig != sigGetter && sig != sigSetter) { 2054 LogTypeError("Duplicate accessor definition", sig->Function()->Start()); 2055 return; 2056 } 2057 } 2058 if (sigSetter != nullptr && ((sigGetter->Function()->Modifiers() ^ sigSetter->Function()->Modifiers()) & 2059 ir::ModifierFlags::ACCESSOR_MODIFIERS) != 0) { 2060 LogTypeError("Getter and setter methods must have the same accessor modifiers", 2061 sigGetter->Function()->Start()); 2062 } 2063 }; 2064 2065 for (const auto &[name, var] : classType->InstanceMethods()) { 2066 if (IsVariableGetterSetter(var)) { 2067 checkGetterSetter(var, name); 2068 } 2069 } 2070 2071 for (const auto &[name, var] : classType->StaticMethods()) { 2072 if (IsVariableGetterSetter(var)) { 2073 checkGetterSetter(var, name); 2074 } 2075 } 2076} 2077 2078void ETSChecker::AddElementsToModuleObject(ETSObjectType *moduleObj, const util::StringView &str) 2079{ 2080 for (const auto &[name, var] : VarBinder()->GetScope()->Bindings()) { 2081 if (name.Is(str.Mutf8()) || name.Is(compiler::Signatures::ETS_GLOBAL)) { 2082 continue; 2083 } 2084 2085 if (var->HasFlag(varbinder::VariableFlags::METHOD)) { 2086 moduleObj->AddProperty<checker::PropertyType::STATIC_METHOD>(var->AsLocalVariable()); 2087 } else if (var->HasFlag(varbinder::VariableFlags::PROPERTY)) { 2088 moduleObj->AddProperty<checker::PropertyType::STATIC_FIELD>(var->AsLocalVariable()); 2089 } else { 2090 moduleObj->AddProperty<checker::PropertyType::STATIC_DECL>(var->AsLocalVariable()); 2091 } 2092 } 2093} 2094 2095// This function computes effective runtime view of type 2096Type *ETSChecker::GetApparentType(Type *type) 2097{ 2098 if (auto it = apparentTypes_.find(type); LIKELY(it != apparentTypes_.end())) { 2099 return it->second; 2100 } 2101 auto cached = [this, type](Type *res) { 2102 if (type != res) { 2103 apparentTypes_.insert({type, res}); 2104 } 2105 apparentTypes_.insert({res, res}); 2106 return res; 2107 }; 2108 2109 if (type->IsETSTypeParameter()) { 2110 return cached(GetApparentType(type->AsETSTypeParameter()->GetConstraintType())); 2111 } 2112 if (type->IsETSNonNullishType()) { 2113 return cached( 2114 GetNonNullishType(GetApparentType(type->AsETSNonNullishType()->GetUnderlying()->GetConstraintType()))); 2115 } 2116 if (type->IsETSArrayType()) { 2117 return cached(type); 2118 } 2119 if (type->IsETSUnionType()) { 2120 bool differ = false; 2121 ArenaVector<checker::Type *> newConstituent(Allocator()->Adapter()); 2122 for (auto const &ct : type->AsETSUnionType()->ConstituentTypes()) { 2123 newConstituent.push_back(GetApparentType(ct)); 2124 differ |= (newConstituent.back() != ct); 2125 } 2126 return cached(differ ? CreateETSUnionType(std::move(newConstituent)) : type); 2127 } 2128 return cached(type); 2129} 2130 2131Type const *ETSChecker::GetApparentType(Type const *type) const 2132{ 2133 if (auto it = apparentTypes_.find(type); LIKELY(it != apparentTypes_.end())) { 2134 return it->second; 2135 } 2136 // Relaxed for some types 2137 if (type->IsETSTypeParameter()) { 2138 return GetApparentType(type->AsETSTypeParameter()->GetConstraintType()); 2139 } 2140 if (type->IsETSArrayType()) { 2141 return type; 2142 } 2143 if (type->IsETSUnionType() || type->IsETSNonNullishType()) { 2144 ASSERT_PRINT(false, std::string("Type ") + type->ToString() + " was not found in apparent_types_"); 2145 } 2146 return type; 2147} 2148 2149ETSObjectType *ETSChecker::GetClosestCommonAncestor(ETSObjectType *source, ETSObjectType *target) 2150{ 2151 if (source->AsETSObjectType()->GetDeclNode() == target->AsETSObjectType()->GetDeclNode()) { 2152 return source; 2153 } 2154 if (target->SuperType() == nullptr) { 2155 return GlobalETSObjectType(); 2156 } 2157 2158 auto *targetBase = GetOriginalBaseType(target->SuperType()); 2159 auto *targetType = targetBase == nullptr ? target->SuperType() : targetBase; 2160 2161 auto *sourceBase = GetOriginalBaseType(source); 2162 auto *sourceType = sourceBase == nullptr ? source : sourceBase; 2163 2164 if (Relation()->IsSupertypeOf(targetType, sourceType)) { 2165 // NOTE: TorokG. Extending the search to find intersection types 2166 return targetType; 2167 } 2168 2169 return GetClosestCommonAncestor(sourceType, targetType); 2170} 2171 2172void ETSChecker::CheckInvokeMethodsLegitimacy(ETSObjectType *const classType) 2173{ 2174 if (classType->HasObjectFlag(ETSObjectFlags::CHECKED_INVOKE_LEGITIMACY)) { 2175 return; 2176 } 2177 2178 auto searchFlag = PropertySearchFlags::SEARCH_IN_INTERFACES | PropertySearchFlags::SEARCH_IN_BASE | 2179 PropertySearchFlags::SEARCH_STATIC_METHOD; 2180 2181 auto *const invokeMethod = classType->GetProperty(compiler::Signatures::STATIC_INVOKE_METHOD, searchFlag); 2182 if (invokeMethod == nullptr) { 2183 classType->AddObjectFlag(ETSObjectFlags::CHECKED_INVOKE_LEGITIMACY); 2184 return; 2185 } 2186 2187 auto *const instantiateMethod = classType->GetProperty(compiler::Signatures::STATIC_INSTANTIATE_METHOD, searchFlag); 2188 if (instantiateMethod != nullptr) { 2189 LogTypeError({"Static ", compiler::Signatures::STATIC_INVOKE_METHOD, " method and static ", 2190 compiler::Signatures::STATIC_INSTANTIATE_METHOD, " method both exist in class/interface ", 2191 classType->Name(), " is not allowed."}, 2192 classType->GetDeclNode()->Start()); 2193 } 2194 classType->AddObjectFlag(ETSObjectFlags::CHECKED_INVOKE_LEGITIMACY); 2195} 2196 2197} // namespace ark::es2panda::checker 2198