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 "identifier.h"
17 
18 #include "checker/ETSchecker.h"
19 #include "checker/TSchecker.h"
20 #include "compiler/core/pandagen.h"
21 #include "compiler/core/ETSGen.h"
22 #include "ir/astDump.h"
23 #include "ir/srcDump.h"
24 
25 namespace ark::es2panda::ir {
Identifier([[maybe_unused]] Tag const tag, Identifier const &other, ArenaAllocator *const allocator)26 Identifier::Identifier([[maybe_unused]] Tag const tag, Identifier const &other, ArenaAllocator *const allocator)
27     : AnnotatedExpression(static_cast<AnnotatedExpression const &>(other), allocator), decorators_(allocator->Adapter())
28 {
29     name_ = other.name_;
30     flags_ = other.flags_;
31 
32     for (auto *decorator : other.decorators_) {
33         decorators_.emplace_back(decorator->Clone(allocator, this));
34     }
35 }
36 
Clone(ArenaAllocator *const allocator, AstNode *const parent)37 Identifier *Identifier::Clone(ArenaAllocator *const allocator, AstNode *const parent)
38 {
39     if (auto *const clone = allocator->New<Identifier>(Tag {}, *this, allocator); clone != nullptr) {
40         clone->SetTsType(TsType());
41         if (parent != nullptr) {
42             clone->SetParent(parent);
43         }
44 
45         if (this->IsReference()) {
46             clone->SetReference();
47         }
48 
49         clone->SetRange(Range());
50 
51         return clone;
52     }
53     throw Error(ErrorType::GENERIC, "", CLONE_ALLOCATION_ERROR);
54 }
55 
TransformChildren(const NodeTransformer &cb, std::string_view const transformationName)56 void Identifier::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName)
57 {
58     if (auto *typeAnnotation = TypeAnnotation(); typeAnnotation != nullptr) {
59         if (auto *transformedNode = cb(typeAnnotation); typeAnnotation != transformedNode) {
60             typeAnnotation->SetTransformedNode(transformationName, transformedNode);
61             SetTsTypeAnnotation(static_cast<TypeNode *>(transformedNode));
62         }
63     }
64 
65     for (auto *&it : decorators_) {
66         if (auto *transformedNode = cb(it); it != transformedNode) {
67             it->SetTransformedNode(transformationName, transformedNode);
68             it = transformedNode->AsDecorator();
69         }
70     }
71 }
72 
Iterate(const NodeTraverser &cb) const73 void Identifier::Iterate(const NodeTraverser &cb) const
74 {
75     if (TypeAnnotation() != nullptr) {
76         cb(TypeAnnotation());
77     }
78 
79     for (auto *it : decorators_) {
80         cb(it);
81     }
82 }
83 
ValidateExpression()84 ValidationInfo Identifier::ValidateExpression()
85 {
86     if ((flags_ & IdentifierFlags::OPTIONAL) != 0U) {
87         return {"Unexpected token '?'.", Start()};
88     }
89 
90     if (TypeAnnotation() != nullptr) {
91         return {"Unexpected token.", TypeAnnotation()->Start()};
92     }
93 
94     ValidationInfo info;
95     return info;
96 }
97 
Dump(ir::AstDumper *dumper) const98 void Identifier::Dump(ir::AstDumper *dumper) const
99 {
100     dumper->Add({{"type", IsPrivateIdent() ? "PrivateIdentifier" : "Identifier"},
101                  {"name", name_},
102                  {"typeAnnotation", AstDumper::Optional(TypeAnnotation())},
103                  {"optional", AstDumper::Optional(IsOptional())},
104                  {"decorators", decorators_}});
105 }
106 
Dump(ir::SrcDumper *dumper) const107 void Identifier::Dump(ir::SrcDumper *dumper) const
108 {
109     if (IsPrivateIdent()) {
110         dumper->Add("private ");
111     }
112     dumper->Add(std::string(name_));
113     if (IsOptional()) {
114         dumper->Add("?");
115     }
116 }
117 
Compile(compiler::PandaGen *pg) const118 void Identifier::Compile(compiler::PandaGen *pg) const
119 {
120     pg->GetAstCompiler()->Compile(this);
121 }
122 
Compile(compiler::ETSGen *etsg) const123 void Identifier::Compile(compiler::ETSGen *etsg) const
124 {
125     etsg->GetAstCompiler()->Compile(this);
126 }
127 
Check(checker::TSChecker *checker)128 checker::Type *Identifier::Check(checker::TSChecker *checker)
129 {
130     return checker->GetAnalyzer()->Check(this);
131 }
132 
Check(checker::ETSChecker *checker)133 checker::Type *Identifier::Check(checker::ETSChecker *checker)
134 {
135     return checker->GetAnalyzer()->Check(this);
136 }
137 }  // namespace ark::es2panda::ir
138