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
Dump(ir::SrcDumper * dumper) const153 void MethodDefinition::Dump(ir::SrcDumper *dumper) const
154 {
155 for (auto method : overloads_) {
156 method->Dump(dumper);
157 dumper->Endl();
158 }
159
160 if (IsPrivate()) {
161 dumper->Add("private ");
162 } else if (IsProtected()) {
163 dumper->Add("protected ");
164 } else if (IsInternal()) {
165 dumper->Add("internal ");
166 } else {
167 dumper->Add("public ");
168 }
169
170 if (IsStatic()) {
171 dumper->Add("static ");
172 }
173
174 if (IsAbstract()) {
175 dumper->Add("abstract ");
176 }
177
178 if (IsFinal()) {
179 dumper->Add("final ");
180 }
181
182 if (IsNative()) {
183 dumper->Add("native ");
184 }
185
186 if (IsAsync()) {
187 dumper->Add("async ");
188 }
189
190 if (IsOverride()) {
191 dumper->Add("override ");
192 }
193
194 if (key_ != nullptr) {
195 key_->Dump(dumper);
196 }
197
198 if (value_ != nullptr) {
199 value_->Dump(dumper);
200 }
201 }
202
Compile(compiler::PandaGen * pg) const203 void MethodDefinition::Compile(compiler::PandaGen *pg) const
204 {
205 pg->GetAstCompiler()->Compile(this);
206 }
207
Compile(compiler::ETSGen * etsg) const208 void MethodDefinition::Compile(compiler::ETSGen *etsg) const
209 {
210 etsg->GetAstCompiler()->Compile(this);
211 }
212
Check(checker::TSChecker * checker)213 checker::Type *MethodDefinition::Check(checker::TSChecker *checker)
214 {
215 return checker->GetAnalyzer()->Check(this);
216 }
217
Check(checker::ETSChecker * checker)218 checker::Type *MethodDefinition::Check(checker::ETSChecker *checker)
219 {
220 return checker->GetAnalyzer()->Check(this);
221 }
222
Clone(ArenaAllocator * const allocator,AstNode * const parent)223 MethodDefinition *MethodDefinition::Clone(ArenaAllocator *const allocator, AstNode *const parent)
224 {
225 auto *const key = key_ != nullptr ? key_->Clone(allocator, nullptr)->AsExpression() : nullptr;
226 auto *const value = value_ != nullptr ? value_->Clone(allocator, nullptr)->AsExpression() : nullptr;
227
228 if (auto *const clone = allocator->New<MethodDefinition>(kind_, key, value, flags_, allocator, isComputed_);
229 clone != nullptr) {
230 if (parent != nullptr) {
231 clone->SetParent(parent);
232 }
233
234 if (key != nullptr) {
235 key->SetParent(clone);
236 }
237
238 if (value != nullptr) {
239 value->SetParent(clone);
240 }
241
242 for (auto *const decorator : decorators_) {
243 clone->AddDecorator(decorator->Clone(allocator, clone));
244 }
245
246 for (auto *const overloads : overloads_) {
247 clone->AddOverload(overloads->Clone(allocator, clone));
248 }
249
250 return clone;
251 }
252
253 throw Error(ErrorType::GENERIC, "", CLONE_ALLOCATION_ERROR);
254 }
255 } // namespace ark::es2panda::ir
256