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 "classProperty.h"
17
18#include "checker/ETSchecker.h"
19#include "checker/TSchecker.h"
20#include "compiler/core/ETSGen.h"
21#include "compiler/core/pandagen.h"
22#include "ir/astDump.h"
23#include "ir/srcDump.h"
24
25namespace ark::es2panda::ir {
26void 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 : decorators_) {
48        if (auto *transformedNode = cb(it); it != transformedNode) {
49            it->SetTransformedNode(transformationName, transformedNode);
50            it = transformedNode->AsDecorator();
51        }
52    }
53}
54
55void ClassProperty::Iterate(const NodeTraverser &cb) const
56{
57    cb(key_);
58
59    if (value_ != nullptr) {
60        cb(value_);
61    }
62
63    if (typeAnnotation_ != nullptr) {
64        cb(typeAnnotation_);
65    }
66
67    for (auto *it : decorators_) {
68        cb(it);
69    }
70}
71
72void ClassProperty::Dump(ir::AstDumper *dumper) const
73{
74    dumper->Add({{"type", "ClassProperty"},
75                 {"key", key_},
76                 {"value", AstDumper::Optional(value_)},
77                 {"accessibility", AstDumper::Optional(AstDumper::ModifierToString(flags_))},
78                 {"abstract", AstDumper::Optional(IsAbstract())},
79                 {"static", IsStatic()},
80                 {"readonly", IsReadonly()},
81                 {"declare", IsDeclare()},
82                 {"optional", IsOptionalDeclaration()},
83                 {"computed", isComputed_},
84                 {"typeAnnotation", AstDumper::Optional(typeAnnotation_)},
85                 {"definite", IsDefinite()},
86                 {"decorators", decorators_}});
87}
88
89void ClassProperty::Dump(ir::SrcDumper *dumper) const
90{
91    if (Parent() != nullptr && Parent()->IsClassDefinition() && !Parent()->AsClassDefinition()->IsLocal()) {
92        if (IsPrivate()) {
93            dumper->Add("private ");
94        } else if (IsProtected()) {
95            dumper->Add("protected ");
96        } else if (IsInternal()) {
97            dumper->Add("internal ");
98        } else {
99            dumper->Add("public ");
100        }
101    }
102
103    if (IsStatic()) {
104        dumper->Add("static ");
105    }
106
107    if (IsReadonly()) {
108        dumper->Add("readonly ");
109    }
110
111    if (key_ != nullptr) {
112        key_->Dump(dumper);
113    }
114
115    if (IsOptionalDeclaration()) {
116        dumper->Add("?");
117    }
118
119    if (typeAnnotation_ != nullptr) {
120        dumper->Add(": ");
121        typeAnnotation_->Dump(dumper);
122    }
123
124    if (value_ != nullptr) {
125        dumper->Add(" = ");
126        value_->Dump(dumper);
127    }
128
129    dumper->Add(";");
130    dumper->Endl();
131}
132
133void ClassProperty::Compile(compiler::PandaGen *pg) const
134{
135    pg->GetAstCompiler()->Compile(this);
136}
137
138void ClassProperty::Compile(compiler::ETSGen *etsg) const
139{
140    etsg->GetAstCompiler()->Compile(this);
141}
142
143checker::Type *ClassProperty::Check(checker::TSChecker *checker)
144{
145    return checker->GetAnalyzer()->Check(this);
146}
147
148checker::Type *ClassProperty::Check(checker::ETSChecker *checker)
149{
150    return checker->GetAnalyzer()->Check(this);
151}
152
153ClassProperty *ClassProperty::Clone(ArenaAllocator *const allocator, AstNode *const parent)
154{
155    auto *const key = key_->Clone(allocator, nullptr)->AsExpression();
156    auto *const value = value_ != nullptr ? value_->Clone(allocator, nullptr)->AsExpression() : nullptr;
157    auto *const typeAnnotation = typeAnnotation_ != nullptr ? typeAnnotation_->Clone(allocator, nullptr) : nullptr;
158
159    if (auto *const clone = allocator->New<ClassProperty>(key, value, typeAnnotation, flags_, allocator, isComputed_);
160        clone != nullptr) {
161        if (parent != nullptr) {
162            clone->SetParent(parent);
163        }
164
165        key->SetParent(clone);
166        if (value != nullptr) {
167            value->SetParent(clone);
168        }
169        if (typeAnnotation != nullptr) {
170            typeAnnotation->SetParent(clone);
171        }
172
173        for (auto *const decorator : decorators_) {
174            clone->AddDecorator(decorator->Clone(allocator, clone));
175        }
176
177        return clone;
178    }
179
180    throw Error(ErrorType::GENERIC, "", CLONE_ALLOCATION_ERROR);
181}
182}  // namespace ark::es2panda::ir
183