• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2025 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 "classProperty.h"
17 #include <string>
18 
19 #include "checker/ETSchecker.h"
20 #include "checker/TSchecker.h"
21 #include "compiler/core/ETSGen.h"
22 #include "compiler/core/pandagen.h"
23 #include "compiler/lowering/util.h"
24 
25 namespace ark::es2panda::ir {
TransformChildren(const NodeTransformer & cb,std::string_view const transformationName)26 void ClassProperty::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName)
27 {
28     if (auto *transformedNode = cb(key_); key_ != transformedNode) {
29         key_->SetTransformedNode(transformationName, transformedNode);
30         key_ = transformedNode->AsExpression();
31     }
32 
33     if (value_ != nullptr) {
34         if (auto *transformedNode = cb(value_); value_ != transformedNode) {
35             value_->SetTransformedNode(transformationName, transformedNode);
36             value_ = transformedNode->AsExpression();
37         }
38     }
39 
40     if (typeAnnotation_ != nullptr) {
41         if (auto *transformedNode = cb(typeAnnotation_); typeAnnotation_ != transformedNode) {
42             typeAnnotation_->SetTransformedNode(transformationName, transformedNode);
43             typeAnnotation_ = static_cast<TypeNode *>(transformedNode);
44         }
45     }
46 
47     for (auto *&it : VectorIterationGuard(decorators_)) {
48         if (auto *transformedNode = cb(it); it != transformedNode) {
49             it->SetTransformedNode(transformationName, transformedNode);
50             it = transformedNode->AsDecorator();
51         }
52     }
53 
54     for (auto *&it : Annotations()) {
55         if (auto *transformedNode = cb(it); it != transformedNode) {
56             it->SetTransformedNode(transformationName, transformedNode);
57             it = transformedNode->AsAnnotationUsage();
58         }
59     }
60 }
61 
Iterate(const NodeTraverser & cb) const62 void ClassProperty::Iterate(const NodeTraverser &cb) const
63 {
64     cb(key_);
65 
66     if (value_ != nullptr) {
67         cb(value_);
68     }
69 
70     if (typeAnnotation_ != nullptr) {
71         cb(typeAnnotation_);
72     }
73 
74     for (auto *it : VectorIterationGuard(decorators_)) {
75         cb(it);
76     }
77 
78     for (auto *it : Annotations()) {
79         cb(it);
80     }
81 }
82 
Dump(ir::AstDumper * dumper) const83 void ClassProperty::Dump(ir::AstDumper *dumper) const
84 {
85     dumper->Add({{"type", "ClassProperty"},
86                  {"key", key_},
87                  {"value", AstDumper::Optional(value_)},
88                  {"accessibility", AstDumper::Optional(AstDumper::ModifierToString(flags_))},
89                  {"static", IsStatic()},
90                  {"readonly", IsReadonly()},
91                  {"declare", IsDeclare()},
92                  {"optional", IsOptionalDeclaration()},
93                  {"computed", isComputed_},
94                  {"typeAnnotation", AstDumper::Optional(typeAnnotation_)},
95                  {"definite", IsDefinite()},
96                  {"decorators", decorators_},
97                  {"annotations", AstDumper::Optional(Annotations())}});
98 }
99 
DumpModifiers(ir::SrcDumper * dumper) const100 void ClassProperty::DumpModifiers(ir::SrcDumper *dumper) const
101 {
102     ES2PANDA_ASSERT(key_);
103     if (dumper->IsDeclgen()) {
104         if (key_->Parent()->IsExported()) {
105             dumper->Add("export declare ");
106         } else if (key_->Parent()->IsDefaultExported()) {
107             dumper->Add("export default declare ");
108         }
109     }
110 
111     if (compiler::HasGlobalClassParent(this)) {
112         if (key_->Parent()->IsConst()) {
113             dumper->Add("const ");
114         } else {
115             dumper->Add("let ");
116         }
117         return;
118     }
119 
120     if (compiler::HasGlobalClassParent(this)) {
121         dumper->Add("let ");
122         return;
123     }
124 
125     if (Parent() != nullptr && Parent()->IsClassDefinition() && !Parent()->AsClassDefinition()->IsLocal()) {
126         if (IsPrivate()) {
127             dumper->Add("private ");
128         } else if (IsProtected()) {
129             dumper->Add("protected ");
130         } else if (IsInternal()) {
131             dumper->Add("internal ");
132         } else {
133             dumper->Add("public ");
134         }
135     }
136 
137     if (IsStatic()) {
138         dumper->Add("static ");
139     }
140 
141     if (IsReadonly()) {
142         dumper->Add("readonly ");
143     }
144 }
145 
DumpNamespaceForDeclGen(ir::SrcDumper * dumper) const146 bool ClassProperty::DumpNamespaceForDeclGen(ir::SrcDumper *dumper) const
147 {
148     if (!dumper->IsDeclgen()) {
149         return false;
150     }
151 
152     if (Parent() == nullptr) {
153         return false;
154     }
155 
156     bool isNamespaceTransformed =
157         Parent()->IsClassDefinition() && Parent()->AsClassDefinition()->IsNamespaceTransformed();
158     if (isNamespaceTransformed) {
159         dumper->Add("let ");
160         return true;
161     }
162     return false;
163 }
164 
DumpPrefix(ir::SrcDumper * dumper) const165 void ClassProperty::DumpPrefix(ir::SrcDumper *dumper) const
166 {
167     for (auto *anno : Annotations()) {
168         anno->Dump(dumper);
169     }
170     if (DumpNamespaceForDeclGen(dumper)) {
171         return;
172     }
173     DumpModifiers(dumper);
174 }
175 
DumpCheckerTypeForDeclGen(ir::SrcDumper * dumper) const176 void ClassProperty::DumpCheckerTypeForDeclGen(ir::SrcDumper *dumper) const
177 {
178     if (!dumper->IsDeclgen()) {
179         return;
180     }
181 
182     if (TsType() == nullptr) {
183         return;
184     }
185 
186     auto typeStr = TsType()->ToString();
187     if (TsType()->IsTypeError() && dumper->IsIsolatedDeclgen() && typeAnnotation_ != nullptr) {
188         typeStr = typeAnnotation_->AsETSTypeReference()->Part()->Name()->AsIdentifier()->Name().Mutf8();
189     }
190 
191     dumper->Add(": ");
192     dumper->Add(typeStr);
193 
194     dumper->PushTask([dumper, typeStr] { dumper->DumpNode(typeStr); });
195 }
196 
RegisterUnexportedForDeclGen(ir::SrcDumper * dumper) const197 bool ClassProperty::RegisterUnexportedForDeclGen(ir::SrcDumper *dumper) const
198 {
199     ES2PANDA_ASSERT(key_);
200     if (!dumper->IsDeclgen()) {
201         return false;
202     }
203 
204     auto name = key_->AsIdentifier()->Name().Mutf8();
205     if (name.rfind('#', 0) == 0) {
206         return true;
207     }
208 
209     if (!compiler::HasGlobalClassParent(this)) {
210         return false;
211     }
212 
213     if (dumper->IsIndirectDepPhase()) {
214         return false;
215     }
216 
217     if (key_->Parent()->IsExported() || key_->Parent()->IsDefaultExported()) {
218         return false;
219     }
220 
221     dumper->AddNode(name, this);
222     return true;
223 }
224 
Dump(ir::SrcDumper * dumper) const225 void ClassProperty::Dump(ir::SrcDumper *dumper) const
226 {
227     if (RegisterUnexportedForDeclGen(dumper)) {
228         return;
229     }
230     DumpPrefix(dumper);
231 
232     if (key_ != nullptr) {
233         key_->Dump(dumper);
234     }
235 
236     if (IsOptionalDeclaration()) {
237         dumper->Add("?");
238     }
239 
240     if (IsDefinite()) {
241         dumper->Add("!");
242     }
243 
244     if (typeAnnotation_ != nullptr && !dumper->IsDeclgen()) {
245         dumper->Add(": ");
246         typeAnnotation_->Dump(dumper);
247     }
248 
249     DumpCheckerTypeForDeclGen(dumper);
250 
251     if (value_ != nullptr && !dumper->IsDeclgen()) {
252         dumper->Add(" = ");
253         value_->Dump(dumper);
254     }
255 
256     dumper->Add(";");
257     dumper->Endl();
258 }
259 
Compile(compiler::PandaGen * pg) const260 void ClassProperty::Compile(compiler::PandaGen *pg) const
261 {
262     pg->GetAstCompiler()->Compile(this);
263 }
264 
Compile(compiler::ETSGen * etsg) const265 void ClassProperty::Compile(compiler::ETSGen *etsg) const
266 {
267     etsg->GetAstCompiler()->Compile(this);
268 }
269 
Check(checker::TSChecker * checker)270 checker::Type *ClassProperty::Check(checker::TSChecker *checker)
271 {
272     return checker->GetAnalyzer()->Check(this);
273 }
274 
Check(checker::ETSChecker * checker)275 checker::VerifiedType ClassProperty::Check(checker::ETSChecker *checker)
276 {
277     return {this, checker->GetAnalyzer()->Check(this)};
278 }
279 
Clone(ArenaAllocator * const allocator,AstNode * const parent)280 ClassProperty *ClassProperty::Clone(ArenaAllocator *const allocator, AstNode *const parent)
281 {
282     auto *const key = key_->Clone(allocator, nullptr)->AsExpression();
283     auto *const value = value_ != nullptr ? value_->Clone(allocator, nullptr)->AsExpression() : nullptr;
284     auto *const typeAnnotation = typeAnnotation_ != nullptr ? typeAnnotation_->Clone(allocator, nullptr) : nullptr;
285 
286     auto *const clone = allocator->New<ClassProperty>(key, value, typeAnnotation, flags_, allocator, isComputed_);
287 
288     if (parent != nullptr) {
289         clone->SetParent(parent);
290     }
291 
292     key->SetParent(clone);
293     if (value != nullptr) {
294         value->SetTsType(value_->TsType());
295         value->SetParent(clone);
296     }
297     if (typeAnnotation != nullptr) {
298         typeAnnotation->SetTsType(typeAnnotation->TsType());
299         typeAnnotation->SetParent(clone);
300     }
301 
302     for (auto *const decorator : decorators_) {
303         clone->AddDecorator(decorator->Clone(allocator, clone));
304     }
305 
306     if (!Annotations().empty()) {
307         ArenaVector<AnnotationUsage *> annotationUsages {allocator->Adapter()};
308         for (auto *annotationUsage : Annotations()) {
309             annotationUsages.push_back(annotationUsage->Clone(allocator, clone)->AsAnnotationUsage());
310         }
311         clone->SetAnnotations(std::move(annotationUsages));
312     }
313 
314     clone->SetRange(range_);
315 
316     return clone;
317 }
318 
Construct(ArenaAllocator * allocator)319 ClassProperty *ClassProperty::Construct(ArenaAllocator *allocator)
320 {
321     return allocator->New<ClassProperty>(nullptr, nullptr, nullptr, ModifierFlags::NONE, allocator, false);
322 }
323 
CopyTo(AstNode * other) const324 void ClassProperty::CopyTo(AstNode *other) const
325 {
326     auto otherImpl = other->AsClassProperty();
327 
328     otherImpl->typeAnnotation_ = typeAnnotation_;
329     otherImpl->isDefault_ = isDefault_;
330     otherImpl->needInitInStaticBlock_ = needInitInStaticBlock_;
331 
332     JsDocAllowed<AnnotationAllowed<ClassElement>>::CopyTo(other);
333 }
334 
335 }  // namespace ark::es2panda::ir
336