• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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