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 "variableDeclaration.h"
17
18 #include "checker/TSchecker.h"
19 #include "checker/ETSchecker.h"
20 #include "compiler/core/ETSGen.h"
21 #include "compiler/core/pandagen.h"
22 #include "utils/arena_containers.h"
23
24 namespace ark::es2panda::ir {
TransformChildren(const NodeTransformer & cb,std::string_view transformationName)25 void VariableDeclaration::TransformChildren(const NodeTransformer &cb, std::string_view transformationName)
26 {
27 for (auto *&it : VectorIterationGuard(decorators_)) {
28 if (auto *transformedNode = cb(it); it != transformedNode) {
29 it->SetTransformedNode(transformationName, transformedNode);
30 it = transformedNode->AsDecorator();
31 }
32 }
33
34 for (auto *&it : VectorIterationGuard(Annotations())) {
35 if (auto *transformedNode = cb(it); it != transformedNode) {
36 it->SetTransformedNode(transformationName, transformedNode);
37 it = transformedNode->AsAnnotationUsage();
38 }
39 }
40
41 for (auto *&it : VectorIterationGuard(declarators_)) {
42 if (auto *transformedNode = cb(it); it != transformedNode) {
43 it->SetTransformedNode(transformationName, transformedNode);
44 it = transformedNode->AsVariableDeclarator();
45 }
46 }
47 }
48
Iterate(const NodeTraverser & cb) const49 void VariableDeclaration::Iterate(const NodeTraverser &cb) const
50 {
51 for (auto *it : VectorIterationGuard(decorators_)) {
52 cb(it);
53 }
54
55 for (auto *it : VectorIterationGuard(Annotations())) {
56 cb(it);
57 }
58
59 for (auto *it : VectorIterationGuard(declarators_)) {
60 cb(it);
61 }
62 }
63
Dump(ir::AstDumper * dumper) const64 void VariableDeclaration::Dump(ir::AstDumper *dumper) const
65 {
66 const char *kind = nullptr;
67
68 switch (kind_) {
69 case VariableDeclarationKind::CONST: {
70 kind = "const";
71 break;
72 }
73 case VariableDeclarationKind::LET: {
74 kind = "let";
75 break;
76 }
77 case VariableDeclarationKind::VAR: {
78 kind = "var";
79 break;
80 }
81 default: {
82 ES2PANDA_UNREACHABLE();
83 }
84 }
85
86 dumper->Add({{"type", "VariableDeclaration"},
87 {"declarations", declarators_},
88 {"kind", kind},
89 {"decorators", AstDumper::Optional(decorators_)},
90 {"annotations", AstDumper::Optional(Annotations())},
91 {"declare", AstDumper::Optional(IsDeclare())}});
92 }
93
Dump(ir::SrcDumper * dumper) const94 void VariableDeclaration::Dump(ir::SrcDumper *dumper) const
95 {
96 for (auto *anno : Annotations()) {
97 anno->Dump(dumper);
98 }
99
100 if (IsDeclare()) {
101 dumper->Add("declare ");
102 }
103
104 switch (kind_) {
105 case VariableDeclarationKind::CONST:
106 dumper->Add("const ");
107 break;
108 case VariableDeclarationKind::LET:
109 dumper->Add("let ");
110 break;
111 case VariableDeclarationKind::VAR:
112 dumper->Add("var ");
113 break;
114 default:
115 ES2PANDA_UNREACHABLE();
116 }
117
118 for (auto declarator : declarators_) {
119 declarator->Dump(dumper);
120 if (declarator != declarators_.back()) {
121 dumper->Add(", ");
122 }
123 }
124
125 if ((parent_ != nullptr) &&
126 (parent_->IsBlockStatement() || parent_->IsBlockExpression() || parent_->IsSwitchCaseStatement())) {
127 dumper->Add(";");
128 }
129 }
130
VariableDeclaration(Tag const tag,VariableDeclaration const & other,ArenaAllocator * const allocator)131 VariableDeclaration::VariableDeclaration([[maybe_unused]] Tag const tag, VariableDeclaration const &other,
132 ArenaAllocator *const allocator)
133 : JsDocAllowed<AnnotationAllowed<Statement>>(static_cast<JsDocAllowed<AnnotationAllowed<Statement>> const &>(other),
134 allocator),
135 kind_(other.kind_),
136 decorators_(allocator->Adapter()),
137 declarators_(allocator->Adapter())
138 {
139 for (auto const &d : other.decorators_) {
140 decorators_.emplace_back(d->Clone(allocator, nullptr));
141 decorators_.back()->SetParent(this);
142 }
143
144 for (auto const &d : other.declarators_) {
145 auto *dClone = d->Clone(allocator, nullptr);
146 ES2PANDA_ASSERT(dClone != nullptr);
147 declarators_.emplace_back(dClone->AsVariableDeclarator());
148 declarators_.back()->SetParent(this);
149 }
150 }
151
Clone(ArenaAllocator * const allocator,AstNode * const parent)152 VariableDeclaration *VariableDeclaration::Clone(ArenaAllocator *const allocator, AstNode *const parent)
153 {
154 auto *const clone = allocator->New<VariableDeclaration>(Tag {}, *this, allocator);
155 ES2PANDA_ASSERT(clone != nullptr);
156 if (parent != nullptr) {
157 clone->SetParent(parent);
158 }
159 clone->SetRange(range_);
160 return clone;
161 }
162
Compile(compiler::PandaGen * pg) const163 void VariableDeclaration::Compile(compiler::PandaGen *pg) const
164 {
165 pg->GetAstCompiler()->Compile(this);
166 }
167
Compile(compiler::ETSGen * etsg) const168 void VariableDeclaration::Compile(compiler::ETSGen *etsg) const
169 {
170 etsg->GetAstCompiler()->Compile(this);
171 }
172
Check(checker::TSChecker * checker)173 checker::Type *VariableDeclaration::Check(checker::TSChecker *checker)
174 {
175 return checker->GetAnalyzer()->Check(this);
176 }
177
Check(checker::ETSChecker * checker)178 checker::VerifiedType VariableDeclaration::Check([[maybe_unused]] checker::ETSChecker *checker)
179 {
180 return {this, checker->GetAnalyzer()->Check(this)};
181 }
182
Construct(ArenaAllocator * allocator)183 VariableDeclaration *VariableDeclaration::Construct(ArenaAllocator *allocator)
184 {
185 ArenaVector<VariableDeclarator *> declarators(allocator->Adapter());
186 return allocator->New<VariableDeclaration>(VariableDeclarationKind::LET, allocator, std::move(declarators));
187 }
188
CopyTo(AstNode * other) const189 void VariableDeclaration::CopyTo(AstNode *other) const
190 {
191 auto otherImpl = other->AsVariableDeclaration();
192
193 otherImpl->kind_ = kind_;
194 otherImpl->decorators_ = decorators_;
195 otherImpl->declarators_ = declarators_;
196
197 JsDocAllowed<AnnotationAllowed<Statement>>::CopyTo(other);
198 }
199
200 } // namespace ark::es2panda::ir
201