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
21namespace ark::es2panda::checker {
22class ETSAnalyzer;
23}  // namespace ark::es2panda::checker
24
25namespace ark::es2panda::ir {
26
27class Expression;
28class ScriptFunction;
29
30enum class MethodDefinitionKind { NONE, CONSTRUCTOR, METHOD, EXTENSION_METHOD, GET, SET };
31
32class MethodDefinition : public ClassElement {
33public:
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
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
57    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
97    void SetOverloads(OverloadsT &&overloads)
98    {
99        overloads_ = std::move(overloads);
100    }
101
102    void ClearOverloads()
103    {
104        overloads_.clear();
105    }
106
107    void AddOverload(MethodDefinition *const overload)
108    {
109        overloads_.emplace_back(overload);
110        overload->SetBaseOverloadMethod(this);
111    }
112
113    void SetBaseOverloadMethod(MethodDefinition *const baseOverloadMethod)
114    {
115        baseOverloadMethod_ = baseOverloadMethod;
116    }
117
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
151private:
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