• 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         for (const auto &t : classDef->IndexSignatures()) {
807             auto key = t->Param()->AsIdentifier()->TypeAnnotation();
808             indexSignatures_[extractor_->GetTypeIndexFromAnnotation(key)] =
809                 extractor_->GetTypeIndexFromAnnotation(t->TypeAnnotation());
810         }
811         if (indexSignatures_.size() > 0U) {
812             // Update current type to IndexSignture Type
813             IndexSigType indexSigType(extractor_, typeIndexShift_, &indexSignatures_);
814             typeIndexShift_ = indexSigType.GetTypeIndexShift();
815             recorder_->UpdateNodeTypeIndex(classDef, typeIndexShift_);
816         }
817     }
818 
FillFieldsLiteralBuffer(bool isStatic)819     void FillFieldsLiteralBuffer(bool isStatic)
820     {
821         // 3 field infos, typeIndex / accessFlag / modifier
822         auto fn = [this](const ArenaMap<util::StringView, std::array<int64_t, 3>> &map) {
823             buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(map.size()));
824             std::for_each(map.begin(), map.end(), [this](const auto &t) {
825                 buffer_->Add(recorder_->Allocator()->New<ir::StringLiteral>(t.first));
826                 FillTypeIndexLiteralBuffer(t.second[0]);  // 0. typeIndex
827                 buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(t.second[1]));  // 1. accessFlag
828                 buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(t.second[2]));  // 2. modifier
829             });
830         };
831 
832         if (isStatic) {
833             fn(staticFields_);
834         } else {
835             fn(fields_);
836         }
837     }
838 
FillMethodsLiteralBuffer(bool isStatic)839     void FillMethodsLiteralBuffer(bool isStatic)
840     {
841         auto fn = [this](const ArenaMap<int64_t, util::StringView> &map) {
842             buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(map.size()));
843             std::for_each(map.begin(), map.end(), [this](const auto &t) {
844                 buffer_->Add(recorder_->Allocator()->New<ir::StringLiteral>(t.second));
845                 FillTypeIndexLiteralBuffer(t.first);
846             });
847         };
848 
849         if (isStatic) {
850             fn(staticMethods_);
851         } else {
852             fn(methods_);
853         }
854     }
855 
FillLiteralBuffer()856     void FillLiteralBuffer()
857     {
858         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(UserType::CLASS));
859         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(modifierAB_));
860         FillTypeIndexLiteralBuffer(extendsHeritage_);
861         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(implementsHeritages_.size()));
862         std::for_each(implementsHeritages_.begin(), implementsHeritages_.end(), [this](const auto &t) {
863             FillTypeIndexLiteralBuffer(t);
864         });
865 
866         FillFieldsLiteralBuffer(false);
867         FillMethodsLiteralBuffer(false);
868         FillFieldsLiteralBuffer(true);
869         FillMethodsLiteralBuffer(true);
870     }
871 };
872 
873 class ClassInstType : public BaseType {
874 public:
ClassInstType(TypeExtractor * extractor,int64_t typeIndexRefShift)875     explicit ClassInstType(TypeExtractor *extractor, int64_t typeIndexRefShift)
876         : BaseType(extractor), typeIndexRefShift_(typeIndexRefShift)
877     {
878         typeIndex_ = recorder_->AddLiteralBuffer(buffer_);
879         typeIndexShift_ = typeIndex_ + recorder_->GetUserTypeIndexShift();
880         recorder_->SetClassInst(typeIndexRefShift_, typeIndexShift_);
881         recorder_->SetClassType(typeIndexShift_, typeIndexRefShift_);
882         recorder_->AddUserType(typeIndexShift_);
883 
884         FillLiteralBuffer();
885     }
886     ~ClassInstType() = default;
887     NO_COPY_SEMANTIC(ClassInstType);
888     NO_MOVE_SEMANTIC(ClassInstType);
889 
GetTypeIndexShift()890     int64_t GetTypeIndexShift() const
891     {
892         return typeIndexShift_;
893     }
894 
895 private:
896     int64_t typeIndexRefShift_ = PrimitiveType::ANY;
897     int64_t typeIndex_ = PrimitiveType::ANY;
898     int64_t typeIndexShift_ = PrimitiveType::ANY;
899 
FillLiteralBuffer()900     void FillLiteralBuffer()
901     {
902         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(UserType::CLASSINST));
903         FillTypeIndexLiteralBuffer(typeIndexRefShift_);
904     }
905 };
906 
907 class InterfaceType : public BaseType {
908 public:
InterfaceType(TypeExtractor * extractor,const ir::TSInterfaceDeclaration * interfaceDef,const util::StringView & name)909     explicit InterfaceType(TypeExtractor *extractor, const ir::TSInterfaceDeclaration *interfaceDef,
910                            const util::StringView &name)
911         : BaseType(extractor),
912           heritages_(recorder_->Allocator()->Adapter()),
913           paramTypes_(recorder_->Allocator()->Adapter()),
914           fields_(recorder_->Allocator()->Adapter()),
915           methods_(recorder_->Allocator()->Adapter()),
916           indexSignatures_(recorder_->Allocator()->Adapter())
917     {
918         typeIndexShift_ = recorder_->GetNodeTypeIndex(interfaceDef);
919         if (typeIndexShift_ != PrimitiveType::ANY) {
920             return;
921         }
922 
923         if (interfaceDef->TypeParams() != nullptr) {
924             CalculateParamTypes(paramTypes_, interfaceDef->TypeParams());
925         }
926 
927         CalculateIndex(name, typeIndex_, typeIndexShift_, true);
928         recorder_->SetNodeTypeIndex(interfaceDef, typeIndexShift_);
929         recorder_->AddUserType(typeIndexShift_);
930 
931         GenericParamTypeBindScope scope(extractor, &paramTypes_);
932         FillHeritages(interfaceDef);
933         FillMembers(interfaceDef);
934         FillLiteralBuffer();
935     }
936     ~InterfaceType() = default;
937     NO_COPY_SEMANTIC(InterfaceType);
938     NO_MOVE_SEMANTIC(InterfaceType);
939 
GetTypeIndexShift()940     int64_t GetTypeIndexShift() const
941     {
942         return typeIndexShift_;
943     }
944 
945 private:
946     ArenaVector<int64_t> heritages_;
947     ArenaMap<util::StringView, int64_t> paramTypes_;
948     // 3 field infos, typeIndex / accessFlag / modifier
949     ArenaMap<util::StringView, std::array<int64_t, 3>> fields_;
950     ArenaVector<int64_t> methods_;
951     ArenaMap<int64_t, int64_t> indexSignatures_;
952     int64_t typeIndex_ = PrimitiveType::ANY;
953     int64_t typeIndexShift_ = PrimitiveType::ANY;
954 
FillHeritages(const ir::TSInterfaceDeclaration * interfaceDef)955     void FillHeritages(const ir::TSInterfaceDeclaration *interfaceDef)
956     {
957         for (const auto &t : interfaceDef->Extends()) {
958             if (t != nullptr) {
959                 // TSTypeReference
960                 heritages_.emplace_back(extractor_->GetTypeIndexFromAnnotation(t->Expr(), false));
961             }
962         }
963     }
964 
FillField(const ir::TSPropertySignature * field)965     void FillField(const ir::TSPropertySignature *field)
966     {
967         AccessFlag flag = AccessFlag::PUBLIC;
968         auto isReadonly = field->Readonly();
969 
970         int64_t typeIndex = extractor_->GetTypeIndexFromAnnotation(field->TypeAnnotation());
971         // 3 field infos, typeIndex / accessFlag / modifier
972         std::array<int64_t, 3> fieldInfo = {typeIndex, flag, static_cast<int64_t>(isReadonly)};
973 
974         auto res = CalculateName(field->Key());
975         if (std::holds_alternative<util::StringView>(res)) {
976             fields_[std::get<util::StringView>(res)] = fieldInfo;
977         } else {
978             auto identifier = std::get<const ir::Identifier *>(res);
979             if (identifier != nullptr) {
980                 recorder_->SetIdentifierTypeIndex(identifier, typeIndex);
981                 fields_[identifier->Name()] = fieldInfo;
982             }
983         }
984     }
985 
FillMethod(const ir::TSMethodSignature * method)986     void FillMethod(const ir::TSMethodSignature *method)
987     {
988         auto res = CalculateName(method->Key());
989         if (std::holds_alternative<util::StringView>(res)) {
990             auto name = std::get<util::StringView>(res);
991             FunctionType functionType(extractor_, method, name);
992             methods_.emplace_back(recorder_->GetNodeTypeIndex(method));
993         } else {
994             auto identifier = std::get<const ir::Identifier *>(res);
995             if (identifier != nullptr) {
996                 auto name = identifier->Name();
997                 FunctionType functionType(extractor_, method, name);
998                 recorder_->SetIdentifierTypeIndex(identifier, functionType.GetTypeIndexShift());
999                 methods_.emplace_back(recorder_->GetNodeTypeIndex(method));
1000             }
1001         }
1002     }
1003 
FillMethod(const ir::TSSignatureDeclaration * method)1004     void FillMethod(const ir::TSSignatureDeclaration *method)
1005     {
1006         FunctionType functionType(extractor_, method, "");
1007         methods_.emplace_back(recorder_->GetNodeTypeIndex(method));
1008     }
1009 
FillIndexSignature(const ir::TSIndexSignature * indexSignature)1010     void FillIndexSignature(const ir::TSIndexSignature *indexSignature)
1011     {
1012         auto key = indexSignature->Param()->AsIdentifier()->TypeAnnotation();
1013         indexSignatures_[extractor_->GetTypeIndexFromAnnotation(key)] =
1014             extractor_->GetTypeIndexFromAnnotation(indexSignature->TypeAnnotation());
1015     }
1016 
FillMembers(const ir::TSInterfaceDeclaration * interfaceDef)1017     void FillMembers(const ir::TSInterfaceDeclaration *interfaceDef)
1018     {
1019         for (const auto &t : interfaceDef->Body()->Body()) {
1020             if (t->IsTSPropertySignature()) {
1021                 FillField(t->AsTSPropertySignature());
1022             } else if (t->IsTSMethodSignature()) {
1023                 FillMethod(t->AsTSMethodSignature());
1024             } else if (t->IsTSSignatureDeclaration()) {
1025                 FillMethod(t->AsTSSignatureDeclaration());
1026             } else if (t->IsTSIndexSignature()) {
1027                 FillIndexSignature(t->AsTSIndexSignature());
1028             }
1029         }
1030         if (indexSignatures_.size() > 0U) {
1031             // Update current type to IndexSignture Type
1032             IndexSigType indexSigType(extractor_, typeIndexShift_, &indexSignatures_);
1033             typeIndexShift_ = indexSigType.GetTypeIndexShift();
1034             recorder_->UpdateNodeTypeIndex(interfaceDef, typeIndexShift_);
1035         }
1036     }
1037 
FillFieldsLiteralBuffer()1038     void FillFieldsLiteralBuffer()
1039     {
1040         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(fields_.size()));
1041         std::for_each(fields_.begin(), fields_.end(), [this](const auto &t) {
1042             buffer_->Add(recorder_->Allocator()->New<ir::StringLiteral>(t.first));
1043             FillTypeIndexLiteralBuffer(t.second[0]);  // 0. typeIndex
1044             buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(t.second[1]));  // 1. accessFlag
1045             buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(t.second[2]));  // 2. modifier
1046         });
1047     }
1048 
FillMethodsLiteralBuffer()1049     void FillMethodsLiteralBuffer()
1050     {
1051         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(methods_.size()));
1052         std::for_each(methods_.begin(), methods_.end(), [this](const auto &t) {
1053             FillTypeIndexLiteralBuffer(t);
1054         });
1055     }
1056 
FillLiteralBuffer()1057     void FillLiteralBuffer()
1058     {
1059         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(UserType::INTERFACE));
1060         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(heritages_.size()));
1061         std::for_each(heritages_.begin(), heritages_.end(), [this](const auto &t) {
1062             FillTypeIndexLiteralBuffer(t);
1063         });
1064 
1065         FillFieldsLiteralBuffer();
1066         FillMethodsLiteralBuffer();
1067     }
1068 };
1069 
1070 class ExternalType : public BaseType {
1071 public:
ExternalType(TypeExtractor * extractor,const util::StringView & importName,const util::StringView & redirectPath)1072     explicit ExternalType(TypeExtractor *extractor, const util::StringView &importName,
1073                           const util::StringView &redirectPath) : BaseType(extractor)
1074     {
1075         std::stringstream ss;
1076         ss << "#" << std::string(importName) << "#" << std::string(redirectPath);
1077         redirectPath_ = util::UString(ss.str(), recorder_->Allocator()).View();
1078         typeIndex_ = recorder_->AddLiteralBuffer(buffer_);
1079         typeIndexShift_ = typeIndex_ + recorder_->GetUserTypeIndexShift();
1080         recorder_->AddUserType(typeIndexShift_);
1081 
1082         FillLiteralBuffer();
1083     }
1084     ~ExternalType() = default;
1085     NO_COPY_SEMANTIC(ExternalType);
1086     NO_MOVE_SEMANTIC(ExternalType);
1087 
GetTypeIndexShift()1088     int64_t GetTypeIndexShift() const
1089     {
1090         return typeIndexShift_;
1091     }
1092 
1093 private:
1094     util::StringView redirectPath_;
1095     int64_t typeIndex_ = PrimitiveType::ANY;
1096     int64_t typeIndexShift_ = PrimitiveType::ANY;
1097 
FillLiteralBuffer()1098     void FillLiteralBuffer()
1099     {
1100         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(UserType::EXTERNAL));
1101         buffer_->Add(recorder_->Allocator()->New<ir::StringLiteral>(redirectPath_));
1102     }
1103 };
1104 
1105 class UnionType : public BaseType {
1106 public:
UnionType(TypeExtractor * extractor,const ir::TSUnionType * unionDef)1107     explicit UnionType(TypeExtractor *extractor, const ir::TSUnionType *unionDef)
1108         : BaseType(extractor), unionTypes_(recorder_->Allocator()->Adapter())
1109     {
1110         auto unionStr = CalculateStr(unionDef->Types());
1111         typeIndexShift_ = recorder_->GetUnionType(unionStr);
1112         if (typeIndexShift_ != PrimitiveType::ANY) {
1113             return;
1114         }
1115 
1116         typeIndex_ = recorder_->AddLiteralBuffer(buffer_);
1117         typeIndexShift_ = typeIndex_ + recorder_->GetUserTypeIndexShift();
1118         recorder_->SetUnionType(unionStr, typeIndexShift_);
1119         recorder_->AddUserType(typeIndexShift_);
1120 
1121         FillTypes(unionDef);
1122         FillLiteralBuffer();
1123     }
1124     ~UnionType() = default;
1125     NO_COPY_SEMANTIC(UnionType);
1126     NO_MOVE_SEMANTIC(UnionType);
1127 
GetTypeIndexShift()1128     int64_t GetTypeIndexShift() const
1129     {
1130         return typeIndexShift_;
1131     }
1132 
1133 private:
1134     ArenaVector<int64_t> unionTypes_;
1135     int64_t typeIndex_ = PrimitiveType::ANY;
1136     int64_t typeIndexShift_ = PrimitiveType::ANY;
1137 
FillTypes(const ir::TSUnionType * unionDef)1138     void FillTypes(const ir::TSUnionType *unionDef)
1139     {
1140         for (const auto &t : unionDef->Types()) {
1141             unionTypes_.emplace_back(extractor_->GetTypeIndexFromAnnotation(t));
1142         }
1143     }
1144 
FillLiteralBuffer()1145     void FillLiteralBuffer()
1146     {
1147         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(UserType::UNION));
1148         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(unionTypes_.size()));
1149         std::for_each(unionTypes_.begin(), unionTypes_.end(), [this](const auto &t) {
1150             FillTypeIndexLiteralBuffer(t);
1151         });
1152     }
1153 };
1154 
1155 class ArrayType : public BaseType {
1156 public:
ArrayType(TypeExtractor * extractor,const ir::TSArrayType * arrayDef)1157     explicit ArrayType(TypeExtractor *extractor, const ir::TSArrayType *arrayDef) : BaseType(extractor)
1158     {
1159         typeIndexRefShift_ = extractor_->GetTypeIndexFromAnnotation(arrayDef->ElementType());
1160         typeIndexShift_ = recorder_->GetArrayType(typeIndexRefShift_);
1161         if (typeIndexShift_ != PrimitiveType::ANY) {
1162             return;
1163         }
1164 
1165         typeIndex_ = recorder_->AddLiteralBuffer(buffer_);
1166         typeIndexShift_ = typeIndex_ + recorder_->GetUserTypeIndexShift();
1167         recorder_->SetArrayType(typeIndexRefShift_, typeIndexShift_);
1168         recorder_->AddUserType(typeIndexShift_);
1169 
1170         FillLiteralBuffer();
1171     }
1172     ~ArrayType() = default;
1173     NO_COPY_SEMANTIC(ArrayType);
1174     NO_MOVE_SEMANTIC(ArrayType);
1175 
GetTypeIndexShift()1176     int64_t GetTypeIndexShift() const
1177     {
1178         return typeIndexShift_;
1179     }
1180 
1181 private:
1182     int64_t typeIndexRefShift_ = PrimitiveType::ANY;
1183     int64_t typeIndex_ = PrimitiveType::ANY;
1184     int64_t typeIndexShift_ = PrimitiveType::ANY;
1185 
FillLiteralBuffer()1186     void FillLiteralBuffer()
1187     {
1188         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(UserType::ARRAY));
1189         FillTypeIndexLiteralBuffer(typeIndexRefShift_);
1190     }
1191 };
1192 
1193 class ObjectType : public BaseType {
1194 public:
ObjectType(TypeExtractor * extractor,const ir::TSTypeLiteral * literalDef)1195     explicit ObjectType(TypeExtractor *extractor, const ir::TSTypeLiteral *literalDef)
1196         : BaseType(extractor),
1197           properties_(recorder_->Allocator()->Adapter()),
1198           methods_(recorder_->Allocator()->Adapter()),
1199           indexSignatures_(recorder_->Allocator()->Adapter())
1200     {
1201         std::string objectStr = "object";
1202         if (literalDef != nullptr) {
1203             objectStr = CalculateStr(literalDef->Members());
1204         }
1205         typeIndexShift_ = recorder_->GetObjectType(objectStr);
1206         if (typeIndexShift_ != PrimitiveType::ANY) {
1207             return;
1208         }
1209 
1210         typeIndex_ = recorder_->AddLiteralBuffer(buffer_);
1211         typeIndexShift_ = typeIndex_ + recorder_->GetUserTypeIndexShift();
1212         recorder_->SetObjectType(objectStr, typeIndexShift_);
1213         recorder_->AddUserType(typeIndexShift_);
1214 
1215         if (literalDef != nullptr) {
1216             FillMembers(literalDef, objectStr);
1217         }
1218         FillLiteralBuffer();
1219     }
1220     ~ObjectType() = default;
1221     NO_COPY_SEMANTIC(ObjectType);
1222     NO_MOVE_SEMANTIC(ObjectType);
1223 
GetTypeIndexShift()1224     int64_t GetTypeIndexShift() const
1225     {
1226         return typeIndexShift_;
1227     }
1228 
1229 private:
1230     ArenaMap<util::StringView, int64_t> properties_;
1231     ArenaVector<int64_t> methods_;
1232     ArenaMap<int64_t, int64_t> indexSignatures_;
1233     int64_t typeIndex_ = PrimitiveType::ANY;
1234     int64_t typeIndexShift_ = PrimitiveType::ANY;
1235 
FillMethod(const ir::TSMethodSignature * method)1236     void FillMethod(const ir::TSMethodSignature *method)
1237     {
1238         auto res = CalculateName(method->Key());
1239         if (std::holds_alternative<util::StringView>(res)) {
1240             auto name = std::get<util::StringView>(res);
1241             FunctionType functionType(extractor_, method, name);
1242             methods_.emplace_back(recorder_->GetNodeTypeIndex(method));
1243         } else {
1244             auto identifier = std::get<const ir::Identifier *>(res);
1245             if (identifier != nullptr) {
1246                 auto name = identifier->Name();
1247                 FunctionType functionType(extractor_, method, name);
1248                 recorder_->SetIdentifierTypeIndex(identifier, functionType.GetTypeIndexShift());
1249                 methods_.emplace_back(recorder_->GetNodeTypeIndex(method));
1250             }
1251         }
1252     }
1253 
FillMethod(const ir::TSSignatureDeclaration * method)1254     void FillMethod(const ir::TSSignatureDeclaration *method)
1255     {
1256         FunctionType functionType(extractor_, method, "");
1257         methods_.emplace_back(recorder_->GetNodeTypeIndex(method));
1258     }
1259 
FillIndexSignature(const ir::TSIndexSignature * indexSignature)1260     void FillIndexSignature(const ir::TSIndexSignature *indexSignature)
1261     {
1262         auto key = indexSignature->Param()->AsIdentifier()->TypeAnnotation();
1263         indexSignatures_[extractor_->GetTypeIndexFromAnnotation(key)] =
1264             extractor_->GetTypeIndexFromAnnotation(indexSignature->TypeAnnotation());
1265     }
1266 
FillMembers(const ir::TSTypeLiteral * literalDef,const std::string & objectStr)1267     void FillMembers(const ir::TSTypeLiteral *literalDef, const std::string &objectStr)
1268     {
1269         auto fn = [this](const auto *property, int64_t typeIndex) {
1270             auto res = CalculateName(property->Key());
1271             if (std::holds_alternative<util::StringView>(res)) {
1272                 properties_[std::get<util::StringView>(res)] = typeIndex;
1273             } else {
1274                 auto identifier = std::get<const ir::Identifier *>(res);
1275                 if (identifier != nullptr) {
1276                     recorder_->SetIdentifierTypeIndex(identifier, typeIndex);
1277                     properties_[identifier->Name()] = typeIndex;
1278                 }
1279             }
1280         };
1281 
1282         for (const auto &t : literalDef->Members()) {
1283             if (t->IsTSPropertySignature()) {
1284                 auto property = t->AsTSPropertySignature();
1285                 int64_t typeIndex = extractor_->GetTypeIndexFromAnnotation(property->TypeAnnotation());
1286                 fn(property, typeIndex);
1287             } else if (t->IsTSMethodSignature()) {
1288                 FillMethod(t->AsTSMethodSignature());
1289             } else if (t->IsTSSignatureDeclaration()) {
1290                 FillMethod(t->AsTSSignatureDeclaration());
1291             } else if (t->IsTSIndexSignature()) {
1292                 FillIndexSignature(t->AsTSIndexSignature());
1293             }
1294         }
1295 
1296         if (indexSignatures_.size() > 0U) {
1297             // Update current type to IndexSignture Type
1298             IndexSigType indexSigType(extractor_, typeIndexShift_, &indexSignatures_);
1299             typeIndexShift_ = indexSigType.GetTypeIndexShift();
1300             recorder_->SetObjectType(objectStr, typeIndexShift_);
1301         }
1302     }
1303 
FillLiteralBuffer()1304     void FillLiteralBuffer()
1305     {
1306         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(UserType::OBJECT));
1307         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(properties_.size()));
1308         std::for_each(properties_.begin(), properties_.end(), [this](const auto &t) {
1309             buffer_->Add(recorder_->Allocator()->New<ir::StringLiteral>(t.first));
1310             FillTypeIndexLiteralBuffer(t.second);
1311         });
1312         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(methods_.size()));
1313         std::for_each(methods_.begin(), methods_.end(), [this](const auto &t) {
1314             FillTypeIndexLiteralBuffer(t);
1315         });
1316     }
1317 };
1318 
1319 class BuiltinInstType : public BaseType {
1320 public:
BuiltinInstType(TypeExtractor * extractor,const std::vector<int64_t> & allTypes)1321     explicit BuiltinInstType(TypeExtractor *extractor, const std::vector<int64_t> &allTypes)
1322         : BaseType(extractor), paramTypes_(recorder_->Allocator()->Adapter())
1323     {
1324         typeIndexBuiltin_ = allTypes[0];
1325         typeIndex_ = recorder_->AddLiteralBuffer(buffer_);
1326         typeIndexShift_ = typeIndex_ + recorder_->GetUserTypeIndexShift();
1327         recorder_->SetBuiltinInst(allTypes, typeIndexShift_);
1328         recorder_->AddUserType(typeIndexShift_);
1329 
1330         FillTypes(allTypes);
1331         FillLiteralBuffer();
1332     }
1333     ~BuiltinInstType() = default;
1334     NO_COPY_SEMANTIC(BuiltinInstType);
1335     NO_MOVE_SEMANTIC(BuiltinInstType);
1336 
GetTypeIndexShift()1337     int64_t GetTypeIndexShift() const
1338     {
1339         return typeIndexShift_;
1340     }
1341 
1342 private:
1343     ArenaVector<int64_t> paramTypes_;
1344     int64_t typeIndexBuiltin_ = PrimitiveType::ANY;
1345     int64_t typeIndex_ = PrimitiveType::ANY;
1346     int64_t typeIndexShift_ = PrimitiveType::ANY;
1347 
FillTypes(const std::vector<int64_t> & allTypes)1348     void FillTypes(const std::vector<int64_t> &allTypes)
1349     {
1350         for (size_t t = 1; t < allTypes.size(); t++) {
1351             paramTypes_.emplace_back(allTypes[t]);
1352         }
1353     }
1354 
FillLiteralBuffer()1355     void FillLiteralBuffer()
1356     {
1357         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(UserType::BUILTININST));
1358         FillTypeIndexLiteralBuffer(typeIndexBuiltin_);
1359         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(paramTypes_.size()));
1360         std::for_each(paramTypes_.begin(), paramTypes_.end(), [this](const auto &t) {
1361             FillTypeIndexLiteralBuffer(t);
1362         });
1363     }
1364 };
1365 
1366 class GenericInstType : public BaseType {
1367 public:
GenericInstType(TypeExtractor * extractor,const std::vector<int64_t> & allTypes)1368     explicit GenericInstType(TypeExtractor *extractor, const std::vector<int64_t> &allTypes)
1369         : BaseType(extractor), paramTypes_(recorder_->Allocator()->Adapter())
1370     {
1371         typeIndexGeneric_ = allTypes[0];
1372         typeIndex_ = recorder_->AddLiteralBuffer(buffer_);
1373         typeIndexShift_ = typeIndex_ + recorder_->GetUserTypeIndexShift();
1374         recorder_->SetGenericInst(allTypes, typeIndexShift_);
1375         recorder_->AddUserType(typeIndexShift_);
1376 
1377         FillTypes(allTypes);
1378         FillLiteralBuffer();
1379     }
1380     ~GenericInstType() = default;
1381     NO_COPY_SEMANTIC(GenericInstType);
1382     NO_MOVE_SEMANTIC(GenericInstType);
1383 
GetTypeIndexShift()1384     int64_t GetTypeIndexShift() const
1385     {
1386         return typeIndexShift_;
1387     }
1388 
1389 private:
1390     ArenaVector<int64_t> paramTypes_;
1391     int64_t typeIndexGeneric_ = PrimitiveType::ANY;
1392     int64_t typeIndex_ = PrimitiveType::ANY;
1393     int64_t typeIndexShift_ = PrimitiveType::ANY;
1394 
FillTypes(const std::vector<int64_t> & allTypes)1395     void FillTypes(const std::vector<int64_t> &allTypes)
1396     {
1397         for (size_t t = 1; t < allTypes.size(); t++) {
1398             paramTypes_.emplace_back(allTypes[t]);
1399         }
1400     }
1401 
FillLiteralBuffer()1402     void FillLiteralBuffer()
1403     {
1404         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(UserType::GENERICINST));
1405         FillTypeIndexLiteralBuffer(typeIndexGeneric_);
1406         buffer_->Add(recorder_->Allocator()->New<ir::NumberLiteral>(paramTypes_.size()));
1407         std::for_each(paramTypes_.begin(), paramTypes_.end(), [this](const auto &t) {
1408             FillTypeIndexLiteralBuffer(t);
1409         });
1410     }
1411 };
1412 
1413 }  // namespace panda::es2panda::extractor
1414 
1415 #endif  // ES2PANDA_TYPESCRIPT_EXACTOR_TYPESYSTEM_H
1416