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 "spreadElement.h"
17
18 #include "checker/TSchecker.h"
19 #include "compiler/core/pandagen.h"
20 #include "compiler/core/ETSGen.h"
21
22 namespace ark::es2panda::ir {
SpreadElement(Tag const tag,SpreadElement const & other,ArenaAllocator * const allocator)23 SpreadElement::SpreadElement([[maybe_unused]] Tag const tag, SpreadElement const &other,
24 ArenaAllocator *const allocator)
25 : AnnotatedExpression(static_cast<AnnotatedExpression const &>(other), allocator), decorators_(allocator->Adapter())
26 {
27 optional_ = other.optional_;
28
29 argument_ = other.argument_->Clone(allocator, this)->AsExpression();
30
31 for (auto *decorator : other.decorators_) {
32 decorators_.emplace_back(decorator->Clone(allocator, this));
33 }
34 }
35
Clone(ArenaAllocator * const allocator,AstNode * const parent)36 SpreadElement *SpreadElement::Clone(ArenaAllocator *const allocator, AstNode *const parent)
37 {
38 auto *const clone = allocator->New<SpreadElement>(Tag {}, *this, allocator);
39 ES2PANDA_ASSERT(clone != nullptr);
40 if (parent != nullptr) {
41 clone->SetParent(parent);
42 }
43 return clone;
44 }
45
ValidateExpression()46 ValidationInfo SpreadElement::ValidateExpression()
47 {
48 ValidationInfo info;
49
50 switch (argument_->Type()) {
51 case AstNodeType::OBJECT_EXPRESSION: {
52 info = argument_->AsObjectExpression()->ValidateExpression();
53 break;
54 }
55 case AstNodeType::ARRAY_EXPRESSION: {
56 info = argument_->AsArrayExpression()->ValidateExpression();
57 break;
58 }
59 default: {
60 break;
61 }
62 }
63
64 return info;
65 }
66
ConvertibleToRest(bool isDeclaration,bool allowPattern)67 bool SpreadElement::ConvertibleToRest(bool isDeclaration, bool allowPattern)
68 {
69 bool convResult = true;
70
71 switch (argument_->Type()) {
72 case AstNodeType::ARRAY_EXPRESSION: {
73 convResult = allowPattern && argument_->AsArrayExpression()->ConvertibleToArrayPattern();
74 break;
75 }
76 case AstNodeType::OBJECT_EXPRESSION: {
77 convResult = allowPattern && argument_->AsObjectExpression()->ConvertibleToObjectPattern();
78 break;
79 }
80 case AstNodeType::META_PROPERTY_EXPRESSION:
81 case AstNodeType::CHAIN_EXPRESSION:
82 case AstNodeType::ASSIGNMENT_EXPRESSION: {
83 convResult = false;
84 break;
85 }
86 case AstNodeType::MEMBER_EXPRESSION: {
87 convResult = !isDeclaration;
88 break;
89 }
90 default: {
91 break;
92 }
93 }
94
95 SetType(AstNodeType::REST_ELEMENT);
96 return convResult;
97 }
98
TransformChildren(const NodeTransformer & cb,std::string_view const transformationName)99 void SpreadElement::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName)
100 {
101 for (auto *&it : VectorIterationGuard(decorators_)) {
102 if (auto *transformedNode = cb(it); it != transformedNode) {
103 it->SetTransformedNode(transformationName, transformedNode);
104 it = transformedNode->AsDecorator();
105 }
106 }
107
108 if (auto *transformedNode = cb(argument_); argument_ != transformedNode) {
109 argument_->SetTransformedNode(transformationName, transformedNode);
110 argument_ = transformedNode->AsExpression();
111 }
112
113 if (auto *const typeAnnotation = TypeAnnotation(); typeAnnotation != nullptr) {
114 if (auto *transformedNode = cb(typeAnnotation); typeAnnotation != transformedNode) {
115 typeAnnotation->SetTransformedNode(transformationName, transformedNode);
116 SetTsTypeAnnotation(static_cast<TypeNode *>(transformedNode));
117 }
118 }
119 }
120
Iterate(const NodeTraverser & cb) const121 void SpreadElement::Iterate(const NodeTraverser &cb) const
122 {
123 for (auto *it : VectorIterationGuard(decorators_)) {
124 cb(it);
125 }
126
127 cb(argument_);
128
129 if (TypeAnnotation() != nullptr) {
130 cb(TypeAnnotation());
131 }
132 }
133
Dump(ir::AstDumper * dumper) const134 void SpreadElement::Dump(ir::AstDumper *dumper) const
135 {
136 dumper->Add({{"type", (type_ == AstNodeType::SPREAD_ELEMENT) ? "SpreadElement" : "RestElement"},
137 {"decorators", AstDumper::Optional(decorators_)},
138 {"argument", argument_},
139 {"typeAnnotation", AstDumper::Optional(TypeAnnotation())}});
140 }
141
Dump(ir::SrcDumper * dumper) const142 void SpreadElement::Dump(ir::SrcDumper *dumper) const
143 {
144 dumper->Add("...");
145 argument_->Dump(dumper);
146 auto type = TypeAnnotation();
147 if (type != nullptr) {
148 dumper->Add(": ");
149 type->Dump(dumper);
150 }
151 }
152
Compile(compiler::PandaGen * pg) const153 void SpreadElement::Compile([[maybe_unused]] compiler::PandaGen *pg) const
154 {
155 pg->GetAstCompiler()->Compile(this);
156 }
Compile(compiler::ETSGen * etsg) const157 void SpreadElement::Compile([[maybe_unused]] compiler::ETSGen *etsg) const
158 {
159 etsg->GetAstCompiler()->Compile(this);
160 }
161
Check(checker::TSChecker * checker)162 checker::Type *SpreadElement::Check([[maybe_unused]] checker::TSChecker *checker)
163 {
164 return checker->GetAnalyzer()->Check(this);
165 }
166
Check(checker::ETSChecker * checker)167 checker::VerifiedType SpreadElement::Check([[maybe_unused]] checker::ETSChecker *checker)
168 {
169 return {this, checker->GetAnalyzer()->Check(this)};
170 }
171
ToString() const172 std::string SpreadElement::ToString() const
173 {
174 auto str = Argument()->ToString();
175 if (str == INVALID_EXPRESSION) {
176 return str;
177 }
178
179 return "..." + str;
180 }
181 } // namespace ark::es2panda::ir
182