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 "etsTypeReferencePart.h"
17
18 #include "checker/ETSchecker.h"
19 #include "checker/ets/typeRelationContext.h"
20 #include "checker/TSchecker.h"
21 #include "compiler/core/ETSGen.h"
22 #include "compiler/core/pandagen.h"
23 #include "ir/astDump.h"
24 #include "ir/srcDump.h"
25
26 namespace ark::es2panda::ir {
TransformChildren(const NodeTransformer & cb,std::string_view const transformationName)27 void ETSTypeReferencePart::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName)
28 {
29 if (auto *transformedNode = cb(name_); name_ != transformedNode) {
30 name_->SetTransformedNode(transformationName, transformedNode);
31 name_ = transformedNode->AsExpression();
32 }
33
34 if (typeParams_ != nullptr) {
35 if (auto *transformedNode = cb(typeParams_); typeParams_ != transformedNode) {
36 typeParams_->SetTransformedNode(transformationName, transformedNode);
37 typeParams_ = transformedNode->AsTSTypeParameterInstantiation();
38 }
39 }
40
41 if (prev_ != nullptr) {
42 if (auto *transformedNode = cb(prev_); prev_ != transformedNode) {
43 prev_->SetTransformedNode(transformationName, transformedNode);
44 prev_ = transformedNode->AsETSTypeReferencePart();
45 }
46 }
47 }
48
Iterate(const NodeTraverser & cb) const49 void ETSTypeReferencePart::Iterate(const NodeTraverser &cb) const
50 {
51 cb(name_);
52
53 if (typeParams_ != nullptr) {
54 cb(typeParams_);
55 }
56
57 if (prev_ != nullptr) {
58 cb(prev_);
59 }
60 }
61
Dump(ir::AstDumper * dumper) const62 void ETSTypeReferencePart::Dump(ir::AstDumper *dumper) const
63 {
64 dumper->Add({{"type", "ETSTypeReferencePart"},
65 {"name", name_},
66 {"typeParams", AstDumper::Optional(typeParams_)},
67 {"previous", AstDumper::Optional(prev_)}});
68 }
69
Dump(ir::SrcDumper * dumper) const70 void ETSTypeReferencePart::Dump(ir::SrcDumper *dumper) const
71 {
72 ASSERT(name_ != nullptr);
73 name_->Dump(dumper);
74 if (typeParams_ != nullptr) {
75 typeParams_->Dump(dumper);
76 }
77 }
78
Compile(compiler::PandaGen * pg) const79 void ETSTypeReferencePart::Compile(compiler::PandaGen *pg) const
80 {
81 pg->GetAstCompiler()->Compile(this);
82 }
Compile(compiler::ETSGen * etsg) const83 void ETSTypeReferencePart::Compile(compiler::ETSGen *etsg) const
84 {
85 etsg->GetAstCompiler()->Compile(this);
86 }
87
Check(checker::TSChecker * checker)88 checker::Type *ETSTypeReferencePart::Check(checker::TSChecker *checker)
89 {
90 return checker->GetAnalyzer()->Check(this);
91 }
92
Check(checker::ETSChecker * checker)93 checker::Type *ETSTypeReferencePart::Check(checker::ETSChecker *checker)
94 {
95 return checker->GetAnalyzer()->Check(this);
96 }
97
HandleInternalTypes(checker::ETSChecker * const checker,const Identifier * const ident)98 checker::Type *ETSTypeReferencePart::HandleInternalTypes(checker::ETSChecker *const checker,
99 const Identifier *const ident)
100 {
101 if ((ident->Variable() != nullptr) && (ident->Variable()->Declaration()->IsTypeAliasDecl())) {
102 return checker->HandleTypeAlias(name_, typeParams_);
103 }
104
105 if (ident->Name() == compiler::Signatures::UNDEFINED) {
106 return checker->GlobalETSUndefinedType();
107 }
108
109 if (ident->Name() == compiler::Signatures::NULL_LITERAL) {
110 return checker->GlobalETSNullType();
111 }
112
113 if (ident->Name() == compiler::Signatures::NEVER_TYPE_NAME) {
114 return checker->GlobalETSNeverType();
115 }
116
117 if (ident->Name() == compiler::Signatures::READONLY_TYPE_NAME ||
118 ident->Name() == compiler::Signatures::REQUIRED_TYPE_NAME) {
119 return checker->HandleUtilityTypeParameterNode(typeParams_, ident->Name().Utf8());
120 }
121
122 if (ident->Name() == compiler::Signatures::PARTIAL_TYPE_NAME) {
123 auto *baseType = checker->HandleUtilityTypeParameterNode(typeParams_, ident->Name().Utf8());
124 if (baseType->IsETSObjectType() && !baseType->AsETSObjectType()->TypeArguments().empty()) {
125 // we treat Partial<A<T,D>> class as a different copy from A<T,D> now,
126 // but not a generic type param for Partial<>
127 for (auto &typeRef : typeParams_->Params()) {
128 checker::InstantiationContext ctx(checker, baseType->AsETSObjectType(),
129 typeRef->AsETSTypeReference()->Part()->typeParams_, Start());
130 baseType = ctx.Result();
131 }
132 }
133 return baseType;
134 }
135
136 return nullptr;
137 }
138
GetType(checker::ETSChecker * checker)139 checker::Type *ETSTypeReferencePart::GetType(checker::ETSChecker *checker)
140 {
141 if (prev_ == nullptr) {
142 if (name_->IsIdentifier()) {
143 SetTsType(HandleInternalTypes(checker, name_->AsIdentifier()));
144 }
145
146 if (TsType() == nullptr) {
147 checker::Type *baseType = checker->GetReferencedTypeBase(name_);
148
149 ASSERT(baseType != nullptr);
150 if (baseType->IsETSObjectType()) {
151 checker::InstantiationContext ctx(checker, baseType->AsETSObjectType(), typeParams_, Start());
152 SetTsType(ctx.Result());
153 } else {
154 SetTsType(baseType);
155 }
156 }
157 } else {
158 checker::Type *baseType = prev_->GetType(checker);
159 SetTsType(checker->GetReferencedTypeFromBase(baseType, name_));
160 }
161 return TsType();
162 }
163
Clone(ArenaAllocator * const allocator,AstNode * const parent)164 ETSTypeReferencePart *ETSTypeReferencePart::Clone(ArenaAllocator *const allocator, AstNode *const parent)
165 {
166 auto *const nameClone = name_ != nullptr ? name_->Clone(allocator, nullptr)->AsExpression() : nullptr;
167 auto *const typeParamsClone =
168 typeParams_ != nullptr ? typeParams_->Clone(allocator, nullptr)->AsTSTypeParameterInstantiation() : nullptr;
169 auto *const prevClone = prev_ != nullptr ? prev_->Clone(allocator, nullptr)->AsETSTypeReferencePart() : nullptr;
170 if (auto *const clone = allocator->New<ETSTypeReferencePart>(nameClone, typeParamsClone, prevClone);
171 clone != nullptr) {
172 if (nameClone != nullptr) {
173 nameClone->SetParent(clone);
174 }
175
176 if (typeParamsClone != nullptr) {
177 typeParamsClone->SetParent(clone);
178 }
179
180 if (prevClone != nullptr) {
181 prevClone->SetParent(clone);
182 }
183
184 if (parent != nullptr) {
185 clone->SetParent(parent);
186 }
187
188 clone->SetRange(Range());
189 return clone;
190 }
191
192 throw Error(ErrorType::GENERIC, "", CLONE_ALLOCATION_ERROR);
193 }
194 } // namespace ark::es2panda::ir
195