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 ®ularImportEntries = 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