1 /* 2 * Copyright (c) 2021-2025 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 #ifndef ES2PANDA_COMPILER_CHECKER_TYPES_ETS_OBJECT_TYPE_H 17 #define ES2PANDA_COMPILER_CHECKER_TYPES_ETS_OBJECT_TYPE_H 18 19 #include "checker/types/type.h" 20 #include "checker/types/ets/etsObjectTypeConstants.h" 21 #include "checker/types/signature.h" 22 #include "ir/ts/tsInterfaceDeclaration.h" 23 #include "ir/ts/tsTypeParameterDeclaration.h" 24 #include "ir/ts/tsEnumDeclaration.h" 25 #include "varbinder/scope.h" 26 #include "ir/base/classDefinition.h" 27 28 namespace ark::es2panda::checker { 29 using PropertyProcesser = std::function<varbinder::LocalVariable *(varbinder::LocalVariable *, Type *)>; 30 31 inline constexpr auto *PARTIAL_CLASS_SUFFIX = "$partial"; 32 33 class ETSObjectType : public Type { 34 public: 35 using PropertyMap = ArenaUnorderedMap<util::StringView, varbinder::LocalVariable *>; 36 using InstantiationMap = ArenaUnorderedMap<util::StringView, ETSObjectType *>; 37 using PropertyTraverser = std::function<void(const varbinder::LocalVariable *)>; 38 using PropertyHolder = std::array<PropertyMap, static_cast<size_t>(PropertyType::COUNT)>; 39 ETSObjectType(ArenaAllocator * allocator,util::StringView name,util::StringView internalName,ir::AstNode * declNode,ETSObjectFlags flags)40 explicit ETSObjectType(ArenaAllocator *allocator, util::StringView name, util::StringView internalName, 41 ir::AstNode *declNode, ETSObjectFlags flags) 42 : ETSObjectType(allocator, name, internalName, std::make_tuple(declNode, flags, nullptr), 43 std::make_index_sequence<static_cast<size_t>(PropertyType::COUNT)> {}) 44 { 45 } 46 ETSObjectType(ArenaAllocator * allocator,util::StringView name,util::StringView internalName,std::tuple<ir::AstNode *,ETSObjectFlags,TypeRelation * > info)47 explicit ETSObjectType(ArenaAllocator *allocator, util::StringView name, util::StringView internalName, 48 std::tuple<ir::AstNode *, ETSObjectFlags, TypeRelation *> info) 49 : ETSObjectType(allocator, name, internalName, info, 50 std::make_index_sequence<static_cast<size_t>(PropertyType::COUNT)> {}) 51 { 52 } 53 AddConstructSignature(Signature * signature)54 void AddConstructSignature(Signature *signature) 55 { 56 constructSignatures_.push_back(signature); 57 propertiesInstantiated_ = true; 58 } 59 AddConstructSignature(const ArenaVector<Signature * > & signatures)60 void AddConstructSignature(const ArenaVector<Signature *> &signatures) const 61 { 62 constructSignatures_.insert(constructSignatures_.end(), signatures.begin(), signatures.end()); 63 propertiesInstantiated_ = true; 64 } 65 AddInterface(ETSObjectType * interfaceType)66 void AddInterface(ETSObjectType *interfaceType) 67 { 68 if (std::find(interfaces_.begin(), interfaces_.end(), interfaceType) == interfaces_.end()) { 69 interfaces_.push_back(interfaceType); 70 } 71 } 72 SetSuperType(ETSObjectType * super)73 void SetSuperType(ETSObjectType *super) 74 { 75 superType_ = super; 76 } 77 SetTypeArguments(ArenaVector<Type * > && typeArgs)78 void SetTypeArguments(ArenaVector<Type *> &&typeArgs) 79 { 80 #ifndef NDEBUG 81 for (auto const &t : typeArgs) { 82 ES2PANDA_ASSERT(t->IsETSReferenceType()); 83 } 84 #endif 85 typeArguments_ = std::move(typeArgs); 86 } 87 SetEnclosingType(ETSObjectType * enclosingType)88 void SetEnclosingType(ETSObjectType *enclosingType) 89 { 90 enclosingType_ = enclosingType; 91 } 92 SetRelation(TypeRelation * relation)93 void SetRelation(TypeRelation *relation) 94 { 95 relation_ = relation; 96 } 97 GetRelation()98 TypeRelation *GetRelation() const 99 { 100 return relation_; 101 } 102 InstanceMethods()103 PropertyMap &InstanceMethods() const 104 { 105 EnsurePropertiesInstantiated(); 106 return properties_[static_cast<size_t>(PropertyType::INSTANCE_METHOD)]; 107 } 108 InstanceFields()109 PropertyMap &InstanceFields() const 110 { 111 EnsurePropertiesInstantiated(); 112 return properties_[static_cast<size_t>(PropertyType::INSTANCE_FIELD)]; 113 } 114 InstanceDecls()115 PropertyMap &InstanceDecls() const 116 { 117 EnsurePropertiesInstantiated(); 118 return properties_[static_cast<size_t>(PropertyType::INSTANCE_DECL)]; 119 } 120 StaticMethods()121 PropertyMap &StaticMethods() const 122 { 123 EnsurePropertiesInstantiated(); 124 return properties_[static_cast<size_t>(PropertyType::STATIC_METHOD)]; 125 } 126 StaticFields()127 PropertyMap &StaticFields() const 128 { 129 EnsurePropertiesInstantiated(); 130 return properties_[static_cast<size_t>(PropertyType::STATIC_FIELD)]; 131 } 132 StaticDecls()133 PropertyMap &StaticDecls() const 134 { 135 EnsurePropertiesInstantiated(); 136 return properties_[static_cast<size_t>(PropertyType::STATIC_DECL)]; 137 } 138 TypeArguments()139 const ArenaVector<Type *> &TypeArguments() const 140 { 141 return typeArguments_; 142 } 143 ConstructSignatures()144 const ArenaVector<Signature *> &ConstructSignatures() const 145 { 146 EnsurePropertiesInstantiated(); 147 return constructSignatures_; 148 } 149 ConstructSignatures()150 ArenaVector<Signature *> &ConstructSignatures() 151 { 152 EnsurePropertiesInstantiated(); 153 return constructSignatures_; 154 } 155 Interfaces()156 const ArenaVector<ETSObjectType *> &Interfaces() const 157 { 158 return interfaces_; 159 } 160 Interfaces()161 ArenaVector<ETSObjectType *> &Interfaces() 162 { 163 return interfaces_; 164 } 165 GetDeclNode()166 ir::AstNode *GetDeclNode() const 167 { 168 return declNode_; 169 } 170 SuperType()171 const ETSObjectType *SuperType() const 172 { 173 return superType_; 174 } 175 SuperType()176 ETSObjectType *SuperType() 177 { 178 return superType_; 179 } 180 EnclosingType()181 const ETSObjectType *EnclosingType() const 182 { 183 return enclosingType_; 184 } 185 EnclosingType()186 ETSObjectType *EnclosingType() 187 { 188 return enclosingType_; 189 } 190 OutermostClass()191 ETSObjectType *OutermostClass() 192 { 193 auto *iter = enclosingType_; 194 195 while (iter != nullptr && iter->EnclosingType() != nullptr) { 196 iter = iter->EnclosingType(); 197 } 198 199 return iter; 200 } 201 SetBaseType(ETSObjectType * baseType)202 void SetBaseType(ETSObjectType *baseType) 203 { 204 baseType_ = baseType; 205 } 206 GetBaseType()207 ETSObjectType *GetBaseType() noexcept 208 { 209 return baseType_; 210 } 211 GetBaseType()212 const ETSObjectType *GetBaseType() const noexcept 213 { 214 return baseType_; 215 } 216 217 ETSObjectType const *GetConstOriginalBaseType() const noexcept; 218 GetOriginalBaseType()219 ETSObjectType *GetOriginalBaseType() const noexcept 220 { 221 return const_cast<ETSObjectType *>(GetConstOriginalBaseType()); 222 } 223 IsGlobalETSObjectType()224 bool IsGlobalETSObjectType() const noexcept 225 { 226 return superType_ == nullptr; 227 } 228 229 bool IsPropertyInherited(const varbinder::Variable *var); 230 231 bool IsPropertyOfAscendant(const varbinder::Variable *var) const; 232 233 bool IsSignatureInherited(Signature *signature); 234 235 bool IsDescendantOf(const ETSObjectType *ascendant) const; 236 Name()237 const util::StringView &Name() const 238 { 239 return name_; 240 } 241 AssemblerName()242 const util::StringView &AssemblerName() const 243 { 244 return internalName_; 245 } 246 ObjectFlags()247 ETSObjectFlags ObjectFlags() const 248 { 249 return flags_; 250 } 251 AddObjectFlag(ETSObjectFlags flag)252 void AddObjectFlag(ETSObjectFlags flag) 253 { 254 flags_ |= flag; 255 } 256 RemoveObjectFlag(ETSObjectFlags flag)257 void RemoveObjectFlag(ETSObjectFlags flag) 258 { 259 flags_ &= ~flag; 260 } 261 HasObjectFlag(ETSObjectFlags flag)262 bool HasObjectFlag(ETSObjectFlags flag) const 263 { 264 return (flags_ & flag) != 0; 265 } 266 IsETSStringLiteralType()267 bool IsETSStringLiteralType() const 268 { 269 return superType_ != nullptr && superType_->IsETSObjectType() && 270 superType_->HasObjectFlag(ETSObjectFlags::STRING); 271 } 272 273 ETSFunctionType *GetFunctionalInterfaceInvokeType() const; 274 BuiltInKind()275 ETSObjectFlags BuiltInKind() const 276 { 277 return static_cast<checker::ETSObjectFlags>(flags_ & ETSObjectFlags::BUILTIN_TYPE); 278 } 279 UnboxableKind()280 ETSObjectFlags UnboxableKind() const 281 { 282 return static_cast<checker::ETSObjectFlags>(flags_ & ETSObjectFlags::UNBOXABLE_TYPE); 283 } 284 GetInstantiatedType(util::StringView hash)285 ETSObjectType *GetInstantiatedType(util::StringView hash) 286 { 287 auto found = instantiationMap_.find(hash); 288 if (found != instantiationMap_.end()) { 289 return found->second; 290 } 291 292 return nullptr; 293 } 294 GetTypeArgumentScope()295 varbinder::Scope *GetTypeArgumentScope() const 296 { 297 auto *typeParams = GetTypeParams(); 298 if (typeParams == nullptr) { 299 return nullptr; 300 } 301 return typeParams->Scope(); 302 } 303 GetInstantiationMap()304 InstantiationMap &GetInstantiationMap() 305 { 306 return instantiationMap_; 307 } 308 309 template <PropertyType TYPE> GetOwnProperty(const util::StringView & name)310 varbinder::LocalVariable *GetOwnProperty(const util::StringView &name) const 311 { 312 EnsurePropertiesInstantiated(); 313 auto found = properties_[static_cast<size_t>(TYPE)].find(name); 314 if (found != properties_[static_cast<size_t>(TYPE)].end()) { 315 return found->second; 316 } 317 return nullptr; 318 } 319 320 template <PropertyType TYPE> AddProperty(varbinder::LocalVariable * prop)321 void AddProperty(varbinder::LocalVariable *prop) const 322 { 323 properties_[static_cast<size_t>(TYPE)].emplace(prop->Name(), prop); 324 propertiesInstantiated_ = true; 325 } 326 327 template <PropertyType TYPE> AddProperty(varbinder::LocalVariable * prop,util::StringView localName)328 void AddProperty(varbinder::LocalVariable *prop, util::StringView localName) const 329 { 330 util::StringView nameToAccess = prop->Name(); 331 332 if (!localName.Empty()) { 333 nameToAccess = localName; 334 } 335 336 properties_[static_cast<size_t>(TYPE)].emplace(nameToAccess, prop); 337 propertiesInstantiated_ = true; 338 } 339 340 template <PropertyType TYPE> RemoveProperty(varbinder::LocalVariable * prop)341 void RemoveProperty(varbinder::LocalVariable *prop) 342 { 343 properties_[static_cast<size_t>(TYPE)].erase(prop->Name()); 344 propertiesInstantiated_ = true; 345 } 346 IsGeneric()347 [[nodiscard]] bool IsGeneric() const noexcept 348 { 349 return !typeArguments_.empty(); 350 } 351 IsPartial()352 [[nodiscard]] bool IsPartial() const noexcept 353 { 354 return name_.EndsWith(PARTIAL_CLASS_SUFFIX); 355 } 356 357 std::vector<const varbinder::LocalVariable *> ForeignProperties() const; 358 varbinder::LocalVariable *GetProperty(const util::StringView &name, PropertySearchFlags flags) const; 359 std::vector<varbinder::LocalVariable *> GetAllProperties() const; 360 varbinder::LocalVariable *CopyProperty(varbinder::LocalVariable *prop, ArenaAllocator *allocator, 361 TypeRelation *relation, GlobalTypesHolder *globalTypes); 362 std::vector<varbinder::LocalVariable *> Methods() const; 363 std::vector<varbinder::LocalVariable *> Fields() const; 364 varbinder::LocalVariable *CreateSyntheticVarFromEverySignature(const util::StringView &name, 365 PropertySearchFlags flags) const; 366 varbinder::LocalVariable *CollectSignaturesForSyntheticType(std::vector<Signature *> &signatures, 367 const util::StringView &name, 368 PropertySearchFlags flags) const; 369 bool CheckIdenticalFlags(ETSObjectType *other) const; 370 371 void Iterate(const PropertyTraverser &cb) const; 372 void ToString(std::stringstream &ss, bool precise) const override; 373 void Identical(TypeRelation *relation, Type *other) override; 374 bool AssignmentSource(TypeRelation *relation, Type *target) override; 375 void AssignmentTarget(TypeRelation *relation, Type *source) override; 376 bool IsBoxedPrimitive() const; 377 Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; 378 void UpdateTypeProperties(checker::ETSChecker *checker, PropertyProcesser const &func); 379 ETSObjectType *Substitute(TypeRelation *relation, const Substitution *substitution) override; 380 ETSObjectType *Substitute(TypeRelation *relation, const Substitution *substitution, bool cache, 381 bool isExtensionFunctionType = false); 382 ETSObjectType *SubstituteArguments(TypeRelation *relation, ArenaVector<Type *> const &arguments); 383 void Cast(TypeRelation *relation, Type *target) override; 384 bool CastNumericObject(TypeRelation *relation, Type *target); 385 void IsSupertypeOf(TypeRelation *relation, Type *source) override; 386 void IsSubtypeOf(TypeRelation *relation, Type *target) override; 387 Type *AsSuper(Checker *checker, varbinder::Variable *sourceVar) override; 388 void ToAssemblerType([[maybe_unused]] std::stringstream &ss) const override; 389 static std::string NameToDescriptor(util::StringView name); 390 void ToDebugInfoType(std::stringstream &ss) const override; 391 void ToDebugInfoSignatureType(std::stringstream &ss) const; 392 void CheckVarianceRecursively(TypeRelation *relation, VarianceFlag varianceFlag) override; 393 394 void AddReExports(ETSObjectType *reExport); 395 void AddReExportAlias(util::StringView const &value, util::StringView const &key); 396 util::StringView GetReExportAliasValue(util::StringView const &key) const; 397 bool IsReExportHaveAliasValue(util::StringView const &key) const; 398 const ArenaVector<ETSObjectType *> &ReExports() const; 399 bool IsSameBasedGeneric(TypeRelation *relation, Type const *other) const; 400 Allocator()401 ArenaAllocator *Allocator() const 402 { 403 return allocator_; 404 } 405 ResolveConditionExpr()406 std::tuple<bool, bool> ResolveConditionExpr() const override 407 { 408 return {false, false}; 409 } 410 411 [[nodiscard]] static std::uint32_t GetPrecedence(checker::ETSChecker *checker, ETSObjectType const *type) noexcept; 412 IsPropertiesInstantiated()413 bool IsPropertiesInstantiated() const 414 { 415 return propertiesInstantiated_; 416 } 417 418 protected: 419 virtual ETSFunctionType *CreateMethodTypeForProp(const util::StringView &name) const; 420 421 private: 422 template <size_t... IS> ETSObjectType(ArenaAllocator * allocator,util::StringView name,util::StringView assemblerName,std::tuple<ir::AstNode *,ETSObjectFlags,TypeRelation * > info,std::index_sequence<IS...> s)423 explicit ETSObjectType(ArenaAllocator *allocator, util::StringView name, util::StringView assemblerName, 424 std::tuple<ir::AstNode *, ETSObjectFlags, TypeRelation *> info, 425 [[maybe_unused]] std::index_sequence<IS...> s) 426 : Type(TypeFlag::ETS_OBJECT), 427 allocator_(allocator), 428 name_(name), 429 internalName_(assemblerName), 430 declNode_(std::get<ir::AstNode *>(info)), 431 interfaces_(allocator->Adapter()), 432 reExports_(allocator->Adapter()), 433 reExportAlias_(allocator->Adapter()), 434 flags_(std::get<ETSObjectFlags>(info)), 435 instantiationMap_(allocator->Adapter()), 436 typeArguments_(allocator->Adapter()), 437 relation_(std::get<TypeRelation *>(info)), 438 constructSignatures_(allocator->Adapter()), 439 properties_ {(void(IS), PropertyMap {allocator->Adapter()})...} 440 { 441 } 442 443 /* Properties and construct signatures are instantiated lazily. */ 444 void InstantiateProperties() const; EnsurePropertiesInstantiated()445 void EnsurePropertiesInstantiated() const 446 { 447 if (!propertiesInstantiated_) { 448 if (isInstantiatingProperties_) { 449 return; // avoid infinite recursive call 450 } 451 isInstantiatingProperties_ = true; 452 InstantiateProperties(); 453 isInstantiatingProperties_ = false; 454 propertiesInstantiated_ = true; 455 } 456 } 457 bool CastWideningNarrowing(TypeRelation *relation, Type *target, TypeFlag unboxFlags, TypeFlag wideningFlags, 458 TypeFlag narrowingFlags); 459 void IdenticalUptoTypeArguments(TypeRelation *relation, Type *other); 460 void SubstitutePartialTypes(TypeRelation *relation, Type *other); 461 void IsGenericSupertypeOf(TypeRelation *relation, ETSObjectType *source); 462 void UpdateTypeProperty(checker::ETSChecker *checker, varbinder::LocalVariable *const prop, PropertyType fieldType, 463 PropertyProcesser const &func); 464 465 varbinder::LocalVariable *SearchFieldsDecls(const util::StringView &name, PropertySearchFlags flags) const; 466 467 void SetCopiedTypeProperties(TypeRelation *relation, ETSObjectType *copiedType, ArenaVector<Type *> &&newTypeArgs, 468 ETSObjectType *base); 469 bool SubstituteTypeArgs(TypeRelation *relation, ArenaVector<Type *> &newTypeArgs, const Substitution *substitution); 470 471 bool TryCastByte(TypeRelation *const relation, Type *const target); 472 bool TryCastIntegral(TypeRelation *const relation, Type *const target); 473 bool TryCastFloating(TypeRelation *const relation, Type *const target); 474 bool TryCastUnboxable(TypeRelation *const relation, Type *const target); 475 476 ir::TSTypeParameterDeclaration *GetTypeParams() const; 477 478 ArenaAllocator *const allocator_; 479 util::StringView const name_; 480 util::StringView const internalName_; 481 ir::AstNode *const declNode_; 482 ArenaVector<ETSObjectType *> interfaces_; 483 ArenaVector<ETSObjectType *> reExports_; 484 ArenaMap<util::StringView, util::StringView> reExportAlias_; 485 ETSObjectFlags flags_; 486 InstantiationMap instantiationMap_; 487 ArenaVector<Type *> typeArguments_; 488 ETSObjectType *superType_ {}; 489 ETSObjectType *enclosingType_ {}; 490 ETSObjectType *baseType_ {}; 491 492 // for lazy properties instantiation 493 TypeRelation *relation_ = nullptr; 494 const Substitution *effectiveSubstitution_ = nullptr; 495 mutable bool isInstantiatingProperties_ = false; 496 mutable bool propertiesInstantiated_ = false; 497 mutable ArenaVector<Signature *> constructSignatures_; 498 mutable PropertyHolder properties_; 499 }; 500 } // namespace ark::es2panda::checker 501 502 #endif /* TYPESCRIPT_TYPES_FUNCTION_TYPE_H */ 503