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#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/astNode.h"
22#include "ir/expressions/identifier.h"
23#include "util/language.h"
24
25namespace ark::es2panda::ir {
26class ClassElement;
27class Identifier;
28class MethodDefinition;
29class TSTypeParameterDeclaration;
30class TSTypeParameterInstantiation;
31class TSClassImplements;
32class TSIndexSignature;
33
34using ENUMBITOPS_OPERATORS;
35
36enum class ClassDefinitionModifiers : uint32_t {
37    NONE = 0,
38    DECLARATION = 1U << 0U,
39    ID_REQUIRED = 1U << 1U,
40    GLOBAL = 1U << 2U,
41    HAS_SUPER = 1U << 3U,
42    SET_CTOR_ID = 1U << 4U,
43    EXTERN = 1U << 5U,
44    ANONYMOUS = 1U << 6U,
45    GLOBAL_INITIALIZED = 1U << 7U,
46    CLASS_DECL = 1U << 8U,
47    INNER = 1U << 9U,
48    FROM_EXTERNAL = 1U << 10U,
49    LOCAL = 1U << 11U,
50    CLASSDEFINITION_CHECKED = 1U << 12U,
51    DECLARATION_ID_REQUIRED = DECLARATION | ID_REQUIRED
52};
53
54}  // namespace ark::es2panda::ir
55
56template <>
57struct enumbitops::IsAllowedType<ark::es2panda::ir::ClassDefinitionModifiers> : std::true_type {
58};
59
60namespace ark::es2panda::ir {
61
62class ClassDefinition : public TypedAstNode {
63public:
64    ClassDefinition() = delete;
65    ~ClassDefinition() override = default;
66
67    NO_COPY_SEMANTIC(ClassDefinition);
68    NO_MOVE_SEMANTIC(ClassDefinition);
69
70    explicit ClassDefinition(const util::StringView &privateId, Identifier *ident,
71                             TSTypeParameterDeclaration *typeParams, TSTypeParameterInstantiation *superTypeParams,
72                             ArenaVector<TSClassImplements *> &&implements, MethodDefinition *ctor,
73                             Expression *superClass, ArenaVector<AstNode *> &&body, ClassDefinitionModifiers modifiers,
74                             ModifierFlags flags, Language lang)
75        : TypedAstNode(AstNodeType::CLASS_DEFINITION, flags),
76          privateId_(privateId),
77          ident_(ident),
78          typeParams_(typeParams),
79          superTypeParams_(superTypeParams),
80          implements_(std::move(implements)),
81          ctor_(ctor),
82          superClass_(superClass),
83          body_(std::move(body)),
84          modifiers_(modifiers),
85          lang_(lang),
86          capturedVars_(body_.get_allocator()),
87          localVariableIsNeeded_(body_.get_allocator()),
88          localIndex_(classCounter_++),
89          localPrefix_("$" + std::to_string(localIndex_))
90    {
91    }
92
93    explicit ClassDefinition(ArenaAllocator *allocator, Identifier *ident, ArenaVector<AstNode *> &&body,
94                             ClassDefinitionModifiers modifiers, ModifierFlags flags, Language lang)
95        : TypedAstNode(AstNodeType::CLASS_DEFINITION, flags),
96          ident_(ident),
97          implements_(allocator->Adapter()),
98          body_(std::move(body)),
99          modifiers_(modifiers),
100          lang_(lang),
101          capturedVars_(allocator->Adapter()),
102          localVariableIsNeeded_(allocator->Adapter()),
103          localIndex_(classCounter_++),
104          localPrefix_("$" + std::to_string(localIndex_))
105    {
106    }
107
108    explicit ClassDefinition(ArenaAllocator *allocator, Identifier *ident, ClassDefinitionModifiers modifiers,
109                             ModifierFlags flags, Language lang)
110        : TypedAstNode(AstNodeType::CLASS_DEFINITION, flags),
111          ident_(ident),
112          implements_(allocator->Adapter()),
113          body_(allocator->Adapter()),
114          modifiers_(modifiers),
115          lang_(lang),
116          capturedVars_(allocator->Adapter()),
117          localVariableIsNeeded_(allocator->Adapter()),
118          localIndex_(classCounter_++),
119          localPrefix_("$" + std::to_string(localIndex_))
120
121    {
122    }
123
124    [[nodiscard]] bool IsScopeBearer() const noexcept override
125    {
126        return true;
127    }
128
129    [[nodiscard]] varbinder::LocalScope *Scope() const noexcept override
130    {
131        return scope_;
132    }
133
134    void SetScope(varbinder::LocalScope *scope)
135    {
136        ASSERT(scope_ == nullptr);
137        scope_ = scope;
138    }
139
140    void ClearScope() noexcept override
141    {
142        scope_ = nullptr;
143    }
144
145    [[nodiscard]] const Identifier *Ident() const noexcept
146    {
147        return ident_;
148    }
149
150    [[nodiscard]] Identifier *Ident() noexcept
151    {
152        return ident_;
153    }
154
155    void SetIdent(ir::Identifier *ident) noexcept;
156
157    [[nodiscard]] const util::StringView &PrivateId() const noexcept
158    {
159        return privateId_;
160    }
161
162    [[nodiscard]] const util::StringView &InternalName() const noexcept
163    {
164        return privateId_;
165    }
166
167    void SetInternalName(util::StringView internalName) noexcept
168    {
169        privateId_ = internalName;
170    }
171
172    [[nodiscard]] Expression *Super() noexcept
173    {
174        return superClass_;
175    }
176
177    [[nodiscard]] const Expression *Super() const noexcept
178    {
179        return superClass_;
180    }
181
182    void SetSuper(Expression *superClass)
183    {
184        superClass_ = superClass;
185        if (superClass_ != nullptr) {
186            superClass_->SetParent(this);
187        }
188    }
189
190    [[nodiscard]] bool IsGlobal() const noexcept
191    {
192        return (modifiers_ & ClassDefinitionModifiers::GLOBAL) != 0;
193    }
194
195    [[nodiscard]] bool IsLocal() const noexcept
196    {
197        return (modifiers_ & ClassDefinitionModifiers::LOCAL) != 0;
198    }
199
200    [[nodiscard]] bool IsExtern() const noexcept
201    {
202        return (modifiers_ & ClassDefinitionModifiers::EXTERN) != 0;
203    }
204
205    [[nodiscard]] bool IsFromExternal() const noexcept
206    {
207        return (modifiers_ & ClassDefinitionModifiers::FROM_EXTERNAL) != 0;
208    }
209    [[nodiscard]] bool IsInner() const noexcept
210    {
211        return (modifiers_ & ClassDefinitionModifiers::INNER) != 0;
212    }
213
214    [[nodiscard]] bool IsGlobalInitialized() const noexcept
215    {
216        return (modifiers_ & ClassDefinitionModifiers::GLOBAL_INITIALIZED) != 0;
217    }
218
219    [[nodiscard]] bool IsClassDefinitionChecked() const noexcept
220    {
221        return (modifiers_ & ClassDefinitionModifiers::CLASSDEFINITION_CHECKED) != 0;
222    }
223
224    [[nodiscard]] es2panda::Language Language() const noexcept
225    {
226        return lang_;
227    }
228
229    void SetGlobalInitialized() noexcept
230    {
231        modifiers_ |= ClassDefinitionModifiers::GLOBAL_INITIALIZED;
232    }
233
234    void SetInnerModifier() noexcept
235    {
236        modifiers_ |= ClassDefinitionModifiers::INNER;
237    }
238
239    void SetClassDefinitionChecked() noexcept
240    {
241        modifiers_ |= ClassDefinitionModifiers::CLASSDEFINITION_CHECKED;
242    }
243
244    [[nodiscard]] ClassDefinitionModifiers Modifiers() const noexcept
245    {
246        return modifiers_;
247    }
248
249    void SetModifiers(ClassDefinitionModifiers modifiers) noexcept
250    {
251        modifiers_ = modifiers;
252    }
253
254    void AddProperties(ArenaVector<AstNode *> &&body)
255    {
256        for (auto *prop : body) {
257            prop->SetParent(this);
258        }
259
260        body_.insert(body_.end(), body.begin(), body.end());
261    }
262
263    [[nodiscard]] ArenaVector<AstNode *> &Body() noexcept
264    {
265        return body_;
266    }
267
268    [[nodiscard]] const ArenaVector<AstNode *> &Body() const noexcept
269    {
270        return body_;
271    }
272
273    [[nodiscard]] MethodDefinition *Ctor() noexcept
274    {
275        return ctor_;
276    }
277
278    void SetCtor(MethodDefinition *ctor)
279    {
280        ctor_ = ctor;
281    }
282
283    [[nodiscard]] ArenaVector<ir::TSClassImplements *> &Implements() noexcept
284    {
285        return implements_;
286    }
287
288    [[nodiscard]] const ArenaVector<ir::TSClassImplements *> &Implements() const noexcept
289    {
290        return implements_;
291    }
292
293    [[nodiscard]] const ir::TSTypeParameterDeclaration *TypeParams() const noexcept
294    {
295        return typeParams_;
296    }
297
298    [[nodiscard]] ir::TSTypeParameterDeclaration *TypeParams() noexcept
299    {
300        return typeParams_;
301    }
302
303    void SetTypeParams(ir::TSTypeParameterDeclaration *typeParams)
304    {
305        typeParams_ = typeParams;
306    }
307
308    const TSTypeParameterInstantiation *SuperTypeParams() const
309    {
310        return superTypeParams_;
311    }
312
313    TSTypeParameterInstantiation *SuperTypeParams()
314    {
315        return superTypeParams_;
316    }
317
318    [[nodiscard]] static int LocalTypeCounter() noexcept
319    {
320        return classCounter_;
321    }
322
323    [[nodiscard]] int LocalIndex() const noexcept
324    {
325        return localIndex_;
326    }
327
328    [[nodiscard]] const std::string &LocalPrefix() const noexcept
329    {
330        return localPrefix_;
331    }
332
333    bool CaptureVariable(varbinder::Variable *var)
334    {
335        return capturedVars_.insert(var).second;
336    }
337
338    bool AddToLocalVariableIsNeeded(varbinder::Variable *var)
339    {
340        return localVariableIsNeeded_.insert(var).second;
341    }
342
343    bool IsLocalVariableNeeded(varbinder::Variable *var) const
344    {
345        return localVariableIsNeeded_.find(var) != localVariableIsNeeded_.end();
346    }
347
348    [[nodiscard]] const ArenaSet<varbinder::Variable *> &CapturedVariables() const noexcept
349    {
350        return capturedVars_;
351    }
352
353    bool EraseCapturedVariable(varbinder::Variable *var)
354    {
355        return capturedVars_.erase(var) != 0;
356    }
357
358    const FunctionExpression *Ctor() const;
359    bool HasPrivateMethod() const;
360    bool HasComputedInstanceField() const;
361    bool HasMatchingPrivateKey(const util::StringView &name) const;
362
363    void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) override;
364    void Iterate(const NodeTraverser &cb) const override;
365
366    void Dump(ir::AstDumper *dumper) const override;
367    void Dump(ir::SrcDumper *dumper) const override;
368    void Compile(compiler::PandaGen *pg) const override;
369    void Compile(compiler::ETSGen *etsg) const override;
370    checker::Type *Check(checker::TSChecker *checker) override;
371    checker::Type *Check(checker::ETSChecker *checker) override;
372
373    void Accept(ASTVisitorT *v) override
374    {
375        v->Accept(this);
376    }
377
378private:
379    void CompileStaticFieldInitializers(compiler::PandaGen *pg, compiler::VReg classReg,
380                                        const std::vector<compiler::VReg> &staticComputedFieldKeys) const;
381
382    // This method is needed by OHOS CI code checker
383    void DumpBody(ir::SrcDumper *dumper) const;
384
385    varbinder::LocalScope *scope_ {nullptr};
386    util::StringView privateId_ {};
387    Identifier *ident_ {};
388    TSTypeParameterDeclaration *typeParams_ {};
389    TSTypeParameterInstantiation *superTypeParams_ {};
390    ArenaVector<TSClassImplements *> implements_;
391    MethodDefinition *ctor_ {};
392    Expression *superClass_ {};
393    ArenaVector<AstNode *> body_;
394    ClassDefinitionModifiers modifiers_;
395    es2panda::Language lang_;
396    ArenaSet<varbinder::Variable *> capturedVars_;
397    ArenaSet<varbinder::Variable *> localVariableIsNeeded_;
398    static int classCounter_;
399    const int localIndex_ {};
400    const std::string localPrefix_ {};
401};
402}  // namespace ark::es2panda::ir
403
404#endif
405