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 #include "methodDefinition.h"
17
18 #include "checker/TSchecker.h"
19 #include "compiler/core/ETSGen.h"
20 #include "compiler/core/pandagen.h"
21 #include "ir/astDump.h"
22 #include "ir/srcDump.h"
23
24 namespace ark::es2panda::ir {
25
Function()26 ScriptFunction *MethodDefinition::Function()
27 {
28 return value_->IsFunctionExpression() ? value_->AsFunctionExpression()->Function() : nullptr;
29 }
30
Function() const31 const ScriptFunction *MethodDefinition::Function() const
32 {
33 return value_->IsFunctionExpression() ? value_->AsFunctionExpression()->Function() : nullptr;
34 }
35
ToPrivateFieldKind(bool const isStatic) const36 PrivateFieldKind MethodDefinition::ToPrivateFieldKind(bool const isStatic) const
37 {
38 switch (kind_) {
39 case MethodDefinitionKind::METHOD: {
40 return isStatic ? PrivateFieldKind::STATIC_METHOD : PrivateFieldKind::METHOD;
41 }
42 case MethodDefinitionKind::GET: {
43 return isStatic ? PrivateFieldKind::STATIC_GET : PrivateFieldKind::GET;
44 }
45 case MethodDefinitionKind::SET: {
46 return isStatic ? PrivateFieldKind::STATIC_SET : PrivateFieldKind::SET;
47 }
48 default: {
49 UNREACHABLE();
50 }
51 }
52 }
53
ResolveReferences(const NodeTraverser &cb) const54 void MethodDefinition::ResolveReferences(const NodeTraverser &cb) const
55 {
56 cb(key_);
57 cb(value_);
58
59 for (auto *it : overloads_) {
60 cb(it);
61 }
62
63 for (auto *it : decorators_) {
64 cb(it);
65 }
66 }
67
Iterate(const NodeTraverser &cb) const68 void MethodDefinition::Iterate(const NodeTraverser &cb) const
69 {
70 cb(key_);
71 cb(value_);
72
73 for (auto *it : overloads_) {
74 if (it->Parent() == this) {
75 cb(it);
76 }
77 }
78
79 for (auto *it : decorators_) {
80 cb(it);
81 }
82 }
83
TransformChildren(const NodeTransformer &cb, std::string_view const transformationName)84 void MethodDefinition::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName)
85 {
86 if (auto *transformedNode = cb(key_); key_ != transformedNode) {
87 key_->SetTransformedNode(transformationName, transformedNode);
88 key_ = transformedNode->AsExpression();
89 }
90
91 if (auto *transformedNode = cb(value_); value_ != transformedNode) {
92 value_->SetTransformedNode(transformationName, transformedNode);
93 value_ = transformedNode->AsExpression();
94 }
95
96 for (auto *&it : overloads_) {
97 if (auto *transformedNode = cb(it); it != transformedNode) {
98 it->SetTransformedNode(transformationName, transformedNode);
99 it = transformedNode->AsMethodDefinition();
100 }
101 }
102
103 for (auto *&it : decorators_) {
104 if (auto *transformedNode = cb(it); it != transformedNode) {
105 it->SetTransformedNode(transformationName, transformedNode);
106 it = transformedNode->AsDecorator();
107 }
108 }
109 }
110
Dump(ir::AstDumper *dumper) const111 void MethodDefinition::Dump(ir::AstDumper *dumper) const
112 {
113 const char *kind = nullptr;
114
115 switch (kind_) {
116 case MethodDefinitionKind::CONSTRUCTOR: {
117 kind = "constructor";
118 break;
119 }
120 case MethodDefinitionKind::METHOD: {
121 kind = "method";
122 break;
123 }
124 case MethodDefinitionKind::EXTENSION_METHOD: {
125 kind = "extensionmethod";
126 break;
127 }
128 case MethodDefinitionKind::GET: {
129 kind = "get";
130 break;
131 }
132 case MethodDefinitionKind::SET: {
133 kind = "set";
134 break;
135 }
136 default: {
137 UNREACHABLE();
138 }
139 }
140
141 dumper->Add({{"type", "MethodDefinition"},
142 {"key", key_},
143 {"kind", kind},
144 {"accessibility", AstDumper::Optional(AstDumper::ModifierToString(flags_))},
145 {"static", IsStatic()},
146 {"optional", IsOptionalDeclaration()},
147 {"computed", isComputed_},
148 {"value", value_},
149 {"overloads", overloads_},
150 {"decorators", decorators_}});
151 }
152
DumpPrefix(ir::SrcDumper *dumper) const153 void MethodDefinition::DumpPrefix(ir::SrcDumper *dumper) const
154 {
155 if (Parent() != nullptr && Parent()->IsClassDefinition() && !Parent()->AsClassDefinition()->IsLocal()) {
156 if (IsPrivate()) {
157 dumper->Add("private ");
158 } else if (IsProtected()) {
159 dumper->Add("protected ");
160 } else if (IsInternal()) {
161 dumper->Add("internal ");
162 } else {
163 dumper->Add("public ");
164 }
165 }
166
167 if (IsStatic()) {
168 dumper->Add("static ");
169 }
170
171 if (IsAbstract()) {
172 dumper->Add("abstract ");
173 }
174
175 if (IsFinal()) {
176 dumper->Add("final ");
177 }
178
179 if (IsNative()) {
180 dumper->Add("native ");
181 }
182
183 if (IsAsync()) {
184 dumper->Add("async ");
185 }
186
187 if (IsOverride()) {
188 dumper->Add("override ");
189 }
190
191 if (kind_ == MethodDefinitionKind::GET) {
192 dumper->Add("get ");
193 } else if (kind_ == MethodDefinitionKind::SET) {
194 dumper->Add("set ");
195 }
196 }
197
Dump(ir::SrcDumper *dumper) const198 void MethodDefinition::Dump(ir::SrcDumper *dumper) const
199 {
200 for (auto method : overloads_) {
201 method->Dump(dumper);
202 dumper->Endl();
203 }
204
205 // Do not dump default constructor
206 if (Parent() != nullptr && Parent()->IsClassDefinition() && value_->IsFunctionExpression() &&
207 value_->AsFunctionExpression()->Function() != nullptr &&
208 value_->AsFunctionExpression()->Function()->IsImplicitSuperCallNeeded()) {
209 return;
210 }
211
212 DumpPrefix(dumper);
213
214 if (key_ != nullptr) {
215 key_->Dump(dumper);
216 }
217
218 if (value_ != nullptr) {
219 value_->Dump(dumper);
220 }
221 }
222
Compile(compiler::PandaGen *pg) const223 void MethodDefinition::Compile(compiler::PandaGen *pg) const
224 {
225 pg->GetAstCompiler()->Compile(this);
226 }
227
Compile(compiler::ETSGen *etsg) const228 void MethodDefinition::Compile(compiler::ETSGen *etsg) const
229 {
230 etsg->GetAstCompiler()->Compile(this);
231 }
232
Check(checker::TSChecker *checker)233 checker::Type *MethodDefinition::Check(checker::TSChecker *checker)
234 {
235 return checker->GetAnalyzer()->Check(this);
236 }
237
Check(checker::ETSChecker *checker)238 checker::Type *MethodDefinition::Check(checker::ETSChecker *checker)
239 {
240 return checker->GetAnalyzer()->Check(this);
241 }
242
Clone(ArenaAllocator *const allocator, AstNode *const parent)243 MethodDefinition *MethodDefinition::Clone(ArenaAllocator *const allocator, AstNode *const parent)
244 {
245 auto *const key = key_ != nullptr ? key_->Clone(allocator, nullptr)->AsExpression() : nullptr;
246 auto *const value = value_ != nullptr ? value_->Clone(allocator, nullptr)->AsExpression() : nullptr;
247
248 if (auto *const clone = allocator->New<MethodDefinition>(kind_, key, value, flags_, allocator, isComputed_);
249 clone != nullptr) {
250 if (parent != nullptr) {
251 clone->SetParent(parent);
252 }
253
254 if (key != nullptr) {
255 key->SetParent(clone);
256 }
257
258 if (value != nullptr) {
259 value->SetParent(clone);
260 }
261
262 for (auto *const decorator : decorators_) {
263 clone->AddDecorator(decorator->Clone(allocator, clone));
264 }
265
266 for (auto *const overloads : overloads_) {
267 clone->AddOverload(overloads->Clone(allocator, clone));
268 }
269
270 return clone;
271 }
272
273 throw Error(ErrorType::GENERIC, "", CLONE_ALLOCATION_ERROR);
274 }
275 } // namespace ark::es2panda::ir
276