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_METHOD_DEFINITION_H
17 #define ES2PANDA_PARSER_INCLUDE_AST_METHOD_DEFINITION_H
18 
19 #include "ir/base/classElement.h"
20 
21 namespace ark::es2panda::checker {
22 class ETSAnalyzer;
23 }  // namespace ark::es2panda::checker
24 
25 namespace ark::es2panda::ir {
26 
27 class Expression;
28 class ScriptFunction;
29 
30 enum class MethodDefinitionKind { NONE, CONSTRUCTOR, METHOD, EXTENSION_METHOD, GET, SET };
31 
32 class MethodDefinition : public ClassElement {
33 public:
34     MethodDefinition() = delete;
35     ~MethodDefinition() override = default;
36 
37     NO_COPY_SEMANTIC(MethodDefinition);
38     NO_MOVE_SEMANTIC(MethodDefinition);
39 
40     using OverloadsT = ArenaVector<MethodDefinition *>;
41 
MethodDefinition(MethodDefinitionKind const kind, Expression *const key, Expression *const value, ModifierFlags const modifiers, ArenaAllocator *const allocator, bool const isComputed)42     explicit MethodDefinition(MethodDefinitionKind const kind, Expression *const key, Expression *const value,
43                               ModifierFlags const modifiers, ArenaAllocator *const allocator, bool const isComputed)
44         : ClassElement(AstNodeType::METHOD_DEFINITION, key, value, modifiers, allocator, isComputed),
45           kind_(kind),
46           overloads_(allocator->Adapter()),
47           baseOverloadMethod_(nullptr),
48           asyncPairMethod_(nullptr)
49     {
50         ASSERT(key_ != nullptr);
51         ASSERT(value != nullptr);
52     }
53 
54     // NOTE (csabahurton): these friend relationships can be removed once there are getters for private fields
55     friend class checker::ETSAnalyzer;
56 
Kind() const57     MethodDefinitionKind Kind() const
58     {
59         return kind_;
60     }
61 
62     [[nodiscard]] bool IsConstructor() const noexcept
63     {
64         return kind_ == MethodDefinitionKind::CONSTRUCTOR;
65     }
66 
67     [[nodiscard]] bool IsExtensionMethod() const noexcept
68     {
69         return kind_ == MethodDefinitionKind::EXTENSION_METHOD;
70     }
71 
72     [[nodiscard]] const OverloadsT &Overloads() const noexcept
73     {
74         return overloads_;
75     }
76 
77     [[nodiscard]] const MethodDefinition *BaseOverloadMethod() const noexcept
78     {
79         return baseOverloadMethod_;
80     }
81 
82     [[nodiscard]] MethodDefinition *BaseOverloadMethod() noexcept
83     {
84         return baseOverloadMethod_;
85     }
86 
87     [[nodiscard]] const MethodDefinition *AsyncPairMethod() const noexcept
88     {
89         return asyncPairMethod_;
90     }
91 
92     [[nodiscard]] MethodDefinition *AsyncPairMethod() noexcept
93     {
94         return asyncPairMethod_;
95     }
96 
SetOverloads(OverloadsT &&overloads)97     void SetOverloads(OverloadsT &&overloads)
98     {
99         overloads_ = std::move(overloads);
100     }
101 
ClearOverloads()102     void ClearOverloads()
103     {
104         overloads_.clear();
105     }
106 
AddOverload(MethodDefinition *const overload)107     void AddOverload(MethodDefinition *const overload)
108     {
109         overloads_.emplace_back(overload);
110         overload->SetBaseOverloadMethod(this);
111     }
112 
SetBaseOverloadMethod(MethodDefinition *const baseOverloadMethod)113     void SetBaseOverloadMethod(MethodDefinition *const baseOverloadMethod)
114     {
115         baseOverloadMethod_ = baseOverloadMethod;
116     }
117 
SetAsyncPairMethod(MethodDefinition *const method)118     void SetAsyncPairMethod(MethodDefinition *const method)
119     {
120         asyncPairMethod_ = method;
121     }
122 
123     [[nodiscard]] bool HasOverload(MethodDefinition *overload) noexcept
124     {
125         return std::find(overloads_.begin(), overloads_.end(), overload) != overloads_.end();
126     }
127 
128     ScriptFunction *Function();
129     const ScriptFunction *Function() const;
130     PrivateFieldKind ToPrivateFieldKind(bool isStatic) const override;
131 
132     [[nodiscard]] MethodDefinition *Clone(ArenaAllocator *allocator, AstNode *parent) override;
133 
134     void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) override;
135     void Iterate(const NodeTraverser &cb) const override;
136 
137     void ResolveReferences(const NodeTraverser &cb) const;
138 
139     void Dump(ir::AstDumper *dumper) const override;
140     void Dump(ir::SrcDumper *dumper) const override;
141     void Compile(compiler::PandaGen *pg) const override;
142     void Compile(compiler::ETSGen *etsg) const override;
143     checker::Type *Check(checker::TSChecker *checker) override;
144     checker::Type *Check(checker::ETSChecker *checker) override;
145 
146     void Accept(ASTVisitorT *v) override
147     {
148         v->Accept(this);
149     }
150 
151 private:
152     void DumpPrefix(ir::SrcDumper *dumper) const;
153 
154     MethodDefinitionKind kind_;
155     // Overloads are stored like in an 1:N fashion.
156     // The very firstly processed method becomes the base(1) and the others tied into it as overloads(N).
157     OverloadsT overloads_;
158     // Base overload method points at the first overload of the overloads.
159     MethodDefinition *baseOverloadMethod_;
160     // Pair method points at the original async method in case of an implement method and vice versa an implement
161     // method's point at the async method
162     MethodDefinition *asyncPairMethod_;
163 };
164 }  // namespace ark::es2panda::ir
165 
166 #endif
167