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_PARSER_INCLUDE_AST_CLASS_DEFINITION_H 17 #define ES2PANDA_PARSER_INCLUDE_AST_CLASS_DEFINITION_H 18 19 #include "varbinder/scope.h" 20 #include "varbinder/variable.h" 21 #include "ir/srcDump.h" 22 #include "ir/annotationAllowed.h" 23 #include "ir/astNode.h" 24 #include "ir/expressions/identifier.h" 25 #include "ir/jsDocAllowed.h" 26 #include "ir/statements/annotationUsage.h" 27 #include "ir/statements/classDeclaration.h" 28 #include "util/language.h" 29 30 namespace ark::es2panda::ir { 31 class ClassElement; 32 class Identifier; 33 class MethodDefinition; 34 class TSTypeParameterDeclaration; 35 class TSTypeParameterInstantiation; 36 class TSClassImplements; 37 class TSIndexSignature; 38 39 using ENUMBITOPS_OPERATORS; 40 41 enum class ClassDefinitionModifiers : uint32_t { 42 NONE = 0, 43 DECLARATION = 1U << 0U, 44 ID_REQUIRED = 1U << 1U, 45 GLOBAL = 1U << 2U, 46 HAS_SUPER = 1U << 3U, 47 SET_CTOR_ID = 1U << 4U, 48 EXTERN = 1U << 5U, 49 ANONYMOUS = 1U << 6U, 50 GLOBAL_INITIALIZED = 1U << 7U, 51 CLASS_DECL = 1U << 8U, 52 INNER = 1U << 9U, 53 FROM_EXTERNAL = 1U << 10U, 54 LOCAL = 1U << 11U, 55 CLASSDEFINITION_CHECKED = 1U << 12U, 56 NAMESPACE_TRANSFORMED = 1U << 13U, 57 STRING_ENUM_TRANSFORMED = 1U << 14U, 58 INT_ENUM_TRANSFORMED = 1U << 15U, 59 FROM_STRUCT = 1U << 16U, 60 FUNCTIONAL_REFERENCE = 1U << 17U, 61 DECLARATION_ID_REQUIRED = DECLARATION | ID_REQUIRED, 62 ETS_MODULE = NAMESPACE_TRANSFORMED | GLOBAL 63 }; 64 65 } // namespace ark::es2panda::ir 66 67 template <> 68 struct enumbitops::IsAllowedType<ark::es2panda::ir::ClassDefinitionModifiers> : std::true_type { 69 }; 70 71 namespace ark::es2panda::ir { 72 73 class ClassDefinition : public JsDocAllowed<AnnotationAllowed<TypedAstNode>> { 74 public: 75 ClassDefinition() = delete; 76 ~ClassDefinition() override = default; 77 78 NO_COPY_SEMANTIC(ClassDefinition); 79 NO_MOVE_SEMANTIC(ClassDefinition); 80 // CC-OFFNXT(G.FUN.01-CPP) solid logic 81 explicit ClassDefinition(Identifier *ident, TSTypeParameterDeclaration *typeParams, 82 TSTypeParameterInstantiation *superTypeParams, 83 ArenaVector<TSClassImplements *> &&implements, MethodDefinition *ctor, 84 Expression *superClass, ArenaVector<AstNode *> &&body, ClassDefinitionModifiers modifiers, 85 ModifierFlags flags, Language lang) 86 : JsDocAllowed<AnnotationAllowed<TypedAstNode>>(AstNodeType::CLASS_DEFINITION, flags, 87 ArenaVector<AnnotationUsage *>(body.get_allocator()), 88 ArenaVector<JsDocInfo>(body.get_allocator())), 89 ident_(ident), 90 typeParams_(typeParams), 91 superTypeParams_(superTypeParams), 92 implements_(std::move(implements)), 93 ctor_(ctor), 94 superClass_(superClass), 95 body_(std::move(body)), 96 modifiers_(modifiers), 97 lang_(lang), 98 capturedVars_(body_.get_allocator()), 99 localVariableIsNeeded_(body_.get_allocator()), 100 localIndex_(classCounter_++), 101 localPrefix_("$" + std::to_string(localIndex_)), 102 exportedClasses_(body_.get_allocator()) 103 { 104 } 105 // CC-OFFNXT(G.FUN.01-CPP) solid logic 106 explicit ClassDefinition(ArenaAllocator *allocator, Identifier *ident, ArenaVector<AstNode *> &&body, 107 ClassDefinitionModifiers modifiers, ModifierFlags flags, Language lang) 108 : JsDocAllowed<AnnotationAllowed<TypedAstNode>>(AstNodeType::CLASS_DEFINITION, flags, allocator), 109 ident_(ident), 110 implements_(allocator->Adapter()), 111 body_(std::move(body)), 112 modifiers_(modifiers), 113 lang_(lang), 114 capturedVars_(allocator->Adapter()), 115 localVariableIsNeeded_(allocator->Adapter()), 116 localIndex_(classCounter_++), 117 localPrefix_("$" + std::to_string(localIndex_)), 118 exportedClasses_(body_.get_allocator()) 119 { 120 } 121 122 explicit ClassDefinition(ArenaAllocator *allocator, Identifier *ident, ClassDefinitionModifiers modifiers, 123 ModifierFlags flags, Language lang) 124 : JsDocAllowed<AnnotationAllowed<TypedAstNode>>(AstNodeType::CLASS_DEFINITION, flags, allocator), 125 ident_(ident), 126 implements_(allocator->Adapter()), 127 body_(allocator->Adapter()), 128 modifiers_(modifiers), 129 lang_(lang), 130 capturedVars_(allocator->Adapter()), 131 localVariableIsNeeded_(allocator->Adapter()), 132 localIndex_(classCounter_++), 133 localPrefix_("$" + std::to_string(localIndex_)), 134 exportedClasses_(body_.get_allocator()) 135 { 136 } 137 138 [[nodiscard]] bool IsScopeBearer() const noexcept override 139 { 140 return true; 141 } 142 143 [[nodiscard]] varbinder::LocalScope *Scope() const noexcept override 144 { 145 return scope_; 146 } 147 148 void SetScope(varbinder::LocalScope *scope) 149 { 150 ES2PANDA_ASSERT(scope_ == nullptr); 151 scope_ = scope; 152 } 153 154 void ClearScope() noexcept override 155 { 156 scope_ = nullptr; 157 } 158 159 [[nodiscard]] const Identifier *Ident() const noexcept 160 { 161 return ident_; 162 } 163 164 [[nodiscard]] Identifier *Ident() noexcept 165 { 166 return ident_; 167 } 168 169 void SetIdent(ir::Identifier *ident) noexcept; 170 171 [[nodiscard]] const util::StringView &InternalName() const noexcept 172 { 173 return internalName_; 174 } 175 176 void SetInternalName(util::StringView internalName) noexcept 177 { 178 internalName_ = internalName; 179 } 180 181 [[nodiscard]] Expression *Super() noexcept 182 { 183 return superClass_; 184 } 185 186 [[nodiscard]] const Expression *Super() const noexcept 187 { 188 return superClass_; 189 } 190 191 void SetSuper(Expression *superClass) 192 { 193 superClass_ = superClass; 194 if (superClass_ != nullptr) { 195 superClass_->SetParent(this); 196 } 197 } 198 199 [[nodiscard]] bool IsGlobal() const noexcept 200 { 201 return (modifiers_ & ClassDefinitionModifiers::GLOBAL) != 0; 202 } 203 204 [[nodiscard]] bool IsLocal() const noexcept 205 { 206 return (modifiers_ & ClassDefinitionModifiers::LOCAL) != 0; 207 } 208 209 [[nodiscard]] bool IsExtern() const noexcept 210 { 211 return (modifiers_ & ClassDefinitionModifiers::EXTERN) != 0; 212 } 213 214 [[nodiscard]] bool IsFromExternal() const noexcept 215 { 216 return (modifiers_ & ClassDefinitionModifiers::FROM_EXTERNAL) != 0; 217 } 218 [[nodiscard]] bool IsInner() const noexcept 219 { 220 return (modifiers_ & ClassDefinitionModifiers::INNER) != 0; 221 } 222 223 [[nodiscard]] bool IsGlobalInitialized() const noexcept 224 { 225 return (modifiers_ & ClassDefinitionModifiers::GLOBAL_INITIALIZED) != 0; 226 } 227 228 [[nodiscard]] bool IsClassDefinitionChecked() const noexcept 229 { 230 return (modifiers_ & ClassDefinitionModifiers::CLASSDEFINITION_CHECKED) != 0; 231 } 232 233 [[nodiscard]] bool IsAnonymous() const noexcept 234 { 235 return (modifiers_ & ClassDefinitionModifiers::ANONYMOUS) != 0; 236 } 237 238 [[nodiscard]] bool IsIntEnumTransformed() const noexcept 239 { 240 return (modifiers_ & ClassDefinitionModifiers::INT_ENUM_TRANSFORMED) != 0; 241 } 242 243 [[nodiscard]] bool IsStringEnumTransformed() const noexcept 244 { 245 return (modifiers_ & ClassDefinitionModifiers::STRING_ENUM_TRANSFORMED) != 0; 246 } 247 248 [[nodiscard]] bool IsEnumTransformed() const noexcept 249 { 250 return IsIntEnumTransformed() || IsStringEnumTransformed(); 251 } 252 253 [[nodiscard]] bool IsNamespaceTransformed() const noexcept 254 { 255 return (modifiers_ & ClassDefinitionModifiers::NAMESPACE_TRANSFORMED) != 0; 256 } 257 258 [[nodiscard]] bool IsFromStruct() const noexcept 259 { 260 return (modifiers_ & ClassDefinitionModifiers::FROM_STRUCT) != 0; 261 } 262 263 [[nodiscard]] bool IsModule() const noexcept 264 { 265 return IsGlobal() || IsNamespaceTransformed(); 266 } 267 268 [[nodiscard]] es2panda::Language Language() const noexcept 269 { 270 return lang_; 271 } 272 273 void SetGlobalInitialized() noexcept 274 { 275 modifiers_ |= ClassDefinitionModifiers::GLOBAL_INITIALIZED; 276 } 277 278 void SetInnerModifier() noexcept 279 { 280 modifiers_ |= ClassDefinitionModifiers::INNER; 281 } 282 283 void SetClassDefinitionChecked() noexcept 284 { 285 modifiers_ |= ClassDefinitionModifiers::CLASSDEFINITION_CHECKED; 286 } 287 288 void SetAnonymousModifier() noexcept 289 { 290 modifiers_ |= ClassDefinitionModifiers::ANONYMOUS; 291 } 292 293 void SetNamespaceTransformed() noexcept 294 { 295 modifiers_ |= ClassDefinitionModifiers::NAMESPACE_TRANSFORMED; 296 } 297 298 void SetFromStructModifier() noexcept 299 { 300 modifiers_ |= ClassDefinitionModifiers::FROM_STRUCT; 301 } 302 303 [[nodiscard]] ClassDefinitionModifiers Modifiers() const noexcept 304 { 305 return modifiers_; 306 } 307 308 void SetModifiers(ClassDefinitionModifiers modifiers) noexcept 309 { 310 modifiers_ = modifiers; 311 } 312 313 void AddProperties(ArenaVector<AstNode *> &&body) 314 { 315 for (auto *prop : body) { 316 prop->SetParent(this); 317 } 318 319 body_.insert(body_.end(), body.begin(), body.end()); 320 } 321 322 [[nodiscard]] ArenaVector<AstNode *> &Body() noexcept 323 { 324 return body_; 325 } 326 327 [[nodiscard]] const ArenaVector<AstNode *> &Body() const noexcept 328 { 329 return body_; 330 } 331 332 [[nodiscard]] MethodDefinition *Ctor() noexcept 333 { 334 return ctor_; 335 } 336 337 void SetCtor(MethodDefinition *ctor) 338 { 339 ctor_ = ctor; 340 } 341 342 [[nodiscard]] ArenaVector<ir::TSClassImplements *> &Implements() noexcept 343 { 344 return implements_; 345 } 346 347 [[nodiscard]] const ArenaVector<ir::TSClassImplements *> &Implements() const noexcept 348 { 349 return implements_; 350 } 351 352 [[nodiscard]] const ir::TSTypeParameterDeclaration *TypeParams() const noexcept 353 { 354 return typeParams_; 355 } 356 357 [[nodiscard]] ir::TSTypeParameterDeclaration *TypeParams() noexcept 358 { 359 return typeParams_; 360 } 361 362 void SetTypeParams(ir::TSTypeParameterDeclaration *typeParams) 363 { 364 typeParams_ = typeParams; 365 } 366 367 const TSTypeParameterInstantiation *SuperTypeParams() const 368 { 369 return superTypeParams_; 370 } 371 372 TSTypeParameterInstantiation *SuperTypeParams() 373 { 374 return superTypeParams_; 375 } 376 377 [[nodiscard]] static int LocalTypeCounter() noexcept 378 { 379 return classCounter_; 380 } 381 382 [[nodiscard]] int LocalIndex() const noexcept 383 { 384 return localIndex_; 385 } 386 387 [[nodiscard]] MethodDefinition *FunctionalReferenceReferencedMethod() const noexcept 388 { 389 return functionalReferenceReferencedMethod_; 390 } 391 392 void SetFunctionalReferenceReferencedMethod(MethodDefinition *functionalReferenceReferencedMethod) 393 { 394 functionalReferenceReferencedMethod_ = functionalReferenceReferencedMethod; 395 } 396 397 [[nodiscard]] const std::string &LocalPrefix() const noexcept 398 { 399 return localPrefix_; 400 } 401 402 bool CaptureVariable(varbinder::Variable *var) 403 { 404 return capturedVars_.insert(var).second; 405 } 406 407 bool AddToLocalVariableIsNeeded(varbinder::Variable *var) 408 { 409 return localVariableIsNeeded_.insert(var).second; 410 } 411 412 bool IsLocalVariableNeeded(varbinder::Variable *var) const 413 { 414 return localVariableIsNeeded_.find(var) != localVariableIsNeeded_.end(); 415 } 416 417 [[nodiscard]] const ArenaSet<varbinder::Variable *> &CapturedVariables() const noexcept 418 { 419 return capturedVars_; 420 } 421 422 bool EraseCapturedVariable(varbinder::Variable *var) 423 { 424 return capturedVars_.erase(var) != 0; 425 } 426 427 void SetOrigEnumDecl(ir::TSEnumDeclaration *enumDecl) 428 { 429 origEnumDecl_ = enumDecl; 430 } 431 432 ir::TSEnumDeclaration *OrigEnumDecl() const 433 { 434 return origEnumDecl_; 435 } 436 437 ClassDeclaration *GetAnonClass() noexcept 438 { 439 return anonClass_; 440 } 441 442 void SetAnonClass(ClassDeclaration *anonClass) noexcept 443 { 444 anonClass_ = anonClass; 445 } 446 447 const FunctionExpression *Ctor() const; 448 bool HasPrivateMethod() const; 449 bool HasNativeMethod() const; 450 bool HasComputedInstanceField() const; 451 bool HasMatchingPrivateKey(const util::StringView &name) const; 452 453 void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) override; 454 void Iterate(const NodeTraverser &cb) const override; 455 456 void Dump(ir::AstDumper *dumper) const override; 457 void Dump(ir::SrcDumper *dumper) const override; 458 void Compile(compiler::PandaGen *pg) const override; 459 void Compile(compiler::ETSGen *etsg) const override; 460 checker::Type *Check(checker::TSChecker *checker) override; 461 checker::VerifiedType Check(checker::ETSChecker *checker) override; 462 463 void Accept(ASTVisitorT *v) override 464 { 465 v->Accept(this); 466 } 467 468 template <typename T> 469 static void DumpItems(ir::SrcDumper *dumper, const std::string &prefix, const ArenaVector<T *> &items) 470 { 471 if (items.empty()) { 472 return; 473 } 474 dumper->Add(prefix); 475 for (size_t i = 0; i < items.size(); ++i) { 476 items[i]->Dump(dumper); 477 if (i < items.size() - 1) { 478 dumper->Add(", "); 479 } 480 } 481 } 482 483 void CleanUp() override 484 { 485 AstNode::CleanUp(); 486 modifiers_ &= ~(ClassDefinitionModifiers::CLASSDEFINITION_CHECKED); 487 } 488 489 void AddToExportedClasses(const ir::ClassDeclaration *cls) 490 { 491 ES2PANDA_ASSERT(cls->IsExported() || cls->Definition()->IsGlobal()); 492 exportedClasses_.push_back(cls); 493 } 494 495 void BatchAddToExportedClasses(const ArenaVector<const ir::ClassDeclaration *> &classes) 496 { 497 for (const auto cls : classes) { 498 AddToExportedClasses(cls); 499 } 500 } 501 502 [[nodiscard]] const ArenaVector<const ir::ClassDeclaration *> &ExportedClasses() const noexcept 503 { 504 return exportedClasses_; 505 } 506 507 protected: 508 ClassDefinition *Construct(ArenaAllocator *allocator) override; 509 510 void CopyTo(AstNode *other) const override; 511 512 private: 513 void CompileStaticFieldInitializers(compiler::PandaGen *pg, compiler::VReg classReg, 514 const std::vector<compiler::VReg> &staticComputedFieldKeys) const; 515 516 // This method is needed by OHOS CI code checker 517 void DumpBody(ir::SrcDumper *dumper) const; 518 void DumpGlobalClass(ir::SrcDumper *dumper) const; 519 void DumpPrefix(ir::SrcDumper *dumper) const; 520 bool RegisterUnexportedForDeclGen(ir::SrcDumper *dumper) const; 521 522 friend class SizeOfNodeTest; 523 varbinder::LocalScope *scope_ {nullptr}; 524 util::StringView internalName_ {}; 525 Identifier *ident_ {}; 526 TSTypeParameterDeclaration *typeParams_ {}; 527 TSTypeParameterInstantiation *superTypeParams_ {}; 528 ArenaVector<TSClassImplements *> implements_; 529 MethodDefinition *ctor_ {}; 530 Expression *superClass_ {}; 531 ArenaVector<AstNode *> body_; 532 ClassDefinitionModifiers modifiers_; 533 es2panda::Language lang_; 534 ArenaSet<varbinder::Variable *> capturedVars_; 535 ArenaSet<varbinder::Variable *> localVariableIsNeeded_; 536 TSEnumDeclaration *origEnumDecl_ {}; 537 ClassDeclaration *anonClass_ {nullptr}; 538 static int classCounter_; 539 int localIndex_ {}; 540 std::string localPrefix_ {}; 541 MethodDefinition *functionalReferenceReferencedMethod_ {}; 542 ArenaVector<const ir::ClassDeclaration *> exportedClasses_; 543 }; 544 } // namespace ark::es2panda::ir 545 546 #endif 547