1 /*
2 * Copyright (c) 2022 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 "typeExtractor.h"
17
18 #include <binder/binder.h>
19 #include <binder/tsBinding.h>
20 #include <ir/base/spreadElement.h>
21 #include <ir/expressions/callExpression.h>
22 #include <ir/expressions/classExpression.h>
23 #include <ir/expressions/memberExpression.h>
24 #include <ir/expressions/newExpression.h>
25 #include <ir/module/exportNamedDeclaration.h>
26 #include <ir/statements/expressionStatement.h>
27 #include <ir/statements/variableDeclaration.h>
28 #include <ir/statements/variableDeclarator.h>
29 #include <ir/ts/tsAsExpression.h>
30 #include <ir/ts/tsClassImplements.h>
31 #include <ir/ts/tsImportEqualsDeclaration.h>
32 #include <ir/ts/tsLiteralType.h>
33 #include <ir/ts/tsModuleDeclaration.h>
34 #include <ir/ts/tsParenthesizedType.h>
35 #include <ir/ts/tsQualifiedName.h>
36 #include <ir/ts/tsSatisfiesExpression.h>
37 #include <ir/ts/tsTypeAliasDeclaration.h>
38 #include <ir/ts/tsTypeAssertion.h>
39 #include <ir/ts/tsTypeParameterInstantiation.h>
40 #include <ir/ts/tsTypeReference.h>
41 #include <parser/module/sourceTextModuleRecord.h>
42
43 #include "typeSystem.h"
44
45 namespace panda::es2panda::extractor {
46
47 #ifndef NDEBUG
48 #define TLOG(type, res) \
49 do { \
50 std::cout << "[LOG]" << __func__ << ": " << static_cast<int64_t>(type) << " | " << (res) << std::endl; \
51 } while (0)
52 #else
53 #define TLOG(type, res) static_cast<void>(0)
54 #endif
55
56 const std::set<ir::AstNodeType> PRUNING_SET = {
57 ir::AstNodeType::IDENTIFIER,
58 ir::AstNodeType::TS_INTERFACE_DECLARATION,
59 ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION,
60 ir::AstNodeType::IMPORT_DECLARATION,
61 ir::AstNodeType::EXPORT_ALL_DECLARATION
62 };
63
TypeExtractor(const ir::BlockStatement * rootNode,bool typeDtsExtractor,bool typeDtsBuiltin,ArenaAllocator * allocator,compiler::CompilerContext * context)64 TypeExtractor::TypeExtractor(const ir::BlockStatement *rootNode, bool typeDtsExtractor, bool typeDtsBuiltin,
65 ArenaAllocator *allocator, compiler::CompilerContext *context)
66 : rootNode_(rootNode), typeDtsExtractor_(typeDtsExtractor), typeDtsBuiltin_(typeDtsBuiltin)
67 {
68 recorder_ = std::make_unique<TypeRecorder>(allocator, context);
69
70 getterMap_[ir::AstNodeType::IDENTIFIER] =
71 std::bind(&TypeExtractor::GetTypeIndexFromIdentifierNode, this, std::placeholders::_1, std::placeholders::_2);
72 getterMap_[ir::AstNodeType::CLASS_EXPRESSION] =
73 std::bind(&TypeExtractor::GetTypeIndexFromClassExpression, this, std::placeholders::_1, std::placeholders::_2);
74 getterMap_[ir::AstNodeType::CLASS_DEFINITION] =
75 std::bind(&TypeExtractor::GetTypeIndexFromClassDefinition, this, std::placeholders::_1, std::placeholders::_2);
76 getterMap_[ir::AstNodeType::TS_INTERFACE_DECLARATION] =
77 std::bind(&TypeExtractor::GetTypeIndexFromInterfaceNode, this, std::placeholders::_1, std::placeholders::_2);
78 getterMap_[ir::AstNodeType::FUNCTION_EXPRESSION] =
79 std::bind(&TypeExtractor::GetTypeIndexFromFunctionNode, this, std::placeholders::_1, std::placeholders::_2);
80 getterMap_[ir::AstNodeType::ARROW_FUNCTION_EXPRESSION] =
81 std::bind(&TypeExtractor::GetTypeIndexFromFunctionNode, this, std::placeholders::_1, std::placeholders::_2);
82 getterMap_[ir::AstNodeType::IMPORT_NAMESPACE_SPECIFIER] =
83 std::bind(&TypeExtractor::GetTypeIndexFromImportNode, this, std::placeholders::_1, std::placeholders::_2);
84 getterMap_[ir::AstNodeType::IMPORT_SPECIFIER] =
85 std::bind(&TypeExtractor::GetTypeIndexFromImportNode, this, std::placeholders::_1, std::placeholders::_2);
86 getterMap_[ir::AstNodeType::IMPORT_DEFAULT_SPECIFIER] =
87 std::bind(&TypeExtractor::GetTypeIndexFromImportNode, this, std::placeholders::_1, std::placeholders::_2);
88 getterMap_[ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION] =
89 std::bind(&TypeExtractor::GetTypeIndexFromTypeAliasNode, this, std::placeholders::_1, std::placeholders::_2);
90 getterMap_[ir::AstNodeType::TS_AS_EXPRESSION] =
91 std::bind(&TypeExtractor::GetTypeIndexFromAsNode, this, std::placeholders::_1, std::placeholders::_2);
92 getterMap_[ir::AstNodeType::TS_SATISFIES_EXPRESSION] =
93 std::bind(&TypeExtractor::GetTypeIndexFromSatisfiesNode, this, std::placeholders::_1, std::placeholders::_2);
94 getterMap_[ir::AstNodeType::TS_TYPE_ASSERTION] =
95 std::bind(&TypeExtractor::GetTypeIndexFromAssertionNode, this, std::placeholders::_1, std::placeholders::_2);
96 getterMap_[ir::AstNodeType::MEMBER_EXPRESSION] =
97 std::bind(&TypeExtractor::GetTypeIndexFromMemberNode, this, std::placeholders::_1, std::placeholders::_2);
98 getterMap_[ir::AstNodeType::TS_QUALIFIED_NAME] =
99 std::bind(&TypeExtractor::GetTypeIndexFromTSQualifiedNode, this, std::placeholders::_1, std::placeholders::_2);
100
101 handlerMap_[ir::AstNodeType::VARIABLE_DECLARATION] =
102 std::bind(&TypeExtractor::HandleVariableDeclaration, this, std::placeholders::_1);
103 handlerMap_[ir::AstNodeType::FUNCTION_DECLARATION] =
104 std::bind(&TypeExtractor::HandleFunctionDeclaration, this, std::placeholders::_1);
105 handlerMap_[ir::AstNodeType::CLASS_DECLARATION] =
106 std::bind(&TypeExtractor::HandleClassDeclaration, this, std::placeholders::_1);
107 handlerMap_[ir::AstNodeType::TS_INTERFACE_DECLARATION] =
108 std::bind(&TypeExtractor::HandleInterfaceDeclaration, this, std::placeholders::_1);
109 handlerMap_[ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION] =
110 std::bind(&TypeExtractor::HandleTypeAliasDeclaration, this, std::placeholders::_1);
111 handlerMap_[ir::AstNodeType::EXPRESSION_STATEMENT] =
112 std::bind(&TypeExtractor::HandleNewlyGenFuncExpression, this, std::placeholders::_1);
113 handlerMap_[ir::AstNodeType::ARROW_FUNCTION_EXPRESSION] =
114 std::bind(&TypeExtractor::HandleArrowFunctionExpression, this, std::placeholders::_1);
115 }
116
StartTypeExtractor(const parser::Program * program)117 void TypeExtractor::StartTypeExtractor(const parser::Program *program)
118 {
119 ASSERT(rootNode_->IsProgram());
120
121 TypeCounter counter(this);
122
123 ExtractImport(program);
124 ExtractNodesType(rootNode_);
125 ExtractExport(program);
126
127 recorder_->Dump(program);
128 recorder_->SetTypeSummaryIndex(counter.GetTypeIndexPlaceHolder());
129 counter.FillLiteralBuffer();
130 }
131
GetTypeDtsExtractor() const132 bool TypeExtractor::GetTypeDtsExtractor() const
133 {
134 return typeDtsExtractor_;
135 }
136
GetTypeDtsBuiltin() const137 bool TypeExtractor::GetTypeDtsBuiltin() const
138 {
139 return typeDtsBuiltin_;
140 }
141
Recorder() const142 TypeRecorder *TypeExtractor::Recorder() const
143 {
144 return recorder_.get();
145 }
146
ExtractNodesType(const ir::AstNode * parent)147 void TypeExtractor::ExtractNodesType(const ir::AstNode *parent)
148 {
149 parent->Iterate([this, parent](const auto *childNode) {
150 ExtractNodeType(parent, childNode);
151 });
152 }
153
ExtractNodeType(const ir::AstNode * parent,const ir::AstNode * childNode)154 void TypeExtractor::ExtractNodeType(const ir::AstNode *parent, const ir::AstNode *childNode)
155 {
156 auto iter = handlerMap_.find(childNode->Type());
157 if (iter != handlerMap_.end()) {
158 iter->second(childNode);
159 }
160
161 // Traversal pruning
162 if (PRUNING_SET.find(childNode->Type()) != PRUNING_SET.end()) {
163 return;
164 }
165
166 ExtractNodesType(childNode);
167 }
168
ExtractImport(const parser::Program * program)169 void TypeExtractor::ExtractImport(const parser::Program *program)
170 {
171 auto moduleRecord = program->Binder()->Program()->ModuleRecord();
172 if (moduleRecord == nullptr) {
173 return;
174 }
175 ExtractImportModuleRecord(moduleRecord);
176
177 auto typeModuleRecord = program->Binder()->Program()->TypeModuleRecord();
178 if (typeModuleRecord == nullptr) {
179 return;
180 }
181 ExtractImportModuleRecord(typeModuleRecord);
182 }
183
ExtractImportModuleRecord(parser::SourceTextModuleRecord * moduleRecord)184 void TypeExtractor::ExtractImportModuleRecord(parser::SourceTextModuleRecord *moduleRecord)
185 {
186 const auto ®ularImportEntries = moduleRecord->GetRegularImportEntries();
187 for (const auto &t : regularImportEntries) {
188 const auto &redirectPath = moduleRecord->GetModuleRequestIdxMap().at(t.second->moduleRequestIdx_);
189 ExternalType externalType(this, t.first, redirectPath);
190 recorder_->SetNodeTypeIndex(t.second->localId_->Parent(), externalType.GetTypeIndexShift());
191 }
192
193 const auto &namespaceImportEntries = moduleRecord->GetNamespaceImportEntries();
194 for (const auto &t : namespaceImportEntries) {
195 /*
196 * eg. export * as ns from './test'
197 */
198 if (t->localId_ == nullptr) {
199 continue;
200 }
201 const auto &redirectPath = moduleRecord->GetModuleRequestIdxMap().at(t->moduleRequestIdx_);
202 ExternalType externalType(this, "*", redirectPath);
203 recorder_->SetNodeTypeIndex(t->localId_->Parent(), externalType.GetTypeIndexShift());
204 recorder_->SetNamespaceType(std::string(t->localName_), externalType.GetTypeIndexShift());
205 recorder_->SetNamespacePath(std::string(t->localName_), std::string(redirectPath));
206 }
207 }
208
ExtractExport(const parser::Program * program)209 void TypeExtractor::ExtractExport(const parser::Program *program)
210 {
211 auto moduleRecord = program->Binder()->Program()->ModuleRecord();
212 if (moduleRecord == nullptr) {
213 return;
214 }
215 ExtractExportModuleRecord(moduleRecord);
216 auto typeModuleRecord = program->Binder()->Program()->TypeModuleRecord();
217 if (typeModuleRecord == nullptr) {
218 return;
219 }
220 ExtractExportModuleRecord(typeModuleRecord);
221 }
222
ExtractExportModuleRecord(parser::SourceTextModuleRecord * moduleRecord)223 void TypeExtractor::ExtractExportModuleRecord(parser::SourceTextModuleRecord *moduleRecord)
224 {
225 const auto &localExportEntries = moduleRecord->GetLocalExportEntries();
226 for (const auto &t : localExportEntries) {
227 auto identifier = t.second->localId_;
228 if (identifier == nullptr) {
229 if (t.second->exportId_ != nullptr) {
230 // Special case for NamespaceExport transform
231 // Refer to parser/statementParser.cpp `AddExportStarEntryItem`
232 recorder_->SetExportType(std::string(t.second->exportName_),
233 recorder_->GetNamespaceType(std::string(t.second->localName_)));
234 }
235 // Other export extries without local identifier is handled during traversal
236 continue;
237 }
238 auto typeIndex = recorder_->GetVariableTypeIndex(identifier->Variable());
239 if (typeIndex != PrimitiveType::ANY) {
240 recorder_->SetExportType(std::string(t.second->exportName_), typeIndex);
241 continue;
242 }
243 if (identifier->Variable() != nullptr && identifier->Variable()->Declaration() != nullptr) {
244 auto declNode = identifier->Variable()->Declaration()->Node();
245 typeIndex = recorder_->GetNodeTypeIndex(declNode);
246 if (typeIndex == PrimitiveType::ANY && declNode != nullptr) {
247 typeIndex = GetTypeIndexFromDeclNode(declNode, true);
248 recorder_->SetIdentifierTypeIndex(identifier, typeIndex);
249 }
250 if (typeIndex != PrimitiveType::ANY) {
251 recorder_->SetExportType(std::string(t.second->exportName_), typeIndex);
252 }
253 }
254 }
255
256 const auto &starExportEntries = moduleRecord->GetStarExportEntries();
257 for (const auto &t : starExportEntries) {
258 recorder_->AddAnonymousReExport(moduleRecord->GetModuleRequestIdxMap().at(t->moduleRequestIdx_));
259 }
260
261 const auto &indirectExportEntries = moduleRecord->GetIndirectExportEntries();
262 for (const auto &t : indirectExportEntries) {
263 const auto &redirectPath = moduleRecord->GetModuleRequestIdxMap().at(t->moduleRequestIdx_);
264 ExternalType externalType(this, t->importName_, redirectPath);
265 recorder_->SetExportType(std::string(t->exportName_), externalType.GetTypeIndexShift());
266 }
267 }
268
GetIdentifierFromExpression(const ir::Expression * expression)269 const ir::Identifier *TypeExtractor::GetIdentifierFromExpression(const ir::Expression *expression)
270 {
271 switch (expression->Type()) {
272 case ir::AstNodeType::IDENTIFIER:
273 return expression->AsIdentifier();
274 case ir::AstNodeType::REST_ELEMENT: {
275 auto argument = expression->AsRestElement()->Argument();
276 if (argument->IsIdentifier()) {
277 return argument->AsIdentifier();
278 }
279 return nullptr;
280 }
281 case ir::AstNodeType::SPREAD_ELEMENT: {
282 auto argument = expression->AsSpreadElement()->Argument();
283 if (argument->IsIdentifier()) {
284 return argument->AsIdentifier();
285 }
286 return nullptr;
287 }
288 default:
289 return nullptr;
290 }
291 }
292
GetDeclNodeFromIdentifier(const ir::Identifier * identifier,const ir::Identifier ** variable)293 const ir::AstNode *TypeExtractor::GetDeclNodeFromIdentifier(const ir::Identifier *identifier,
294 const ir::Identifier **variable)
295 {
296 if (identifier == nullptr) {
297 return nullptr;
298 }
299
300 std::vector<binder::Variable *> variables;
301 variables.reserve(identifier->TSVariables().size() + 1U);
302 variables.emplace_back(identifier->Variable());
303 for (const auto &v : identifier->TSVariables()) {
304 variables.emplace_back(v);
305 }
306
307 for (const auto &v : variables) {
308 if (v == nullptr || v->Declaration() == nullptr || v->Declaration()->Node() == nullptr) {
309 continue;
310 }
311
312 auto res = v->Declaration()->Node();
313 // Save reference identifier if it contains variable binding to decl node
314 // TODO(extractor): consider js&ts decl node merging, for example
315 // class A { a : string = "aaa" }
316 // interface A { b : number }
317 // let a : A = new A()
318 // console.log(a.b)
319 *variable = identifier;
320 TLOG(res->Type(), identifier);
321 return res;
322 }
323 return nullptr;
324 }
325
GetDeclNodeFromInitializer(const ir::Expression * initializer,const ir::Identifier ** variable)326 const ir::AstNode *TypeExtractor::GetDeclNodeFromInitializer(const ir::Expression *initializer,
327 const ir::Identifier **variable)
328 {
329 switch (initializer->Type()) {
330 case ir::AstNodeType::IDENTIFIER: // let a = b / let a : A
331 return GetDeclNodeFromIdentifier(initializer->AsIdentifier(), variable);
332 case ir::AstNodeType::NEW_EXPRESSION: {
333 auto callee = initializer->AsNewExpression()->Callee();
334 if (callee->IsClassExpression()) { // let a = new class {}
335 return callee;
336 } else if (callee->IsIdentifier()) { // let a = new A()
337 return GetDeclNodeFromIdentifier(callee->AsIdentifier(), variable);
338 }
339 break;
340 }
341 case ir::AstNodeType::TS_CLASS_IMPLEMENTS: { // class a implements A {}
342 auto expr = initializer->AsTSClassImplements()->Expr();
343 if (expr->IsIdentifier()) {
344 return GetDeclNodeFromIdentifier(expr->AsIdentifier(), variable);
345 }
346 ASSERT(expr->IsTSQualifiedName());
347 return expr->AsTSQualifiedName();
348 }
349 case ir::AstNodeType::CLASS_EXPRESSION: // let a = class A {}
350 case ir::AstNodeType::FUNCTION_EXPRESSION: // let a = function func () {}
351 case ir::AstNodeType::ARROW_FUNCTION_EXPRESSION: // let a = () => {}
352 case ir::AstNodeType::MEMBER_EXPRESSION: // let a = ns.A
353 case ir::AstNodeType::TS_QUALIFIED_NAME: // let a : ns.A
354 case ir::AstNodeType::TS_AS_EXPRESSION: // let a = x as number
355 case ir::AstNodeType::TS_TYPE_ASSERTION: // let a = <number>x
356 return initializer;
357 default:
358 break;
359 }
360
361 auto identifier = GetIdentifierFromExpression(initializer);
362 if (identifier != nullptr) {
363 return GetDeclNodeFromIdentifier(identifier, variable);
364 }
365 return nullptr;
366 }
367
GetTypeIndexFromDeclNode(const ir::AstNode * node,bool isNewInstance)368 int64_t TypeExtractor::GetTypeIndexFromDeclNode(const ir::AstNode *node, bool isNewInstance)
369 {
370 auto iter = getterMap_.find(node->Type());
371 if (iter != getterMap_.end()) {
372 return iter->second(node, isNewInstance);
373 }
374 return PrimitiveType::ANY;
375 }
376
GetTypeIndexFromIdentifierNode(const ir::AstNode * node,bool isNewInstance)377 int64_t TypeExtractor::GetTypeIndexFromIdentifierNode(const ir::AstNode *node, bool isNewInstance)
378 {
379 auto typeIndex = recorder_->GetNodeTypeIndex(node);
380 TLOG(node->Type(), typeIndex);
381 return typeIndex;
382 }
383
GetTypeIndexFromClassExpression(const ir::AstNode * node,bool isNewInstance)384 int64_t TypeExtractor::GetTypeIndexFromClassExpression(const ir::AstNode *node, bool isNewInstance)
385 {
386 auto classDef = node->AsClassExpression()->Definition();
387 auto typeIndex = GetTypeIndexFromClassDefinition(classDef, isNewInstance);
388 TLOG(node->Type(), typeIndex);
389 return typeIndex;
390 }
391
GetTypeIndexFromClassDefinition(const ir::AstNode * node,bool isNewInstance)392 int64_t TypeExtractor::GetTypeIndexFromClassDefinition(const ir::AstNode *node, bool isNewInstance)
393 {
394 int64_t typeIndex = PrimitiveType::ANY;
395 auto fn = [&node, &typeIndex, this](const util::StringView &name) {
396 ClassType classType(this, node->AsClassDefinition(), name);
397 typeIndex = classType.GetTypeIndexShift();
398 };
399
400 auto identifier = node->AsClassDefinition()->Ident();
401 if (identifier != nullptr) {
402 fn(identifier->Name());
403 recorder_->SetIdentifierTypeIndex(identifier, typeIndex);
404 } else {
405 fn(std::move(DEFAULT_NAME));
406 }
407
408 if (isNewInstance) {
409 typeIndex = GetTypeIndexFromClassInst(typeIndex, node);
410 }
411
412 TLOG(node->Type(), typeIndex);
413 return typeIndex;
414 }
415
GetTypeIndexFromInterfaceNode(const ir::AstNode * node,bool isNewInstance)416 int64_t TypeExtractor::GetTypeIndexFromInterfaceNode(const ir::AstNode *node, [[maybe_unused]] bool isNewInstance)
417 {
418 int64_t typeIndex = PrimitiveType::ANY;
419 auto fn = [&node, &typeIndex, this](const util::StringView &name) {
420 InterfaceType interfaceType(this, node->AsTSInterfaceDeclaration(), name);
421 typeIndex = interfaceType.GetTypeIndexShift();
422 };
423
424 auto identifier = node->AsTSInterfaceDeclaration()->Id();
425 if (identifier != nullptr) {
426 fn(identifier->Name());
427 recorder_->SetIdentifierTypeIndex(identifier, typeIndex);
428 } else {
429 fn(std::move(DEFAULT_NAME));
430 }
431
432 TLOG(node->Type(), typeIndex);
433 return typeIndex;
434 }
435
GetTypeIndexFromFunctionNode(const ir::AstNode * node,bool isNewInstance)436 int64_t TypeExtractor::GetTypeIndexFromFunctionNode(const ir::AstNode *node, [[maybe_unused]] bool isNewInstance)
437 {
438 int64_t typeIndex = PrimitiveType::ANY;
439 auto fn = [&node, &typeIndex, this](const util::StringView &name) {
440 FunctionType functionType(this, node, name);
441 typeIndex = functionType.GetTypeIndexShift();
442 };
443
444 if (node->IsFunctionExpression()) {
445 auto identifier = node->AsFunctionExpression()->Function()->Id();
446 if (identifier != nullptr) {
447 fn(identifier->Name());
448 recorder_->SetIdentifierTypeIndex(identifier, typeIndex);
449 } else {
450 fn("");
451 }
452 } else {
453 fn("");
454 }
455
456 TLOG(node->Type(), typeIndex);
457 return typeIndex;
458 }
459
GetTypeIndexFromImportNode(const ir::AstNode * node,bool isNewInstance)460 int64_t TypeExtractor::GetTypeIndexFromImportNode(const ir::AstNode *node, [[maybe_unused]] bool isNewInstance)
461 {
462 auto typeIndex = recorder_->GetNodeTypeIndex(node);
463 TLOG(node->Type(), typeIndex);
464 return typeIndex;
465 }
466
GetTypeIndexFromTypeAliasNode(const ir::AstNode * node,bool isNewInstance)467 int64_t TypeExtractor::GetTypeIndexFromTypeAliasNode(const ir::AstNode *node, [[maybe_unused]] bool isNewInstance)
468 {
469 auto typeNode = node->AsTSTypeAliasDeclaration()->TypeAnnotation();
470 if (!AddSearchingTypeRefNodes(typeNode)) {
471 RemoveSearchingTypeRefNodes(typeNode);
472 return PrimitiveType::ANY;
473 }
474 auto typeIndex = GetTypeIndexFromAnnotation(typeNode);
475 TLOG(node->Type(), typeIndex);
476 RemoveSearchingTypeRefNodes(typeNode);
477 return typeIndex;
478 }
479
GetTypeIndexFromAsNode(const ir::AstNode * node,bool isNewInstance)480 int64_t TypeExtractor::GetTypeIndexFromAsNode(const ir::AstNode *node, [[maybe_unused]] bool isNewInstance)
481 {
482 auto typeIndex = GetTypeIndexFromAnnotation(node->AsTSAsExpression()->TypeAnnotation());
483 TLOG(node->Type(), typeIndex);
484 return typeIndex;
485 }
486
GetTypeIndexFromSatisfiesNode(const ir::AstNode * node,bool isNewInstance)487 int64_t TypeExtractor::GetTypeIndexFromSatisfiesNode(const ir::AstNode *node, [[maybe_unused]] bool isNewInstance)
488 {
489 auto typeIndex = GetTypeIndexFromAnnotation(node->AsTSSatisfiesExpression()->TypeAnnotation());
490 TLOG(node->Type(), typeIndex);
491 return typeIndex;
492 }
493
GetTypeIndexFromAssertionNode(const ir::AstNode * node,bool isNewInstance)494 int64_t TypeExtractor::GetTypeIndexFromAssertionNode(const ir::AstNode *node, [[maybe_unused]] bool isNewInstance)
495 {
496 auto typeIndex = GetTypeIndexFromAnnotation(node->AsTSTypeAssertion()->TypeAnnotation());
497 TLOG(node->Type(), typeIndex);
498 return typeIndex;
499 }
500
GetTypeIndexFromMemberNode(const ir::AstNode * node,bool isNewInstance)501 int64_t TypeExtractor::GetTypeIndexFromMemberNode(const ir::AstNode *node, [[maybe_unused]] bool isNewInstance)
502 {
503 int64_t typeIndex = PrimitiveType::ANY;
504 auto object = node->AsMemberExpression()->Object();
505 auto property = node->AsMemberExpression()->Property();
506 if (object->IsIdentifier() && property->IsIdentifier()) {
507 auto redirectPath = recorder_->GetNamespacePath(std::string(object->AsIdentifier()->Name()));
508 if (redirectPath != "") {
509 ExternalType externalType(this, property->AsIdentifier()->Name(), util::StringView(redirectPath));
510 typeIndex = externalType.GetTypeIndexShift();
511 }
512 }
513 TLOG(node->Type(), typeIndex);
514 return typeIndex;
515 }
516
GetTypeIndexFromTSQualifiedNode(const ir::AstNode * node,bool isNewInstance)517 int64_t TypeExtractor::GetTypeIndexFromTSQualifiedNode(const ir::AstNode *node, bool isNewInstance)
518 {
519 ArenaDeque<const ir::Identifier *> identifiers(recorder_->Allocator()->Adapter());
520 const ir::Expression *head = node->AsTSQualifiedName();
521 while (head->IsTSQualifiedName()) {
522 identifiers.emplace_front(head->AsTSQualifiedName()->Right());
523 head = head->AsTSQualifiedName()->Left();
524 }
525
526 ASSERT(head->IsIdentifier());
527 ArenaVector<const binder::Variable *> variables(recorder_->Allocator()->Adapter());
528 for (const auto &v : head->AsIdentifier()->TSVariables()) {
529 GetVariablesFromTSQualifiedNodes(v, identifiers, variables);
530 }
531
532 int64_t typeIndex = PrimitiveType::ANY;
533 for (const auto &v : variables) {
534 if (v->Declaration() != nullptr && v->Declaration()->Node() != nullptr) {
535 typeIndex = GetTypeIndexFromDeclNode(v->Declaration()->Node(), isNewInstance);
536 if (typeIndex != PrimitiveType::ANY) {
537 break;
538 }
539 }
540 }
541 if (typeIndex == PrimitiveType::ANY) {
542 auto left = node->AsTSQualifiedName()->Left();
543 auto right = node->AsTSQualifiedName()->Right();
544 if (left->IsIdentifier()) {
545 auto redirectPath = recorder_->GetNamespacePath(std::string(left->AsIdentifier()->Name()));
546 if (redirectPath != "") {
547 ExternalType externalType(this, right->Name(), util::StringView(redirectPath));
548 typeIndex = externalType.GetTypeIndexShift();
549 }
550 }
551 }
552 TLOG(node->Type(), typeIndex);
553 return typeIndex;
554 }
555
GetTypeIndexFromAnnotation(const ir::Expression * typeAnnotation,bool isNewInstance)556 int64_t TypeExtractor::GetTypeIndexFromAnnotation(const ir::Expression *typeAnnotation, bool isNewInstance)
557 {
558 if (typeAnnotation == nullptr) {
559 return PrimitiveType::ANY;
560 }
561
562 switch (typeAnnotation->AsTypeNode()->Type()) {
563 case ir::AstNodeType::TS_ANY_KEYWORD:
564 case ir::AstNodeType::TS_NUMBER_KEYWORD:
565 case ir::AstNodeType::TS_BOOLEAN_KEYWORD:
566 case ir::AstNodeType::TS_VOID_KEYWORD:
567 case ir::AstNodeType::TS_STRING_KEYWORD:
568 case ir::AstNodeType::TS_SYMBOL_KEYWORD:
569 case ir::AstNodeType::TS_NULL_KEYWORD:
570 case ir::AstNodeType::TS_UNDEFINED_KEYWORD:
571 return PRIMITIVE_TYPE_MAP.at(typeAnnotation->AsTypeNode()->Type());
572 case ir::AstNodeType::TS_LITERAL_TYPE:
573 return GetTypeIndexFromTSLiteralType(typeAnnotation->AsTSLiteralType());
574 case ir::AstNodeType::TS_NEVER_KEYWORD:
575 case ir::AstNodeType::TS_UNKNOWN_KEYWORD:
576 return PrimitiveType::ANY;
577 case ir::AstNodeType::TS_ARRAY_TYPE: { // ArrayType
578 ArrayType arrayType(this, typeAnnotation->AsTSArrayType());
579 return arrayType.GetTypeIndexShift();
580 }
581 case ir::AstNodeType::TS_UNION_TYPE: { // UnionType
582 UnionType unionType(this, typeAnnotation->AsTSUnionType());
583 return unionType.GetTypeIndexShift();
584 }
585 case ir::AstNodeType::TS_PARENT_TYPE: { // (UnionType) / (FunctionType)
586 auto type = typeAnnotation->AsTSParenthesizedType()->Type();
587 ASSERT(type != nullptr);
588 if (type->IsTSUnionType()) {
589 UnionType unionType(this, type->AsTSUnionType());
590 return unionType.GetTypeIndexShift();
591 } else if (type->IsTSFunctionType()) {
592 FunctionType functionType(this, type->AsTSFunctionType(), "");
593 return functionType.GetTypeIndexShift();
594 } else if (type->IsTSConstructorType()) {
595 FunctionType functionType(this, type->AsTSConstructorType(), "");
596 return functionType.GetTypeIndexShift();
597 }
598 return PrimitiveType::ANY;
599 }
600 case ir::AstNodeType::TS_TYPE_LITERAL: { // ObjectType
601 ObjectType objectType(this, typeAnnotation->AsTSTypeLiteral());
602 return objectType.GetTypeIndexShift();
603 }
604 case ir::AstNodeType::TS_OBJECT_KEYWORD: { // ObjectType
605 ObjectType objectType(this, nullptr); // let a : object
606 return objectType.GetTypeIndexShift();
607 }
608 case ir::AstNodeType::TS_FUNCTION_TYPE: { // FunctionType, let a : () => {}
609 FunctionType functionType(this, typeAnnotation->AsTSFunctionType(), "");
610 return functionType.GetTypeIndexShift();
611 }
612 case ir::AstNodeType::TS_CONSTRUCTOR_TYPE: { // FunctionType, let a : new () => {}
613 FunctionType functionType(this, typeAnnotation->AsTSConstructorType(), "");
614 return functionType.GetTypeIndexShift();
615 }
616 case ir::AstNodeType::TS_BIGINT_KEYWORD:
617 case ir::AstNodeType::TS_CONDITIONAL_TYPE:
618 case ir::AstNodeType::TS_IMPORT_TYPE:
619 case ir::AstNodeType::TS_INDEXED_ACCESS_TYPE:
620 case ir::AstNodeType::TS_INTERSECTION_TYPE:
621 case ir::AstNodeType::TS_INFER_TYPE:
622 case ir::AstNodeType::TS_MAPPED_TYPE:
623 case ir::AstNodeType::TS_OPTIONAL_TYPE:
624 case ir::AstNodeType::TS_REST_TYPE:
625 case ir::AstNodeType::TS_TEMPLATE_LITERAL_TYPE:
626 case ir::AstNodeType::TS_THIS_TYPE:
627 case ir::AstNodeType::TS_TUPLE_TYPE:
628 case ir::AstNodeType::TS_TYPE_OPERATOR:
629 case ir::AstNodeType::TS_TYPE_PREDICATE:
630 case ir::AstNodeType::TS_TYPE_QUERY:
631 return PrimitiveType::ANY;
632 case ir::AstNodeType::TS_TYPE_REFERENCE: { // let a : A
633 return GetTypeIndexFromTypeReference(typeAnnotation->AsTSTypeReference(), isNewInstance);
634 }
635 default:
636 UNREACHABLE();
637 }
638 }
639
GetTypeIndexFromIdentifier(const ir::Identifier * identifier)640 int64_t TypeExtractor::GetTypeIndexFromIdentifier(const ir::Identifier *identifier)
641 {
642 auto typeAnnotation = identifier->TypeAnnotation();
643 auto typeIndex = GetTypeIndexFromAnnotation(typeAnnotation);
644 recorder_->SetIdentifierTypeIndex(identifier, typeIndex);
645 TLOG(identifier->Type(), typeIndex);
646 return typeIndex;
647 }
648
GetTypeIndexFromInitializer(const ir::Expression * initializer)649 int64_t TypeExtractor::GetTypeIndexFromInitializer(const ir::Expression *initializer)
650 {
651 int64_t typeIndex = PrimitiveType::ANY;
652 // Special case for Builtin
653 if (initializer->IsNewExpression()) {
654 auto callee = initializer->AsNewExpression()->Callee();
655 if (callee->IsIdentifier()) {
656 typeIndex = GetTypeIndexFromBuiltin(callee->AsIdentifier()->Name(),
657 initializer->AsNewExpression()->TypeParams());
658 if (typeIndex != PrimitiveType::ANY) {
659 return typeIndex;
660 }
661 }
662 }
663
664 const ir::Identifier *identifier = nullptr;
665 // Identifier here is a reference identifier binding to decl node which also contains variable
666 auto declNode = GetDeclNodeFromInitializer(initializer, &identifier);
667 if (declNode != nullptr) {
668 if (initializer->IsNewExpression() && initializer->AsNewExpression()->TypeParams() != nullptr) {
669 typeIndex = GetTypeIndexFromGenericInst(declNode, initializer->AsNewExpression()->TypeParams());
670 } else {
671 typeIndex = GetTypeIndexFromDeclNode(declNode, initializer->IsNewExpression());
672 }
673 recorder_->SetIdentifierTypeIndex(identifier, recorder_->GetClassType(typeIndex));
674 }
675 TLOG(initializer->Type(), typeIndex);
676 return typeIndex;
677 }
678
HandleVariableDeclaration(const ir::AstNode * node)679 void TypeExtractor::HandleVariableDeclaration(const ir::AstNode *node)
680 {
681 auto isExported = IsExportNode(node);
682 for (const auto *it : node->AsVariableDeclaration()->Declarators()) {
683 if (!it->Id()->IsIdentifier()) {
684 // BindingElement needs type inference, like:
685 // ArrayExpression: let [a, b] = [1, 2]
686 // ObjectExpression: let {a, b} = c
687 continue;
688 }
689 auto identifier = it->Id()->AsIdentifier();
690 ASSERT(identifier != nullptr);
691 auto typeIndex = GetTypeIndexFromIdentifier(identifier);
692 if (typeIndex == PrimitiveType::ANY && it->Init() != nullptr) {
693 typeIndex = GetTypeIndexFromInitializer(it->Init());
694 }
695 recorder_->SetIdentifierTypeIndex(identifier, typeIndex);
696 if (isExported && typeIndex != PrimitiveType::ANY) {
697 recorder_->SetExportType(std::string(identifier->Name()), typeIndex);
698 }
699 }
700 }
701
HandleFunctionDeclaration(const ir::AstNode * node)702 void TypeExtractor::HandleFunctionDeclaration(const ir::AstNode *node)
703 {
704 int64_t typeIndex = PrimitiveType::ANY;
705 auto fn = [&node, &typeIndex, this](const util::StringView &name) {
706 FunctionType functionType(this, node, name);
707 typeIndex = functionType.GetTypeIndexShift();
708 if (IsExportNode(node)) {
709 recorder_->SetExportType(std::string(name), typeIndex);
710 }
711 if (IsDeclareNode(node)) {
712 recorder_->SetDeclareType(std::string(name), typeIndex);
713 }
714 };
715
716 auto identifier = node->AsFunctionDeclaration()->Function()->Id();
717 if (identifier != nullptr) {
718 fn(identifier->Name());
719 recorder_->SetIdentifierTypeIndex(identifier, typeIndex);
720 } else {
721 fn("");
722 }
723 }
724
HandleClassDeclaration(const ir::AstNode * node)725 void TypeExtractor::HandleClassDeclaration(const ir::AstNode *node)
726 {
727 int64_t typeIndex = PrimitiveType::ANY;
728 auto classDef = node->AsClassDeclaration()->Definition();
729 auto fn = [&node, &typeIndex, &classDef, this](const util::StringView &name) {
730 ClassType classType(this, classDef, name);
731 typeIndex = classType.GetTypeIndexShift();
732 if (IsExportNode(node)) {
733 recorder_->SetExportType(std::string(name), typeIndex);
734 }
735 if (IsDeclareNode(node)) {
736 recorder_->SetDeclareType(std::string(name), typeIndex);
737 }
738 };
739
740 auto identifier = classDef->Ident();
741 if (identifier != nullptr) {
742 fn(identifier->Name());
743 recorder_->SetIdentifierTypeIndex(identifier, typeIndex);
744 } else {
745 fn(std::move(DEFAULT_NAME));
746 }
747 }
748
HandleInterfaceDeclaration(const ir::AstNode * node)749 void TypeExtractor::HandleInterfaceDeclaration(const ir::AstNode *node)
750 {
751 int64_t typeIndex = PrimitiveType::ANY;
752 auto interfaceDef = node->AsTSInterfaceDeclaration();
753 auto fn = [&node, &typeIndex, &interfaceDef, this](const util::StringView &name) {
754 InterfaceType interfaceType(this, interfaceDef, name);
755 typeIndex = interfaceType.GetTypeIndexShift();
756 if (IsExportNode(node)) {
757 recorder_->SetExportType(std::string(name), typeIndex);
758 }
759 if (IsDeclareNode(node)) {
760 recorder_->SetDeclareType(std::string(name), typeIndex);
761 }
762 };
763
764 auto identifier = interfaceDef->Id();
765 if (identifier != nullptr) {
766 fn(identifier->Name());
767 recorder_->SetIdentifierTypeIndex(identifier, typeIndex);
768 } else {
769 fn(std::move(DEFAULT_NAME));
770 }
771 }
772
HandleTypeAliasDeclaration(const ir::AstNode * node)773 void TypeExtractor::HandleTypeAliasDeclaration(const ir::AstNode *node)
774 {
775 // Create the type if it is exported or declared
776 auto typeAliasDef = node->AsTSTypeAliasDeclaration();
777 auto identifier = typeAliasDef->Id();
778 if (IsExportNode(node)) {
779 recorder_->SetExportType(std::string(identifier->Name()),
780 GetTypeIndexFromAnnotation(typeAliasDef->TypeAnnotation()));
781 }
782 if (IsDeclareNode(node)) {
783 recorder_->SetDeclareType(std::string(identifier->Name()),
784 GetTypeIndexFromAnnotation(typeAliasDef->TypeAnnotation()));
785 }
786 }
787
HandleNewlyGenFuncExpression(const ir::AstNode * node)788 void TypeExtractor::HandleNewlyGenFuncExpression(const ir::AstNode *node)
789 {
790 if (!node->Original()) {
791 return;
792 }
793 auto originalNode = node->Original();
794 int64_t typeFlag = PrimitiveType::ANY;
795 switch (originalNode->Type()) {
796 case ir::AstNodeType::TS_MODULE_DECLARATION: {
797 typeFlag = extractor::BuiltinFlag::NAMESPACE_FUNCTION;
798 break;
799 }
800 case ir::AstNodeType::TS_ENUM_DECLARATION: {
801 typeFlag = extractor::BuiltinFlag::ENUM_FUNCTION;
802 break;
803 }
804 case ir::AstNodeType::EXPORT_NAMED_DECLARATION: {
805 auto decl = originalNode->AsExportNamedDeclaration()->Decl();
806 if (!decl) {
807 return;
808 }
809 if (decl->IsTSModuleDeclaration()) {
810 typeFlag = extractor::BuiltinFlag::NAMESPACE_FUNCTION;
811 } else if (decl->IsTSEnumDeclaration()) {
812 typeFlag = extractor::BuiltinFlag::ENUM_FUNCTION;
813 }
814 break;
815 }
816 default: {
817 return;
818 }
819 }
820 if (typeFlag != PrimitiveType::ANY) {
821 auto funcExpr = node->AsExpressionStatement()->GetExpression()->AsCallExpression()->Callee();
822 recorder_->SetNodeTypeIndex(funcExpr->AsFunctionExpression()->Function(), typeFlag);
823 }
824 }
825
HandleArrowFunctionExpression(const ir::AstNode * node)826 void TypeExtractor::HandleArrowFunctionExpression(const ir::AstNode *node)
827 {
828 ASSERT(node->IsArrowFunctionExpression());
829 auto typeIndex = recorder_->GetNodeTypeIndex(node->AsArrowFunctionExpression()->Function());
830 if (typeIndex != PrimitiveType::ANY) {
831 return;
832 }
833 GetTypeIndexFromFunctionNode(node, false);
834 }
835
GetTypeIndexFromClassInst(int64_t typeIndex,const ir::AstNode * node,int64_t builtinTypeIndex)836 int64_t TypeExtractor::GetTypeIndexFromClassInst(int64_t typeIndex, const ir::AstNode *node, int64_t builtinTypeIndex)
837 {
838 // A class instance type should point to a class type or a builtin type
839 ASSERT((node == nullptr) ^ (builtinTypeIndex == PrimitiveType::ANY));
840 if (node && !node->IsClassDefinition()) {
841 return PrimitiveType::ANY;
842 }
843
844 if (builtinTypeIndex != PrimitiveType::ANY && !recorder_->isBuiltinType(builtinTypeIndex)) {
845 return PrimitiveType::ANY;
846 }
847
848 auto typeIndexTmp = recorder_->GetClassInst(typeIndex);
849 if (typeIndexTmp == PrimitiveType::ANY) {
850 ClassInstType classInstType(this, typeIndex);
851 return classInstType.GetTypeIndexShift();
852 }
853 return typeIndexTmp;
854 }
855
GetTypeIndexFromTypeReference(const ir::TSTypeReference * typeReference,bool isNewInstance)856 int64_t TypeExtractor::GetTypeIndexFromTypeReference(const ir::TSTypeReference *typeReference, bool isNewInstance)
857 {
858 auto typeName = typeReference->TypeName();
859 ASSERT(typeName != nullptr);
860 if (typeName->IsIdentifier()) {
861 const auto &name = typeName->AsIdentifier()->Name();
862 // First, consider if the type identify is Builtin Type
863 auto typeIndexBuiltin = GetTypeIndexFromBuiltin(name, typeReference->TypeParams());
864 if (typeIndexBuiltin != PrimitiveType::ANY) {
865 return typeIndexBuiltin;
866 }
867 // Second, consider if the type identify is Generic Type
868 auto genericParamTypeMap = GetGenericParamTypeMap();
869 if (genericParamTypeMap != nullptr) {
870 auto t = genericParamTypeMap->find(name);
871 if (t != genericParamTypeMap->end()) {
872 return t->second;
873 }
874 }
875 }
876
877 const ir::Identifier *identifier = nullptr;
878 // TypeName can be Identifier or TSQualifiedName
879 // Identifier here is a reference identifier binding to decl node which also contains variable
880 auto declNode = GetDeclNodeFromInitializer(typeName, &identifier);
881 if (declNode != nullptr) {
882 int64_t typeIndex = PrimitiveType::ANY;
883 if (typeReference->TypeParams() != nullptr) {
884 typeIndex = GetTypeIndexFromGenericInst(declNode, typeReference->TypeParams());
885 } else {
886 typeIndex = GetTypeIndexFromDeclNode(declNode, isNewInstance);
887 }
888 recorder_->SetIdentifierTypeIndex(identifier, recorder_->GetClassType(typeIndex));
889 return typeIndex;
890 }
891 return PrimitiveType::ANY;
892 }
893
GetTypeIndexFromTSLiteralType(const ir::TSLiteralType * tsLiteralType)894 int64_t TypeExtractor::GetTypeIndexFromTSLiteralType(const ir::TSLiteralType *tsLiteralType)
895 {
896 switch (tsLiteralType->Literal()->Type()) {
897 case ir::AstNodeType::NUMBER_LITERAL:
898 return PrimitiveType::NUMBER;
899 case ir::AstNodeType::BOOLEAN_LITERAL:
900 return PrimitiveType::BOOLEAN;
901 case ir::AstNodeType::STRING_LITERAL:
902 return PrimitiveType::STRING;
903 case ir::AstNodeType::NULL_LITERAL:
904 return PrimitiveType::NUL;
905 default:
906 return PrimitiveType::ANY;
907 }
908 }
909
GetTypeIndexFromBuiltin(const util::StringView & name,const ir::TSTypeParameterInstantiation * node)910 int64_t TypeExtractor::GetTypeIndexFromBuiltin(const util::StringView &name,
911 const ir::TSTypeParameterInstantiation *node)
912 {
913 auto typeIndexBuiltin = GetBuiltinTypeIndex(name);
914 if (typeIndexBuiltin != PrimitiveType::ANY) {
915 if (node == nullptr) {
916 return GetTypeIndexFromClassInst(typeIndexBuiltin, nullptr, typeIndexBuiltin);
917 }
918 return GetTypeIndexFromBuiltinInst(typeIndexBuiltin, node);
919 }
920 return PrimitiveType::ANY;
921 }
922
GetTypeIndexFromBuiltinInst(int64_t typeIndexBuiltin,const ir::TSTypeParameterInstantiation * node)923 int64_t TypeExtractor::GetTypeIndexFromBuiltinInst(int64_t typeIndexBuiltin,
924 const ir::TSTypeParameterInstantiation *node)
925 {
926 std::vector<int64_t> allTypes = {typeIndexBuiltin};
927 for (const auto &t : node->Params()) {
928 allTypes.emplace_back(GetTypeIndexFromAnnotation(t));
929 }
930 auto typeIndex = recorder_->GetBuiltinInst(allTypes);
931 if (typeIndex != PrimitiveType::ANY) {
932 return typeIndex;
933 }
934
935 // New instance for builtin generic type
936 BuiltinInstType builtinInstType(this, allTypes);
937 return GetTypeIndexFromClassInst(builtinInstType.GetTypeIndexShift(), nullptr, typeIndexBuiltin);
938 }
939
GetTypeIndexFromGenericInst(const ir::AstNode * declNode,const ir::TSTypeParameterInstantiation * node)940 int64_t TypeExtractor::GetTypeIndexFromGenericInst(const ir::AstNode *declNode,
941 const ir::TSTypeParameterInstantiation *node)
942 {
943 if (!declNode->IsClassDefinition()) {
944 return PrimitiveType::ANY;
945 }
946 int64_t typeIndexGeneric = GetTypeIndexFromDeclNode(declNode, false);
947 std::vector<int64_t> allTypes = {typeIndexGeneric};
948 for (const auto &t : node->Params()) {
949 allTypes.emplace_back(GetTypeIndexFromAnnotation(t));
950 }
951 auto typeIndex = recorder_->GetGenericInst(allTypes);
952 if (typeIndex != PrimitiveType::ANY) {
953 return typeIndex;
954 }
955
956 // New instance for generic type
957 GenericInstType genericInstType(this, allTypes);
958 return GetTypeIndexFromClassInst(genericInstType.GetTypeIndexShift(), declNode);
959 }
960
IsExportNode(const ir::AstNode * node) const961 bool TypeExtractor::IsExportNode(const ir::AstNode *node) const
962 {
963 auto parent = node->Parent();
964 if (parent->Parent() != rootNode_) {
965 return false;
966 }
967 if (parent->IsExportNamedDeclaration() || parent->IsExportDefaultDeclaration()) {
968 return true;
969 }
970 return false;
971 }
972
IsDeclareNode(const ir::AstNode * node) const973 bool TypeExtractor::IsDeclareNode(const ir::AstNode *node) const
974 {
975 if (!typeDtsExtractor_) {
976 return false;
977 }
978 switch (node->Type()) {
979 case ir::AstNodeType::FUNCTION_DECLARATION:
980 return node->AsFunctionDeclaration()->Function()->Declare();
981 case ir::AstNodeType::CLASS_DEFINITION:
982 return node->AsClassDefinition()->Declare();
983 case ir::AstNodeType::TS_INTERFACE_DECLARATION:
984 return true;
985 case ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION:
986 return node->AsTSTypeAliasDeclaration()->Declare();
987 default:
988 break;
989 }
990 return false;
991 }
992
GetVariablesFromTSQualifiedNodes(const binder::Variable * variable,ArenaDeque<const ir::Identifier * > & identifiers,ArenaVector<const binder::Variable * > & variables) const993 void TypeExtractor::GetVariablesFromTSQualifiedNodes(const binder::Variable *variable,
994 ArenaDeque<const ir::Identifier *> &identifiers, ArenaVector<const binder::Variable *> &variables) const
995 {
996 ASSERT(variable != nullptr);
997
998 if (identifiers.empty()) {
999 variables.emplace_back(variable);
1000 return;
1001 }
1002 switch (variable->Type()) {
1003 case binder::VariableType::ENUMLITERAL: {
1004 auto name = identifiers.front()->Name();
1005 identifiers.pop_front();
1006 auto findRes = variable->AsEnumLiteralVariable()->FindEnumMemberVariable(name);
1007 if (findRes != nullptr) {
1008 GetVariablesFromTSQualifiedNodes(findRes, identifiers, variables);
1009 }
1010 break;
1011 }
1012 case binder::VariableType::NAMESPACE: {
1013 ArenaVector<binder::Variable *> findRes(recorder_->Allocator()->Adapter());
1014 GetVariablesFromNamespace(variable->AsNamespaceVariable(), findRes, identifiers, variables);
1015 identifiers.pop_front();
1016 for (const auto &v : findRes) {
1017 GetVariablesFromTSQualifiedNodes(v, identifiers, variables);
1018 }
1019 break;
1020 }
1021 case binder::VariableType::IMPORT_EQUALS: {
1022 auto ref = variable->Declaration()->Node()->Parent()->AsTSImportEqualsDeclaration()->ModuleReference();
1023 while (ref->IsTSQualifiedName()) {
1024 identifiers.emplace_front(ref->AsTSQualifiedName()->Right());
1025 ref = ref->AsTSQualifiedName()->Left();
1026 }
1027
1028 ASSERT(ref->IsIdentifier());
1029 for (const auto &v : ref->AsIdentifier()->TSVariables()) {
1030 if (v->Name() == ref->AsIdentifier()->Name()) {
1031 GetVariablesFromTSQualifiedNodes(v, identifiers, variables);
1032 }
1033 }
1034 break;
1035 }
1036 default:
1037 break;
1038 }
1039 }
1040
GetVariablesFromNamespace(const binder::NamespaceVariable * variable,ArenaVector<binder::Variable * > & findRes,ArenaDeque<const ir::Identifier * > & identifiers,ArenaVector<const binder::Variable * > & variables) const1041 void TypeExtractor::GetVariablesFromNamespace(const binder::NamespaceVariable *variable,
1042 ArenaVector<binder::Variable *> &findRes, ArenaDeque<const ir::Identifier *> &identifiers,
1043 ArenaVector<const binder::Variable *> &variables) const
1044 {
1045 ASSERT(variable->IsNamespaceVariable());
1046 auto exportBindings = variable->GetExportBindings();
1047 if (!exportBindings) {
1048 return;
1049 }
1050 auto fn = [&findRes](binder::Variable *variable) {
1051 if (variable != nullptr) {
1052 findRes.emplace_back(variable);
1053 }
1054 };
1055 auto name = identifiers.front()->Name();
1056 if (identifiers.size() == 1U) {
1057 fn(exportBindings->FindExportVariable(name));
1058 if (findRes.empty()) {
1059 fn(exportBindings->FindExportVariable(util::StringView(binder::TSBinding::ToTSBinding(name))));
1060 }
1061 } else {
1062 fn(exportBindings->FindExportTSVariable<binder::TSBindingType::NAMESPACE>(name));
1063 }
1064 fn(exportBindings->FindExportTSVariable<binder::TSBindingType::ENUMLITERAL>(name));
1065 fn(exportBindings->FindExportTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name));
1066 }
1067
1068 // static
GetBuiltinTypeIndex(util::StringView name)1069 int64_t TypeExtractor::GetBuiltinTypeIndex(util::StringView name)
1070 {
1071 auto t = BUILTIN_TYPE_MAP.find(std::string(name));
1072 if (t != BUILTIN_TYPE_MAP.end()) {
1073 return t->second;
1074 }
1075 return PrimitiveType::ANY;
1076 }
1077
1078 } // namespace panda::es2panda::extractor
1079