• 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/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 &regularImportEntries = 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