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