• 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 #ifndef ES2PANDA_TYPESCRIPT_EXACTOR_TYPESYSTEM_H
17 #define ES2PANDA_TYPESCRIPT_EXACTOR_TYPESYSTEM_H
18 
19 #include <cstdint>
20 
21 #include <binder/variable.h>
22 #include <compiler/base/literals.h>
23 #include <ir/astDump.h>
24 #include <ir/astNode.h>
25 #include <ir/base/classDefinition.h>
26 #include <ir/base/classProperty.h>
27 #include <ir/base/methodDefinition.h>
28 #include <ir/base/scriptFunction.h>
29 #include <ir/expressions/arrowFunctionExpression.h>
30 #include <ir/expressions/assignmentExpression.h>
31 #include <ir/expressions/functionExpression.h>
32 #include <ir/expressions/identifier.h>
33 #include <ir/expressions/literals/numberLiteral.h>
34 #include <ir/expressions/literals/stringLiteral.h>
35 #include <ir/statements/classDeclaration.h>
36 #include <ir/statements/functionDeclaration.h>
37 #include <ir/ts/tsArrayType.h>
38 #include <ir/ts/tsClassImplements.h>
39 #include <ir/ts/tsConstructorType.h>
40 #include <ir/ts/tsFunctionType.h>
41 #include <ir/ts/tsIndexSignature.h>
42 #include <ir/ts/tsInterfaceBody.h>
43 #include <ir/ts/tsInterfaceDeclaration.h>
44 #include <ir/ts/tsInterfaceHeritage.h>
45 #include <ir/ts/tsMethodSignature.h>
46 #include <ir/ts/tsParameterProperty.h>
47 #include <ir/ts/tsPrivateIdentifier.h>
48 #include <ir/ts/tsPropertySignature.h>
49 #include <ir/ts/tsSignatureDeclaration.h>
50 #include <ir/ts/tsTypeLiteral.h>
51 #include <ir/ts/tsTypeParameter.h>
52 #include <ir/ts/tsTypeParameterDeclaration.h>
53 #include <ir/ts/tsUnionType.h>
54 
55 namespace panda::es2panda::extractor {
56 
57 enum PrimitiveType : uint8_t {
58     ANY = 0,
59     NUMBER,
60     BOOLEAN,
61     VOID,
62     STRING,
63     SYMBOL,
64     NUL,
65     UNDEFINED,
66     INT,
67 };
68 
69 const std::unordered_map<ir::AstNodeType, PrimitiveType> PRIMITIVE_TYPE_MAP = {
70     {ir::AstNodeType::TS_ANY_KEYWORD, PrimitiveType::ANY},
71     {ir::AstNodeType::TS_NUMBER_KEYWORD, PrimitiveType::NUMBER},
72     {ir::AstNodeType::TS_BOOLEAN_KEYWORD, PrimitiveType::BOOLEAN},
73     {ir::AstNodeType::TS_VOID_KEYWORD, PrimitiveType::VOID},
74     {ir::AstNodeType::TS_STRING_KEYWORD, PrimitiveType::STRING},
75     {ir::AstNodeType::TS_SYMBOL_KEYWORD, PrimitiveType::SYMBOL},
76     {ir::AstNodeType::TS_NULL_KEYWORD, PrimitiveType::NUL},
77     {ir::AstNodeType::TS_UNDEFINED_KEYWORD, PrimitiveType::UNDEFINED},
78     // Placeholder for Type Inference INT
79 };
80 
81 enum BuiltinType : uint8_t {
82     BT_HEAD = 20,
83     BT_FUNCTION,
84     BT_RANGEERROR,
85     BT_ERROR,
86     BT_OBJECT,
87     BT_SYNTAXERROR,
88     BT_TYPEERROR,
89     BT_REFERENCEERROR,
90     BT_URIERROR,
91     BT_SYMBOL,
92     BT_EVALERROR,
93     BT_NUMBER,
94     BT_PARSEFLOAT,
95     BT_DATE,
96     BT_BOOLEAN,
97     BT_BIGINT,
98     BT_PARSEINT,
99     BT_WEAKMAP,
100     BT_REGEXP,
101     BT_SET,
102     BT_MAP,
103     BT_WEAKREF,
104     BT_WEAKSET,
105     BT_FINALIZATIONREGISTRY,
106     BT_ARRAY,
107     BT_UINT8CLAMPEDARRAY,
108     BT_UINT8ARRAY,
109     BT_TYPEDARRAY,
110     BT_INT8ARRAY,
111     BT_UINT16ARRAY,
112     BT_UINT32ARRAY,
113     BT_INT16ARRAY,
114     BT_INT32ARRAY,
115     BT_FLOAT32ARRAY,
116     BT_FLOAT64ARRAY,
117     BT_BIGINT64ARRAY,
118     BT_BIGUINT64ARRAY,
119     BT_SHAREDARRAYBUFFER,
120     BT_DATAVIEW,
121     BT_STRING,
122     BT_ARRAYBUFFER,
123     BT_EVAL,
124     BT_ISFINITE,
125     BT_ARKPRIVATE,
126     BT_PRINT,
127     BT_DECODEURI,
128     BT_DECODEURICOMPONENT,
129     BT_ISNAN,
130     BT_ENCODEURI,
131     BT_NAN,
132     BT_GLOBALTHIS,
133     BT_ENCODEURICOMPONENT,
134     BT_INFINITY,
135     BT_MATH,
136     BT_JSON,
137     BT_ATOMICS,
138     BT_UNDEFINED,
139     BT_REFLECT,
140     BT_PROMISE,
141     BT_PROXY,
142     BT_GENERATORFUNCTION,
143     BT_INTL,
144 };
145 
146 const std::unordered_map<std::string, BuiltinType> BUILTIN_TYPE_MAP = {
147     {"Function", BuiltinType::BT_FUNCTION},
148     {"RangeError", BuiltinType::BT_RANGEERROR},
149     {"Error", BuiltinType::BT_ERROR},
150     {"Object", BuiltinType::BT_OBJECT},
151     {"SyntaxError", BuiltinType::BT_SYNTAXERROR},
152     {"TypeError", BuiltinType::BT_TYPEERROR},
153     {"ReferenceError", BuiltinType::BT_REFERENCEERROR},
154     {"URIError", BuiltinType::BT_URIERROR},
155     {"Symbol", BuiltinType::BT_SYMBOL},
156     {"EvalError", BuiltinType::BT_EVALERROR},
157     {"Number", BuiltinType::BT_NUMBER},
158     {"parseFloat", BuiltinType::BT_PARSEFLOAT},
159     {"Date", BuiltinType::BT_DATE},
160     {"Boolean", BuiltinType::BT_BOOLEAN},
161     {"BigInt", BuiltinType::BT_BIGINT},
162     {"parseInt", BuiltinType::BT_PARSEINT},
163     {"WeakMap", BuiltinType::BT_WEAKMAP},
164     {"RegExp", BuiltinType::BT_REGEXP},
165     {"Set", BuiltinType::BT_SET},
166     {"Map", BuiltinType::BT_MAP},
167     {"WeakRef", BuiltinType::BT_WEAKREF},
168     {"WeakSet", BuiltinType::BT_WEAKSET},
169     {"FinalizationRegistry", BuiltinType::BT_FINALIZATIONREGISTRY},
170     {"Array", BuiltinType::BT_ARRAY},
171     {"Uint8ClampedArray", BuiltinType::BT_UINT8CLAMPEDARRAY},
172     {"Uint8Array", BuiltinType::BT_UINT8ARRAY},
173     {"TypedArray", BuiltinType::BT_TYPEDARRAY},
174     {"Int8Array", BuiltinType::BT_INT8ARRAY},
175     {"Uint16Array", BuiltinType::BT_UINT16ARRAY},
176     {"Uint32Array", BuiltinType::BT_UINT32ARRAY},
177     {"Int16Array", BuiltinType::BT_INT16ARRAY},
178     {"Int32Array", BuiltinType::BT_INT32ARRAY},
179     {"Float32Array", BuiltinType::BT_FLOAT32ARRAY},
180     {"Float64Array", BuiltinType::BT_FLOAT64ARRAY},
181     {"BigInt64Array", BuiltinType::BT_BIGINT64ARRAY},
182     {"BigUint64Array", BuiltinType::BT_BIGUINT64ARRAY},
183     {"SharedArrayBuffer", BuiltinType::BT_SHAREDARRAYBUFFER},
184     {"DataView", BuiltinType::BT_DATAVIEW},
185     {"String", BuiltinType::BT_STRING},
186     {"ArrayBuffer", BuiltinType::BT_ARRAYBUFFER},
187     {"eval", BuiltinType::BT_EVAL},
188     {"isFinite", BuiltinType::BT_ISFINITE},
189     {"ArkPrivate", BuiltinType::BT_ARKPRIVATE},
190     {"print", BuiltinType::BT_PRINT},
191     {"decodeURI", BuiltinType::BT_DECODEURI},
192     {"decodeURIComponent", BuiltinType::BT_DECODEURICOMPONENT},
193     {"isNaN", BuiltinType::BT_ISNAN},
194     {"encodeURI", BuiltinType::BT_ENCODEURI},
195     {"NaN", BuiltinType::BT_NAN},
196     {"globalThis", BuiltinType::BT_GLOBALTHIS},
197     {"encodeURIComponent", BuiltinType::BT_ENCODEURICOMPONENT},
198     {"Infinity", BuiltinType::BT_INFINITY},
199     {"Math", BuiltinType::BT_MATH},
200     {"JSON", BuiltinType::BT_JSON},
201     {"Atomics", BuiltinType::BT_ATOMICS},
202     {"undefined", BuiltinType::BT_UNDEFINED},
203     {"Reflect", BuiltinType::BT_REFLECT},
204     {"Promise", BuiltinType::BT_PROMISE},
205     {"Proxy", BuiltinType::BT_PROXY},
206     {"GeneratorFunction", BuiltinType::BT_GENERATORFUNCTION},
207     {"Intl", BuiltinType::BT_INTL},
208 };
209 
210 enum UserType : uint8_t {
211     COUNTER,
212     CLASS,
213     CLASSINST,
214     FUNCTION,
215     UNION,
216     ARRAY,
217     OBJECT,
218     EXTERNAL,
219     INTERFACE,
220     BUILTININST,
221     GENERICINST,
222     INDEXSIG
223 };
224 
225 enum BuiltinFlag : int8_t {
226     NAMESPACE_FUNCTION = -1,
227     ENUM_FUNCTION = -2
228 };
229 
230 enum FuncModifier : uint8_t {
231     NOMODIFIER = 0,
232     STATIC = 1 << 2,
233     ASYNC = 1 << 3,
234     GENERATOR = 1 << 4,
235     ACCESSOR = 1 << 5,
236     ABSTRACT = 1 << 6,
237     OVERLOAD = 1 << 7
238 };
239 
240 enum AccessFlag : uint8_t {
241     PUBLIC,
242     PRIVATE,
243     PROTECTED
244 };
245 
246 class BaseType {
247 public:
BaseType(TypeExtractor * extractor)248     explicit BaseType(TypeExtractor *extractor)
249         : extractor_(extractor), recorder_(extractor_->Recorder()), buffer_(recorder_->NewLiteralBuffer())
250     {
251     }
252     ~BaseType() = default;
253     NO_COPY_SEMANTIC(BaseType);
254     NO_MOVE_SEMANTIC(BaseType);
255 
256 protected:
257     TypeExtractor *extractor_;
258     TypeRecorder *recorder_;
259     compiler::LiteralBuffer *buffer_;
260 
FillTypeIndexLiteralBuffer(int64_t typeIndex)261     void FillTypeIndexLiteralBuffer(int64_t typeIndex)
262     {
263         if (typeIndex >= recorder_->GetUserTypeIndexShift()) {
264             std::stringstream ss;
265             ss << std::string(recorder_->GetRecordName()) << "_" << (typeIndex - recorder_->GetUserTypeIndexShift());
266             buffer_->Add(recorder_->Allocator()->New<ir::UserTypeIndexLiteral>(typeIndex,
267                 util::UString(ss.str(), recorder_->Allocator()).View()));
268         } else if (typeIndex >= PrimitiveType::ANY) {
269             buffer_->Add(recorder_->Allocator()->New<ir::BuiltinTypeIndexLiteral>(typeIndex));
270         } else {
271             buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(typeIndex));
272         }
273     }
274 
CalculateIndex(const util::StringView & name,int64_t & typeIndex,int64_t & typeIndexShift,bool forBuiltin)275     void CalculateIndex(const util::StringView &name, int64_t &typeIndex, int64_t &typeIndexShift, bool forBuiltin)
276     {
277         if (forBuiltin && extractor_->GetTypeDtsBuiltin()) {
278             auto t = BUILTIN_TYPE_MAP.find(std::string(name));
279             if (t != BUILTIN_TYPE_MAP.end()) {
280                 typeIndexShift = t->second;
281                 typeIndex = typeIndexShift - BuiltinType::BT_HEAD;
282             }
283         }
284 
285         if (typeIndex == PrimitiveType::ANY) {
286             typeIndex = recorder_->AddLiteralBuffer(buffer_);
287             typeIndexShift = typeIndex + recorder_->GetUserTypeIndexShift();
288         } else {
289             recorder_->SetLiteralBuffer(typeIndex, buffer_);
290         }
291     }
292 
CalculateName(const ir::Expression * expression)293     std::variant<util::StringView, const ir::Identifier *> CalculateName(const ir::Expression *expression)
294     {
295         if (expression->IsLiteral()) {
296             auto name = expression->AsLiteral()->GetName();
297             if (name.has_value()) {
298                 return name.value();
299             }
300             return nullptr;
301         } else {
302             return extractor_->GetIdentifierFromExpression(expression);
303         }
304     }
305 
CalculateStr(const ArenaVector<ir::Expression * > & expressions)306     std::string CalculateStr(const ArenaVector<ir::Expression *> &expressions)
307     {
308         std::vector<std::string> tmp;
309         for (const auto &t : expressions) {
310             ir::AstDumper dumper(t);
311             tmp.emplace_back(dumper.Str());
312         }
313         std::sort(tmp.begin(), tmp.end());
314 
315         std::stringstream ss;
316         for (const auto &t : tmp) {
317             ss << t;
318         }
319         return ss.str();
320     }
321 
CalculateParamTypes(ArenaMap<util::StringView,int64_t> & paramTypes,const ir::TSTypeParameterDeclaration * typeParams)322     void CalculateParamTypes(ArenaMap<util::StringView, int64_t> &paramTypes,
323         const ir::TSTypeParameterDeclaration *typeParams)
324     {
325         int64_t index = 0;
326         for (const auto &t : typeParams->Params()) {
327             paramTypes[t->Name()->Name()] = (--index);
328         }
329     }
330 };
331 
332 class TypeCounter : public BaseType {
333 public:
TypeCounter(TypeExtractor * extractor)334     explicit TypeCounter(TypeExtractor *extractor) : BaseType(extractor)
335     {
336         typeIndexPlaceHolder_ = recorder_->AddLiteralBuffer(buffer_);
337         if (extractor_->GetTypeDtsExtractor()) {
338             // Make builtin type slots
339             for (int64_t i = 0; i < TypeRecorder::USERTYPEINDEXHEAD - BuiltinType::BT_HEAD; i++) {
340                 auto buffer = recorder_->NewLiteralBuffer();
341                 (void)recorder_->AddLiteralBuffer(buffer);
342             }
343             recorder_->SetUserTypeIndexShift(BuiltinType::BT_HEAD);
344         }
345     }
346     ~TypeCounter() = default;
347     NO_COPY_SEMANTIC(TypeCounter);
348     NO_MOVE_SEMANTIC(TypeCounter);
349 
GetTypeIndexPlaceHolder()350     int64_t GetTypeIndexPlaceHolder() const
351     {
352         return typeIndexPlaceHolder_;
353     }
354 
FillLiteralBuffer()355     void FillLiteralBuffer()
356     {
357         const auto &userType = recorder_->GetUserType();
358         if (extractor_->GetTypeDtsExtractor()) {
359             buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(userType.size() +
360                 TypeRecorder::USERTYPEINDEXHEAD - BuiltinType::BT_HEAD));
361             for (int builtinTypeOrder = BuiltinType::BT_HEAD; builtinTypeOrder < TypeRecorder::USERTYPEINDEXHEAD;
362                  builtinTypeOrder++) {
363                 FillTypeIndexLiteralBuffer(builtinTypeOrder + 1);
364             }
365         } else {
366             buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(userType.size()));
367         }
368         std::for_each(userType.begin(), userType.end(), [this](const auto &t) {
369             FillTypeIndexLiteralBuffer(t);
370         });
371         const auto &anonymousReExport = recorder_->GetAnonymousReExport();
372         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(anonymousReExport.size()));
373         std::for_each(anonymousReExport.begin(), anonymousReExport.end(), [this](const auto &t) {
374             buffer_->Add(recorder_->Allocator()->New<ir::StringLiteral>(t));
375         });
376         recorder_->SetLiteralBuffer(typeIndexPlaceHolder_, buffer_);
377     }
378 
379 private:
380     int64_t typeIndexPlaceHolder_ = PrimitiveType::ANY;
381 };
382 
383 class IndexSigType : public BaseType {
384 public:
IndexSigType(TypeExtractor * extractor,int64_t typeIndexRefShift,const ArenaMap<int64_t,int64_t> * indexSignatures)385     explicit IndexSigType(TypeExtractor *extractor, int64_t typeIndexRefShift,
386         const ArenaMap<int64_t, int64_t> *indexSignatures)
387         : BaseType(extractor), typeIndexRefShift_(typeIndexRefShift)
388     {
389         typeIndex_ = recorder_->AddLiteralBuffer(buffer_);
390         typeIndexShift_ = typeIndex_ + recorder_->GetUserTypeIndexShift();
391         recorder_->SetIndexSig(typeIndexRefShift_, typeIndexShift_);
392         recorder_->AddUserType(typeIndexShift_);
393 
394         FillLiteralBuffer(indexSignatures);
395     }
396     ~IndexSigType() = default;
397     NO_COPY_SEMANTIC(IndexSigType);
398     NO_MOVE_SEMANTIC(IndexSigType);
399 
GetTypeIndexShift()400     int64_t GetTypeIndexShift() const
401     {
402         return typeIndexShift_;
403     }
404 
405 private:
406     int64_t typeIndexRefShift_ = PrimitiveType::ANY;
407     int64_t typeIndex_ = PrimitiveType::ANY;
408     int64_t typeIndexShift_ = PrimitiveType::ANY;
409 
FillLiteralBuffer(const ArenaMap<int64_t,int64_t> * indexSignatures)410     void FillLiteralBuffer(const ArenaMap<int64_t, int64_t> *indexSignatures)
411     {
412         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(UserType::INDEXSIG));
413         FillTypeIndexLiteralBuffer(typeIndexRefShift_);
414 
415         ASSERT(indexSignatures != nullptr);
416         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(indexSignatures->size()));
417         std::for_each(indexSignatures->begin(), indexSignatures->end(), [this](const auto &t) {
418             FillTypeIndexLiteralBuffer(t.first);
419             FillTypeIndexLiteralBuffer(t.second);
420         });
421     }
422 };
423 
424 // 8 types of AstNode to create FunctionType
425 // For { MethodDefinition / FunctionDeclaration / FunctionExpression / ArrowFunctionExpression }
426 // which contains ScriptFunction
427 // For { TSMethodSignature / TSSignatureDeclaration / TSFunctionType / TSConstructorType }
428 // which only contains Signature
429 class FunctionType : public BaseType {
430 public:
FunctionType(TypeExtractor * extractor,const ir::AstNode * node,const util::StringView & name)431     explicit FunctionType(TypeExtractor *extractor, const ir::AstNode *node, const util::StringView &name)
432         : BaseType(extractor), paramsTypeIndex_(recorder_->Allocator()->Adapter())
433     {
434         name_ = name;
435 
436         auto fn = [this](const auto *func) {
437             typeIndexShift_ = recorder_->GetNodeTypeIndex(func);
438             if (typeIndexShift_ != PrimitiveType::ANY) {
439                 return;
440             }
441 
442             CalculateIndex(name_, typeIndex_, typeIndexShift_, !(func->IsTSMethodSignature()));
443             recorder_->SetNodeTypeIndex(func, typeIndexShift_);
444             recorder_->AddUserType(typeIndexShift_);
445             if constexpr (std::is_same_v<decltype(func), const ir::ScriptFunction *>) {
446                 if (name_.Is("")) {
447                     name_ = recorder_->GetAnonymousFunctionNames(func);
448                 }
449                 FillModifier(func);
450                 if (func->ThisParams() != nullptr) {
451                     auto identifier = func->ThisParams()->AsIdentifier();
452                     paramsTypeIndex_.emplace_back(extractor_->GetTypeIndexFromIdentifier(identifier));
453                     containThis_ = true;
454                 }
455             }
456             FillParameters(func);
457             FillReturn(func);
458             FillLiteralBuffer();
459         };
460 
461         if (node->IsMethodDefinition()) {
462             auto methodDef = node->AsMethodDefinition();
463             auto modifiers = methodDef->Modifiers();
464             if (modifiers & ir::ModifierFlags::PRIVATE) {
465                 accessFlag_ = AccessFlag::PRIVATE;
466             }
467             if (modifiers & ir::ModifierFlags::PROTECTED) {
468                 accessFlag_ = AccessFlag::PROTECTED;
469             }
470             FillMethodModifier(methodDef);
471             fn(methodDef->Function());
472         } else if (node->IsFunctionDeclaration()) {
473             fn(node->AsFunctionDeclaration()->Function());
474         } else if (node->IsFunctionExpression()) {
475             fn(node->AsFunctionExpression()->Function());
476         } else if (node->IsArrowFunctionExpression()) {
477             fn(node->AsArrowFunctionExpression()->Function());
478         } else if (node->IsTSMethodSignature()) {
479             fn(node->AsTSMethodSignature());
480         } else if (node->IsTSSignatureDeclaration() || node->IsTSFunctionType() || node->IsTSConstructorType()) {
481             HandleFuncNodeWithoutName(node);
482         }
483     }
484     ~FunctionType() = default;
485     NO_COPY_SEMANTIC(FunctionType);
486     NO_MOVE_SEMANTIC(FunctionType);
487 
GetModifier()488     uint8_t GetModifier() const
489     {
490         return modifier_;
491     }
492 
GetTypeIndexShift()493     int64_t GetTypeIndexShift() const
494     {
495         return typeIndexShift_;
496     }
497 
498 private:
499     util::StringView name_ {};
500     AccessFlag accessFlag_ = AccessFlag::PUBLIC;
501     uint8_t modifier_ = FuncModifier::NOMODIFIER;
502     bool containThis_ = false;
503     ArenaVector<int64_t> paramsTypeIndex_;
504     int64_t typeIndexReturn_ = PrimitiveType::ANY;
505     int64_t typeIndex_ = PrimitiveType::ANY;
506     int64_t typeIndexShift_ = PrimitiveType::ANY;
507 
HandleFuncNodeWithoutName(const ir::AstNode * node)508     void HandleFuncNodeWithoutName(const ir::AstNode *node)
509     {
510         ir::AstDumper dumper(node);
511         auto functionStr = dumper.Str();
512         typeIndexShift_ = recorder_->GetFunctionType(functionStr);
513         if (typeIndexShift_ != PrimitiveType::ANY) {
514             return;
515         }
516 
517         typeIndex_ = recorder_->AddLiteralBuffer(buffer_);
518         typeIndexShift_ = typeIndex_ + recorder_->GetUserTypeIndexShift();
519         recorder_->SetFunctionType(functionStr, typeIndexShift_);
520         recorder_->AddUserType(typeIndexShift_);
521 
522         if (node->IsTSSignatureDeclaration()) {
523             FillParameters(node->AsTSSignatureDeclaration());
524             FillReturn(node->AsTSSignatureDeclaration());
525         } else if (node->IsTSFunctionType()) {
526             FillParameters(node->AsTSFunctionType());
527             FillReturn(node->AsTSFunctionType());
528         } else {
529             FillParameters(node->AsTSConstructorType());
530             FillReturn(node->AsTSConstructorType());
531         }
532         FillLiteralBuffer();
533     }
534 
FillMethodModifier(const ir::MethodDefinition * methodDef)535     void FillMethodModifier(const ir::MethodDefinition *methodDef)
536     {
537         if (methodDef->IsStatic()) {
538             modifier_ += FuncModifier::STATIC;
539         }
540         if (methodDef->IsAccessor()) {
541             modifier_ += FuncModifier::ACCESSOR;
542         }
543         if (methodDef->IsAbstract()) {
544             modifier_ += FuncModifier::ABSTRACT;
545         }
546     }
547 
FillModifier(const ir::ScriptFunction * scriptFunc)548     void FillModifier(const ir::ScriptFunction *scriptFunc)
549     {
550         if (scriptFunc->IsAsync()) {
551             modifier_ += FuncModifier::ASYNC;
552         }
553         if (scriptFunc->IsGenerator()) {
554             modifier_ += FuncModifier::GENERATOR;
555         }
556         if (scriptFunc->IsOverload()) {
557             modifier_ += FuncModifier::OVERLOAD;
558         }
559     }
560 
561     template <typename T>
FillParameters(const T * func)562     void FillParameters(const T *func)
563     {
564         for (const auto &t : func->Params()) {
565             auto param = t;
566             if (t->IsTSParameterProperty()) {
567                 param = t->AsTSParameterProperty()->Parameter();
568             }
569             if (param->IsAssignmentExpression()) {
570                 param = param->AsAssignmentExpression()->Left();
571             }
572             if (param->IsAssignmentPattern()) {
573                 param = param->AsAssignmentPattern()->Left();
574             }
575 
576             // Identifier / SpreadElement / RestElement / ArrayExpression / ObjectExpression
577             auto identifier = extractor_->GetIdentifierFromExpression(param);
578             if (identifier != nullptr) {
579                 if (identifier->Name().Is("this") && paramsTypeIndex_.size() == 0) {
580                     containThis_ = true;
581                 }
582                 paramsTypeIndex_.emplace_back(extractor_->GetTypeIndexFromIdentifier(identifier));
583             } else {
584                 paramsTypeIndex_.emplace_back(PrimitiveType::ANY);
585             }
586         }
587     }
588 
589     template <typename T>
FillReturn(const T * func)590     void FillReturn(const T *func)
591     {
592         typeIndexReturn_ = extractor_->GetTypeIndexFromAnnotation(func->ReturnTypeAnnotation());
593     }
594 
FillLiteralBuffer()595     void FillLiteralBuffer()
596     {
597         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(UserType::FUNCTION));
598         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(accessFlag_ + modifier_));
599         buffer_->Add(recorder_->Allocator()->New<ir::StringLiteral>(name_));
600         if (containThis_) {
601             buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(1));
602             FillTypeIndexLiteralBuffer(paramsTypeIndex_.at(0));
603             buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(paramsTypeIndex_.size() - 1));
604             for (size_t i = 1; i < paramsTypeIndex_.size(); i++) {
605                 FillTypeIndexLiteralBuffer(paramsTypeIndex_.at(i));
606             }
607         } else {
608             buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(0));
609             buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(paramsTypeIndex_.size()));
610             for (size_t i = 0; i < paramsTypeIndex_.size(); i++) {
611                 FillTypeIndexLiteralBuffer(paramsTypeIndex_.at(i));
612             }
613         }
614         FillTypeIndexLiteralBuffer(typeIndexReturn_);
615     }
616 };
617 
618 // 2 types of AstNode to create ClassType
619 // For { ClassDeclaration / ClassExpression }
620 // which contains ClassDefinition
621 class ClassType : public BaseType {
622 public:
ClassType(TypeExtractor * extractor,const ir::ClassDefinition * classDef,const util::StringView & name)623     explicit ClassType(TypeExtractor *extractor, const ir::ClassDefinition *classDef, const util::StringView &name)
624         : BaseType(extractor),
625           implementsHeritages_(recorder_->Allocator()->Adapter()),
626           paramTypes_(recorder_->Allocator()->Adapter()),
627           staticFields_(recorder_->Allocator()->Adapter()),
628           staticMethods_(recorder_->Allocator()->Adapter()),
629           fields_(recorder_->Allocator()->Adapter()),
630           methods_(recorder_->Allocator()->Adapter()),
631           indexSignatures_(recorder_->Allocator()->Adapter())
632     {
633         typeIndexShift_ = recorder_->GetNodeTypeIndex(classDef);
634         if (typeIndexShift_ != PrimitiveType::ANY) {
635             return;
636         }
637 
638         if (classDef->TypeParams() != nullptr) {
639             CalculateParamTypes(paramTypes_, classDef->TypeParams());
640         }
641 
642         CalculateIndex(name, typeIndex_, typeIndexShift_, true);
643         recorder_->SetNodeTypeIndex(classDef, typeIndexShift_);
644         recorder_->AddUserType(typeIndexShift_);
645 
646         GenericParamTypeBindScope scope(extractor, &paramTypes_);
647         FillModifier(classDef);
648         FillHeritages(classDef);
649         FillFieldsandMethods(classDef);
650         FillIndexSignatures(classDef);
651         FillLiteralBuffer();
652     }
653     ~ClassType() = default;
654     NO_COPY_SEMANTIC(ClassType);
655     NO_MOVE_SEMANTIC(ClassType);
656 
GetTypeIndexShift()657     int64_t GetTypeIndexShift() const
658     {
659         return typeIndexShift_;
660     }
661 
662 private:
663     bool modifierAB_ = false;
664     int64_t extendsHeritage_ = PrimitiveType::ANY;
665     ArenaVector<int64_t> implementsHeritages_;
666     ArenaMap<util::StringView, int64_t> paramTypes_;
667     // 3 field infos, typeIndex / accessFlag / modifier
668     ArenaMap<util::StringView, std::array<int64_t, 3>> staticFields_;
669     ArenaMap<int64_t, util::StringView> staticMethods_;
670     // 3 field infos, typeIndex / accessFlag / modifier
671     ArenaMap<util::StringView, std::array<int64_t, 3>> fields_;
672     ArenaMap<int64_t, util::StringView> methods_;
673     ArenaMap<int64_t, int64_t> indexSignatures_;
674     int64_t typeIndex_ = PrimitiveType::ANY;
675     int64_t typeIndexShift_ = PrimitiveType::ANY;
676 
677     size_t fieldsWithInitNum_ = 0U;
678     size_t methodsWithBodyNum_ = 0U;
679 
FillModifier(const ir::ClassDefinition * classDef)680     void FillModifier(const ir::ClassDefinition *classDef)
681     {
682         modifierAB_ = classDef->Abstract();
683     }
684 
FillHeritages(const ir::ClassDefinition * classDef)685     void FillHeritages(const ir::ClassDefinition *classDef)
686     {
687         auto super = classDef->Super();
688         if (super != nullptr) {
689             extendsHeritage_ = extractor_->GetTypeIndexFromInitializer(super);
690         }
691 
692         for (const auto &t : classDef->Implements()) {
693             if (t != nullptr) {
694                 implementsHeritages_.emplace_back(extractor_->GetTypeIndexFromInitializer(t));
695             }
696         }
697     }
698 
FillField(const ir::ClassProperty * field)699     void FillField(const ir::ClassProperty *field)
700     {
701         auto modifiers = field->Modifiers();
702         bool isStatic = (modifiers & ir::ModifierFlags::STATIC);
703         AccessFlag flag = AccessFlag::PUBLIC;
704         if (modifiers & ir::ModifierFlags::PRIVATE) {
705             flag = AccessFlag::PRIVATE;
706         }
707         if (modifiers & ir::ModifierFlags::PROTECTED) {
708             flag = AccessFlag::PROTECTED;
709         }
710         auto isReadonly = (modifiers & ir::ModifierFlags::READONLY);
711 
712         int64_t typeIndex = extractor_->GetTypeIndexFromAnnotation(field->TypeAnnotation());
713         if (typeIndex == PrimitiveType::ANY && field->Value() != nullptr) {
714             typeIndex = extractor_->GetTypeIndexFromInitializer(field->Value());
715         }
716 
717         // 3 field infos, typeIndex / accessFlag / modifier
718         std::array<int64_t, 3> fieldInfo = {typeIndex, flag, static_cast<int64_t>(isReadonly)};
719         auto fn = [&fieldInfo, &isStatic, this](const util::StringView &name) {
720             if (isStatic) {
721                 staticFields_[name] = fieldInfo;
722             } else {
723                 fields_[name] = fieldInfo;
724             }
725         };
726 
727         const ir::Expression *expression;
728         if (field->Key()->IsTSPrivateIdentifier()) {
729             expression = field->Key()->AsTSPrivateIdentifier()->Key();
730         } else {
731             expression = field->Key();
732         }
733         auto res = CalculateName(expression);
734         if (std::holds_alternative<util::StringView>(res)) {
735             fn(std::get<util::StringView>(res));
736         } else {
737             auto identifier = std::get<const ir::Identifier *>(res);
738             if (identifier != nullptr) {
739                 recorder_->SetIdentifierTypeIndex(identifier, typeIndex);
740                 fn(identifier->Name());
741             }
742         }
743 
744         if (field->Value() != nullptr) {
745             fieldsWithInitNum_++;
746         }
747     }
748 
FillMethod(const ir::MethodDefinition * method)749     void FillMethod(const ir::MethodDefinition *method)
750     {
751         auto fn = [&method, this](const FunctionType &functionType, const util::StringView &name) {
752             if ((functionType.GetModifier() & FuncModifier::STATIC) == 0) {
753                 methods_[recorder_->GetNodeTypeIndex(method->Function())] = name;
754             } else {
755                 staticMethods_ [recorder_->GetNodeTypeIndex(method->Function())] = name;
756             }
757         };
758 
759         auto res = CalculateName(method->Key());
760         if (std::holds_alternative<util::StringView>(res)) {
761             auto name = std::get<util::StringView>(res);
762             FunctionType functionType(extractor_, method, name);
763             fn(functionType, name);
764         } else {
765             auto identifier = std::get<const ir::Identifier *>(res);
766             if (identifier != nullptr) {
767                 auto name = identifier->Name();
768                 FunctionType functionType(extractor_, method, name);
769                 recorder_->SetIdentifierTypeIndex(identifier, functionType.GetTypeIndexShift());
770                 fn(functionType, name);
771             }
772         }
773 
774         if (method->Function()->Body() != nullptr) {
775             methodsWithBodyNum_++;
776         }
777     }
778 
FillFieldsandMethods(const ir::ClassDefinition * classDef)779     void FillFieldsandMethods(const ir::ClassDefinition *classDef)
780     {
781         auto methodDef = const_cast<ir::ClassDefinition *>(classDef)->Ctor();
782         ASSERT(methodDef->IsMethodDefinition());
783         // Filter Implicit Constructor
784         const auto &range = methodDef->Key()->Range();
785         if (!(range.start.index == range.end.index && range.start.line == range.end.line &&
786             range.start.index == range.start.line && range.end.index == range.end.line)) {
787             FillMethod(methodDef);
788         }
789 
790         for (const auto &t : classDef->Body()) {
791             if (t->IsClassProperty()) {
792                 FillField(t->AsClassProperty());
793             } else if (t->IsMethodDefinition()) {
794                 FillMethod(t->AsMethodDefinition());
795             }
796         }
797 
798         // Create class instance type stands for 'this'
799         if (!classDef->Abstract() && (fieldsWithInitNum_ > 0U || methodsWithBodyNum_ > 0U)) {
800             (void)extractor_->GetTypeIndexFromClassInst(typeIndexShift_, classDef);
801         }
802     }
803 
FillIndexSignatures(const ir::ClassDefinition * classDef)804     void FillIndexSignatures(const ir::ClassDefinition *classDef)
805     {
806         bool isAllIndexSignatureStatic = true;
807         for (const auto &t : classDef->IndexSignatures()) {
808             if (!t->Static()) {
809                 isAllIndexSignatureStatic = false;
810                 auto key = t->Param()->AsIdentifier()->TypeAnnotation();
811                 indexSignatures_[extractor_->GetTypeIndexFromAnnotation(key)] =
812                     extractor_->GetTypeIndexFromAnnotation(t->TypeAnnotation());
813             }
814         }
815         if (indexSignatures_.size() > 0U && !isAllIndexSignatureStatic) {
816             // Update current type to IndexSignture Type
817             IndexSigType indexSigType(extractor_, typeIndexShift_, &indexSignatures_);
818             typeIndexShift_ = indexSigType.GetTypeIndexShift();
819             recorder_->UpdateNodeTypeIndex(classDef, typeIndexShift_);
820         }
821     }
822 
FillFieldsLiteralBuffer(bool isStatic)823     void FillFieldsLiteralBuffer(bool isStatic)
824     {
825         // 3 field infos, typeIndex / accessFlag / modifier
826         auto fn = [this](const ArenaMap<util::StringView, std::array<int64_t, 3>> &map) {
827             buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(map.size()));
828             std::for_each(map.begin(), map.end(), [this](const auto &t) {
829                 buffer_->Add(recorder_->Allocator()->New<ir::StringLiteral>(t.first));
830                 FillTypeIndexLiteralBuffer(t.second[0]);  // 0. typeIndex
831                 buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(t.second[1]));  // 1. accessFlag
832                 buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(t.second[2]));  // 2. modifier
833             });
834         };
835 
836         if (isStatic) {
837             fn(staticFields_);
838         } else {
839             fn(fields_);
840         }
841     }
842 
FillMethodsLiteralBuffer(bool isStatic)843     void FillMethodsLiteralBuffer(bool isStatic)
844     {
845         auto fn = [this](const ArenaMap<int64_t, util::StringView> &map) {
846             buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(map.size()));
847             std::for_each(map.begin(), map.end(), [this](const auto &t) {
848                 buffer_->Add(recorder_->Allocator()->New<ir::StringLiteral>(t.second));
849                 FillTypeIndexLiteralBuffer(t.first);
850             });
851         };
852 
853         if (isStatic) {
854             fn(staticMethods_);
855         } else {
856             fn(methods_);
857         }
858     }
859 
FillLiteralBuffer()860     void FillLiteralBuffer()
861     {
862         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(UserType::CLASS));
863         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(modifierAB_));
864         FillTypeIndexLiteralBuffer(extendsHeritage_);
865         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(implementsHeritages_.size()));
866         std::for_each(implementsHeritages_.begin(), implementsHeritages_.end(), [this](const auto &t) {
867             FillTypeIndexLiteralBuffer(t);
868         });
869 
870         FillFieldsLiteralBuffer(false);
871         FillMethodsLiteralBuffer(false);
872         FillFieldsLiteralBuffer(true);
873         FillMethodsLiteralBuffer(true);
874     }
875 };
876 
877 class ClassInstType : public BaseType {
878 public:
ClassInstType(TypeExtractor * extractor,int64_t typeIndexRefShift)879     explicit ClassInstType(TypeExtractor *extractor, int64_t typeIndexRefShift)
880         : BaseType(extractor), typeIndexRefShift_(typeIndexRefShift)
881     {
882         typeIndex_ = recorder_->AddLiteralBuffer(buffer_);
883         typeIndexShift_ = typeIndex_ + recorder_->GetUserTypeIndexShift();
884         recorder_->SetClassInst(typeIndexRefShift_, typeIndexShift_);
885         recorder_->SetClassType(typeIndexShift_, typeIndexRefShift_);
886         recorder_->AddUserType(typeIndexShift_);
887 
888         FillLiteralBuffer();
889     }
890     ~ClassInstType() = default;
891     NO_COPY_SEMANTIC(ClassInstType);
892     NO_MOVE_SEMANTIC(ClassInstType);
893 
GetTypeIndexShift()894     int64_t GetTypeIndexShift() const
895     {
896         return typeIndexShift_;
897     }
898 
899 private:
900     int64_t typeIndexRefShift_ = PrimitiveType::ANY;
901     int64_t typeIndex_ = PrimitiveType::ANY;
902     int64_t typeIndexShift_ = PrimitiveType::ANY;
903 
FillLiteralBuffer()904     void FillLiteralBuffer()
905     {
906         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(UserType::CLASSINST));
907         FillTypeIndexLiteralBuffer(typeIndexRefShift_);
908     }
909 };
910 
911 class InterfaceType : public BaseType {
912 public:
InterfaceType(TypeExtractor * extractor,const ir::TSInterfaceDeclaration * interfaceDef,const util::StringView & name)913     explicit InterfaceType(TypeExtractor *extractor, const ir::TSInterfaceDeclaration *interfaceDef,
914                            const util::StringView &name)
915         : BaseType(extractor),
916           heritages_(recorder_->Allocator()->Adapter()),
917           paramTypes_(recorder_->Allocator()->Adapter()),
918           fields_(recorder_->Allocator()->Adapter()),
919           methods_(recorder_->Allocator()->Adapter()),
920           indexSignatures_(recorder_->Allocator()->Adapter())
921     {
922         typeIndexShift_ = recorder_->GetNodeTypeIndex(interfaceDef);
923         if (typeIndexShift_ != PrimitiveType::ANY) {
924             return;
925         }
926 
927         if (interfaceDef->TypeParams() != nullptr) {
928             CalculateParamTypes(paramTypes_, interfaceDef->TypeParams());
929         }
930 
931         CalculateIndex(name, typeIndex_, typeIndexShift_, true);
932         recorder_->SetNodeTypeIndex(interfaceDef, typeIndexShift_);
933         recorder_->AddUserType(typeIndexShift_);
934 
935         GenericParamTypeBindScope scope(extractor, &paramTypes_);
936         FillHeritages(interfaceDef);
937         FillMembers(interfaceDef);
938         FillLiteralBuffer();
939     }
940     ~InterfaceType() = default;
941     NO_COPY_SEMANTIC(InterfaceType);
942     NO_MOVE_SEMANTIC(InterfaceType);
943 
GetTypeIndexShift()944     int64_t GetTypeIndexShift() const
945     {
946         return typeIndexShift_;
947     }
948 
949 private:
950     ArenaVector<int64_t> heritages_;
951     ArenaMap<util::StringView, int64_t> paramTypes_;
952     // 3 field infos, typeIndex / accessFlag / modifier
953     ArenaMap<util::StringView, std::array<int64_t, 3>> fields_;
954     ArenaVector<int64_t> methods_;
955     ArenaMap<int64_t, int64_t> indexSignatures_;
956     int64_t typeIndex_ = PrimitiveType::ANY;
957     int64_t typeIndexShift_ = PrimitiveType::ANY;
958 
FillHeritages(const ir::TSInterfaceDeclaration * interfaceDef)959     void FillHeritages(const ir::TSInterfaceDeclaration *interfaceDef)
960     {
961         for (const auto &t : interfaceDef->Extends()) {
962             if (t != nullptr) {
963                 // TSTypeReference
964                 heritages_.emplace_back(extractor_->GetTypeIndexFromAnnotation(t->Expr(), false));
965             }
966         }
967     }
968 
FillField(const ir::TSPropertySignature * field)969     void FillField(const ir::TSPropertySignature *field)
970     {
971         AccessFlag flag = AccessFlag::PUBLIC;
972         auto isReadonly = field->Readonly();
973 
974         int64_t typeIndex = extractor_->GetTypeIndexFromAnnotation(field->TypeAnnotation());
975         // 3 field infos, typeIndex / accessFlag / modifier
976         std::array<int64_t, 3> fieldInfo = {typeIndex, flag, static_cast<int64_t>(isReadonly)};
977 
978         auto res = CalculateName(field->Key());
979         if (std::holds_alternative<util::StringView>(res)) {
980             fields_[std::get<util::StringView>(res)] = fieldInfo;
981         } else {
982             auto identifier = std::get<const ir::Identifier *>(res);
983             if (identifier != nullptr) {
984                 recorder_->SetIdentifierTypeIndex(identifier, typeIndex);
985                 fields_[identifier->Name()] = fieldInfo;
986             }
987         }
988     }
989 
FillMethod(const ir::TSMethodSignature * method)990     void FillMethod(const ir::TSMethodSignature *method)
991     {
992         auto res = CalculateName(method->Key());
993         if (std::holds_alternative<util::StringView>(res)) {
994             auto name = std::get<util::StringView>(res);
995             FunctionType functionType(extractor_, method, name);
996             methods_.emplace_back(recorder_->GetNodeTypeIndex(method));
997         } else {
998             auto identifier = std::get<const ir::Identifier *>(res);
999             if (identifier != nullptr) {
1000                 auto name = identifier->Name();
1001                 FunctionType functionType(extractor_, method, name);
1002                 recorder_->SetIdentifierTypeIndex(identifier, functionType.GetTypeIndexShift());
1003                 methods_.emplace_back(recorder_->GetNodeTypeIndex(method));
1004             }
1005         }
1006     }
1007 
FillMethod(const ir::TSSignatureDeclaration * method)1008     void FillMethod(const ir::TSSignatureDeclaration *method)
1009     {
1010         FunctionType functionType(extractor_, method, "");
1011         methods_.emplace_back(recorder_->GetNodeTypeIndex(method));
1012     }
1013 
FillIndexSignature(const ir::TSIndexSignature * indexSignature)1014     void FillIndexSignature(const ir::TSIndexSignature *indexSignature)
1015     {
1016         auto key = indexSignature->Param()->AsIdentifier()->TypeAnnotation();
1017         indexSignatures_[extractor_->GetTypeIndexFromAnnotation(key)] =
1018             extractor_->GetTypeIndexFromAnnotation(indexSignature->TypeAnnotation());
1019     }
1020 
FillMembers(const ir::TSInterfaceDeclaration * interfaceDef)1021     void FillMembers(const ir::TSInterfaceDeclaration *interfaceDef)
1022     {
1023         for (const auto &t : interfaceDef->Body()->Body()) {
1024             if (t->IsTSPropertySignature()) {
1025                 FillField(t->AsTSPropertySignature());
1026             } else if (t->IsTSMethodSignature()) {
1027                 FillMethod(t->AsTSMethodSignature());
1028             } else if (t->IsTSSignatureDeclaration()) {
1029                 FillMethod(t->AsTSSignatureDeclaration());
1030             } else if (t->IsTSIndexSignature()) {
1031                 FillIndexSignature(t->AsTSIndexSignature());
1032             }
1033         }
1034         if (indexSignatures_.size() > 0U) {
1035             // Update current type to IndexSignture Type
1036             IndexSigType indexSigType(extractor_, typeIndexShift_, &indexSignatures_);
1037             typeIndexShift_ = indexSigType.GetTypeIndexShift();
1038             recorder_->UpdateNodeTypeIndex(interfaceDef, typeIndexShift_);
1039         }
1040     }
1041 
FillFieldsLiteralBuffer()1042     void FillFieldsLiteralBuffer()
1043     {
1044         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(fields_.size()));
1045         std::for_each(fields_.begin(), fields_.end(), [this](const auto &t) {
1046             buffer_->Add(recorder_->Allocator()->New<ir::StringLiteral>(t.first));
1047             FillTypeIndexLiteralBuffer(t.second[0]);  // 0. typeIndex
1048             buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(t.second[1]));  // 1. accessFlag
1049             buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(t.second[2]));  // 2. modifier
1050         });
1051     }
1052 
FillMethodsLiteralBuffer()1053     void FillMethodsLiteralBuffer()
1054     {
1055         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(methods_.size()));
1056         std::for_each(methods_.begin(), methods_.end(), [this](const auto &t) {
1057             FillTypeIndexLiteralBuffer(t);
1058         });
1059     }
1060 
FillLiteralBuffer()1061     void FillLiteralBuffer()
1062     {
1063         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(UserType::INTERFACE));
1064         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(heritages_.size()));
1065         std::for_each(heritages_.begin(), heritages_.end(), [this](const auto &t) {
1066             FillTypeIndexLiteralBuffer(t);
1067         });
1068 
1069         FillFieldsLiteralBuffer();
1070         FillMethodsLiteralBuffer();
1071     }
1072 };
1073 
1074 class ExternalType : public BaseType {
1075 public:
ExternalType(TypeExtractor * extractor,const util::StringView & importName,const util::StringView & redirectPath)1076     explicit ExternalType(TypeExtractor *extractor, const util::StringView &importName,
1077                           const util::StringView &redirectPath) : BaseType(extractor)
1078     {
1079         std::stringstream ss;
1080         ss << "#" << std::string(importName) << "#" << std::string(redirectPath);
1081         redirectPath_ = util::UString(ss.str(), recorder_->Allocator()).View();
1082         typeIndex_ = recorder_->AddLiteralBuffer(buffer_);
1083         typeIndexShift_ = typeIndex_ + recorder_->GetUserTypeIndexShift();
1084         recorder_->AddUserType(typeIndexShift_);
1085 
1086         FillLiteralBuffer();
1087     }
1088     ~ExternalType() = default;
1089     NO_COPY_SEMANTIC(ExternalType);
1090     NO_MOVE_SEMANTIC(ExternalType);
1091 
GetTypeIndexShift()1092     int64_t GetTypeIndexShift() const
1093     {
1094         return typeIndexShift_;
1095     }
1096 
1097 private:
1098     util::StringView redirectPath_;
1099     int64_t typeIndex_ = PrimitiveType::ANY;
1100     int64_t typeIndexShift_ = PrimitiveType::ANY;
1101 
FillLiteralBuffer()1102     void FillLiteralBuffer()
1103     {
1104         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(UserType::EXTERNAL));
1105         buffer_->Add(recorder_->Allocator()->New<ir::StringLiteral>(redirectPath_));
1106     }
1107 };
1108 
1109 class UnionType : public BaseType {
1110 public:
UnionType(TypeExtractor * extractor,const ir::TSUnionType * unionDef)1111     explicit UnionType(TypeExtractor *extractor, const ir::TSUnionType *unionDef)
1112         : BaseType(extractor), unionTypes_(recorder_->Allocator()->Adapter())
1113     {
1114         auto unionStr = CalculateStr(unionDef->Types());
1115         typeIndexShift_ = recorder_->GetUnionType(unionStr);
1116         if (typeIndexShift_ != PrimitiveType::ANY) {
1117             return;
1118         }
1119 
1120         typeIndex_ = recorder_->AddLiteralBuffer(buffer_);
1121         typeIndexShift_ = typeIndex_ + recorder_->GetUserTypeIndexShift();
1122         recorder_->SetUnionType(unionStr, typeIndexShift_);
1123         recorder_->AddUserType(typeIndexShift_);
1124 
1125         FillTypes(unionDef);
1126         FillLiteralBuffer();
1127     }
1128     ~UnionType() = default;
1129     NO_COPY_SEMANTIC(UnionType);
1130     NO_MOVE_SEMANTIC(UnionType);
1131 
GetTypeIndexShift()1132     int64_t GetTypeIndexShift() const
1133     {
1134         return typeIndexShift_;
1135     }
1136 
1137 private:
1138     ArenaVector<int64_t> unionTypes_;
1139     int64_t typeIndex_ = PrimitiveType::ANY;
1140     int64_t typeIndexShift_ = PrimitiveType::ANY;
1141 
FillTypes(const ir::TSUnionType * unionDef)1142     void FillTypes(const ir::TSUnionType *unionDef)
1143     {
1144         for (const auto &t : unionDef->Types()) {
1145             unionTypes_.emplace_back(extractor_->GetTypeIndexFromAnnotation(t));
1146         }
1147     }
1148 
FillLiteralBuffer()1149     void FillLiteralBuffer()
1150     {
1151         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(UserType::UNION));
1152         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(unionTypes_.size()));
1153         std::for_each(unionTypes_.begin(), unionTypes_.end(), [this](const auto &t) {
1154             FillTypeIndexLiteralBuffer(t);
1155         });
1156     }
1157 };
1158 
1159 class ArrayType : public BaseType {
1160 public:
ArrayType(TypeExtractor * extractor,const ir::TSArrayType * arrayDef)1161     explicit ArrayType(TypeExtractor *extractor, const ir::TSArrayType *arrayDef) : BaseType(extractor)
1162     {
1163         typeIndexRefShift_ = extractor_->GetTypeIndexFromAnnotation(arrayDef->ElementType());
1164         typeIndexShift_ = recorder_->GetArrayType(typeIndexRefShift_);
1165         if (typeIndexShift_ != PrimitiveType::ANY) {
1166             return;
1167         }
1168 
1169         typeIndex_ = recorder_->AddLiteralBuffer(buffer_);
1170         typeIndexShift_ = typeIndex_ + recorder_->GetUserTypeIndexShift();
1171         recorder_->SetArrayType(typeIndexRefShift_, typeIndexShift_);
1172         recorder_->AddUserType(typeIndexShift_);
1173 
1174         FillLiteralBuffer();
1175     }
1176     ~ArrayType() = default;
1177     NO_COPY_SEMANTIC(ArrayType);
1178     NO_MOVE_SEMANTIC(ArrayType);
1179 
GetTypeIndexShift()1180     int64_t GetTypeIndexShift() const
1181     {
1182         return typeIndexShift_;
1183     }
1184 
1185 private:
1186     int64_t typeIndexRefShift_ = PrimitiveType::ANY;
1187     int64_t typeIndex_ = PrimitiveType::ANY;
1188     int64_t typeIndexShift_ = PrimitiveType::ANY;
1189 
FillLiteralBuffer()1190     void FillLiteralBuffer()
1191     {
1192         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(UserType::ARRAY));
1193         FillTypeIndexLiteralBuffer(typeIndexRefShift_);
1194     }
1195 };
1196 
1197 class ObjectType : public BaseType {
1198 public:
ObjectType(TypeExtractor * extractor,const ir::TSTypeLiteral * literalDef)1199     explicit ObjectType(TypeExtractor *extractor, const ir::TSTypeLiteral *literalDef)
1200         : BaseType(extractor),
1201           properties_(recorder_->Allocator()->Adapter()),
1202           methods_(recorder_->Allocator()->Adapter()),
1203           indexSignatures_(recorder_->Allocator()->Adapter())
1204     {
1205         std::string objectStr = "object";
1206         if (literalDef != nullptr) {
1207             objectStr = CalculateStr(literalDef->Members());
1208         }
1209         typeIndexShift_ = recorder_->GetObjectType(objectStr);
1210         if (typeIndexShift_ != PrimitiveType::ANY) {
1211             return;
1212         }
1213 
1214         typeIndex_ = recorder_->AddLiteralBuffer(buffer_);
1215         typeIndexShift_ = typeIndex_ + recorder_->GetUserTypeIndexShift();
1216         recorder_->SetObjectType(objectStr, typeIndexShift_);
1217         recorder_->AddUserType(typeIndexShift_);
1218 
1219         if (literalDef != nullptr) {
1220             FillMembers(literalDef, objectStr);
1221         }
1222         FillLiteralBuffer();
1223     }
1224     ~ObjectType() = default;
1225     NO_COPY_SEMANTIC(ObjectType);
1226     NO_MOVE_SEMANTIC(ObjectType);
1227 
GetTypeIndexShift()1228     int64_t GetTypeIndexShift() const
1229     {
1230         return typeIndexShift_;
1231     }
1232 
1233 private:
1234     ArenaMap<util::StringView, int64_t> properties_;
1235     ArenaVector<int64_t> methods_;
1236     ArenaMap<int64_t, int64_t> indexSignatures_;
1237     int64_t typeIndex_ = PrimitiveType::ANY;
1238     int64_t typeIndexShift_ = PrimitiveType::ANY;
1239 
FillMethod(const ir::TSMethodSignature * method)1240     void FillMethod(const ir::TSMethodSignature *method)
1241     {
1242         auto res = CalculateName(method->Key());
1243         if (std::holds_alternative<util::StringView>(res)) {
1244             auto name = std::get<util::StringView>(res);
1245             FunctionType functionType(extractor_, method, name);
1246             methods_.emplace_back(recorder_->GetNodeTypeIndex(method));
1247         } else {
1248             auto identifier = std::get<const ir::Identifier *>(res);
1249             if (identifier != nullptr) {
1250                 auto name = identifier->Name();
1251                 FunctionType functionType(extractor_, method, name);
1252                 recorder_->SetIdentifierTypeIndex(identifier, functionType.GetTypeIndexShift());
1253                 methods_.emplace_back(recorder_->GetNodeTypeIndex(method));
1254             }
1255         }
1256     }
1257 
FillMethod(const ir::TSSignatureDeclaration * method)1258     void FillMethod(const ir::TSSignatureDeclaration *method)
1259     {
1260         FunctionType functionType(extractor_, method, "");
1261         methods_.emplace_back(recorder_->GetNodeTypeIndex(method));
1262     }
1263 
FillIndexSignature(const ir::TSIndexSignature * indexSignature)1264     void FillIndexSignature(const ir::TSIndexSignature *indexSignature)
1265     {
1266         auto key = indexSignature->Param()->AsIdentifier()->TypeAnnotation();
1267         indexSignatures_[extractor_->GetTypeIndexFromAnnotation(key)] =
1268             extractor_->GetTypeIndexFromAnnotation(indexSignature->TypeAnnotation());
1269     }
1270 
FillMembers(const ir::TSTypeLiteral * literalDef,const std::string & objectStr)1271     void FillMembers(const ir::TSTypeLiteral *literalDef, const std::string &objectStr)
1272     {
1273         auto fn = [this](const auto *property, int64_t typeIndex) {
1274             auto res = CalculateName(property->Key());
1275             if (std::holds_alternative<util::StringView>(res)) {
1276                 properties_[std::get<util::StringView>(res)] = typeIndex;
1277             } else {
1278                 auto identifier = std::get<const ir::Identifier *>(res);
1279                 if (identifier != nullptr) {
1280                     recorder_->SetIdentifierTypeIndex(identifier, typeIndex);
1281                     properties_[identifier->Name()] = typeIndex;
1282                 }
1283             }
1284         };
1285 
1286         for (const auto &t : literalDef->Members()) {
1287             if (t->IsTSPropertySignature()) {
1288                 auto property = t->AsTSPropertySignature();
1289                 int64_t typeIndex = extractor_->GetTypeIndexFromAnnotation(property->TypeAnnotation());
1290                 fn(property, typeIndex);
1291             } else if (t->IsTSMethodSignature()) {
1292                 FillMethod(t->AsTSMethodSignature());
1293             } else if (t->IsTSSignatureDeclaration()) {
1294                 FillMethod(t->AsTSSignatureDeclaration());
1295             } else if (t->IsTSIndexSignature()) {
1296                 FillIndexSignature(t->AsTSIndexSignature());
1297             }
1298         }
1299 
1300         if (indexSignatures_.size() > 0U) {
1301             // Update current type to IndexSignture Type
1302             IndexSigType indexSigType(extractor_, typeIndexShift_, &indexSignatures_);
1303             typeIndexShift_ = indexSigType.GetTypeIndexShift();
1304             recorder_->SetObjectType(objectStr, typeIndexShift_);
1305         }
1306     }
1307 
FillLiteralBuffer()1308     void FillLiteralBuffer()
1309     {
1310         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(UserType::OBJECT));
1311         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(properties_.size()));
1312         std::for_each(properties_.begin(), properties_.end(), [this](const auto &t) {
1313             buffer_->Add(recorder_->Allocator()->New<ir::StringLiteral>(t.first));
1314             FillTypeIndexLiteralBuffer(t.second);
1315         });
1316         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(methods_.size()));
1317         std::for_each(methods_.begin(), methods_.end(), [this](const auto &t) {
1318             FillTypeIndexLiteralBuffer(t);
1319         });
1320     }
1321 };
1322 
1323 class BuiltinInstType : public BaseType {
1324 public:
BuiltinInstType(TypeExtractor * extractor,const std::vector<int64_t> & allTypes)1325     explicit BuiltinInstType(TypeExtractor *extractor, const std::vector<int64_t> &allTypes)
1326         : BaseType(extractor), paramTypes_(recorder_->Allocator()->Adapter())
1327     {
1328         typeIndexBuiltin_ = allTypes[0];
1329         typeIndex_ = recorder_->AddLiteralBuffer(buffer_);
1330         typeIndexShift_ = typeIndex_ + recorder_->GetUserTypeIndexShift();
1331         recorder_->SetBuiltinInst(allTypes, typeIndexShift_);
1332         recorder_->AddUserType(typeIndexShift_);
1333 
1334         FillTypes(allTypes);
1335         FillLiteralBuffer();
1336     }
1337     ~BuiltinInstType() = default;
1338     NO_COPY_SEMANTIC(BuiltinInstType);
1339     NO_MOVE_SEMANTIC(BuiltinInstType);
1340 
GetTypeIndexShift()1341     int64_t GetTypeIndexShift() const
1342     {
1343         return typeIndexShift_;
1344     }
1345 
1346 private:
1347     ArenaVector<int64_t> paramTypes_;
1348     int64_t typeIndexBuiltin_ = PrimitiveType::ANY;
1349     int64_t typeIndex_ = PrimitiveType::ANY;
1350     int64_t typeIndexShift_ = PrimitiveType::ANY;
1351 
FillTypes(const std::vector<int64_t> & allTypes)1352     void FillTypes(const std::vector<int64_t> &allTypes)
1353     {
1354         for (size_t t = 1; t < allTypes.size(); t++) {
1355             paramTypes_.emplace_back(allTypes[t]);
1356         }
1357     }
1358 
FillLiteralBuffer()1359     void FillLiteralBuffer()
1360     {
1361         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(UserType::BUILTININST));
1362         FillTypeIndexLiteralBuffer(typeIndexBuiltin_);
1363         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(paramTypes_.size()));
1364         std::for_each(paramTypes_.begin(), paramTypes_.end(), [this](const auto &t) {
1365             FillTypeIndexLiteralBuffer(t);
1366         });
1367     }
1368 };
1369 
1370 class GenericInstType : public BaseType {
1371 public:
GenericInstType(TypeExtractor * extractor,const std::vector<int64_t> & allTypes)1372     explicit GenericInstType(TypeExtractor *extractor, const std::vector<int64_t> &allTypes)
1373         : BaseType(extractor), paramTypes_(recorder_->Allocator()->Adapter())
1374     {
1375         typeIndexGeneric_ = allTypes[0];
1376         typeIndex_ = recorder_->AddLiteralBuffer(buffer_);
1377         typeIndexShift_ = typeIndex_ + recorder_->GetUserTypeIndexShift();
1378         recorder_->SetGenericInst(allTypes, typeIndexShift_);
1379         recorder_->AddUserType(typeIndexShift_);
1380 
1381         FillTypes(allTypes);
1382         FillLiteralBuffer();
1383     }
1384     ~GenericInstType() = default;
1385     NO_COPY_SEMANTIC(GenericInstType);
1386     NO_MOVE_SEMANTIC(GenericInstType);
1387 
GetTypeIndexShift()1388     int64_t GetTypeIndexShift() const
1389     {
1390         return typeIndexShift_;
1391     }
1392 
1393 private:
1394     ArenaVector<int64_t> paramTypes_;
1395     int64_t typeIndexGeneric_ = PrimitiveType::ANY;
1396     int64_t typeIndex_ = PrimitiveType::ANY;
1397     int64_t typeIndexShift_ = PrimitiveType::ANY;
1398 
FillTypes(const std::vector<int64_t> & allTypes)1399     void FillTypes(const std::vector<int64_t> &allTypes)
1400     {
1401         for (size_t t = 1; t < allTypes.size(); t++) {
1402             paramTypes_.emplace_back(allTypes[t]);
1403         }
1404     }
1405 
FillLiteralBuffer()1406     void FillLiteralBuffer()
1407     {
1408         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(UserType::GENERICINST));
1409         FillTypeIndexLiteralBuffer(typeIndexGeneric_);
1410         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(paramTypes_.size()));
1411         std::for_each(paramTypes_.begin(), paramTypes_.end(), [this](const auto &t) {
1412             FillTypeIndexLiteralBuffer(t);
1413         });
1414     }
1415 };
1416 
1417 }  // namespace panda::es2panda::extractor
1418 
1419 #endif  // ES2PANDA_TYPESCRIPT_EXACTOR_TYPESYSTEM_H
1420