diff --git a/es2panda/binder/binder.cpp b/es2panda/binder/binder.cpp index 0d2fd97b87f69bb69448c3bfcb0de0f38c478e55..99155a70775d76904f1bea8334472f81416ec04a 100644 --- a/es2panda/binder/binder.cpp +++ b/es2panda/binder/binder.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -206,14 +207,19 @@ void Binder::LookupIdentReference(ir::Identifier *ident) InstantiateArguments(); } - ScopeFindResult res = scope_->Find(ident->Name(), bindingOptions_); + ScopeFindResult res; + if (bindingFlags_ & ResolveBindingFlags::TS_BEFORE_TRANSFORM) { + ident->SetTSVariables(FindIdentifierTSVariables(ident, scope_, res)); + } else { + res = scope_->Find(ident->Name(), bindingOptions_); + } if (res.level != 0) { ASSERT(res.variable); res.variable->SetLexical(res.scope, program_->HotfixHelper()); } - if (!res.variable) { + if (res.variable == nullptr) { return; } @@ -397,6 +403,10 @@ void Binder::BuildClassDefinition(ir::ClassDefinition *classDef) ResolveReference(classDef, classDef->Super()); } + for (auto *impl : classDef->Implements()) { + ResolveReference(classDef, impl); + } + if (classDef->Ident()) { ScopeFindResult res = scope_->Find(classDef->Ident()->Name()); @@ -713,4 +723,44 @@ bool Binder::HasVariableName(const util::StringView &name) const return variableNames_.find(name) != variableNames_.end(); } +std::vector Binder::FindIdentifierTSVariables(const ir::Identifier *identifier, Scope *scope, + ScopeFindResult &res) +{ + const auto &name = identifier->Name(); + std::vector findRes; + + auto currentScope = scope; + while (currentScope != nullptr) { + // Find ts variables + auto fn = [&findRes](Variable *variable) { + if (variable != nullptr) { + findRes.emplace_back(variable); + } + }; + + fn(currentScope->FindLocalTSVariable(name)); + fn(currentScope->FindLocalTSVariable(name)); + fn(currentScope->FindLocalTSVariable(name)); + if (currentScope->IsTSModuleScope()) { + fn(currentScope->AsTSModuleScope()->FindExportTSVariable(name)); + fn(currentScope->AsTSModuleScope()->FindExportTSVariable(name)); + fn(currentScope->AsTSModuleScope()->FindExportTSVariable(name)); + } + + // Find js variable + if (currentScope->FindLocal(name, bindingOptions_) != nullptr) { + res = scope->Find(name, bindingOptions_); + break; + } + + if (!findRes.empty()) { + break; + } + + currentScope = currentScope->Parent(); + } + + return findRes; +} + } // namespace panda::es2panda::binder diff --git a/es2panda/binder/binder.h b/es2panda/binder/binder.h index a45d8a198daec5f148103262440a115c961e2e6e..464df08b5aed413c445c0f2ca91af4574a0cf916 100644 --- a/es2panda/binder/binder.h +++ b/es2panda/binder/binder.h @@ -127,6 +127,9 @@ public: bool HasVariableName(const util::StringView &name) const; + std::vector FindIdentifierTSVariables(const ir::Identifier *identifier, Scope *scope, + ScopeFindResult &res); + static constexpr std::string_view FUNCTION_ARGUMENTS = "arguments"; static constexpr std::string_view MANDATORY_PARAM_FUNC = "4funcObj"; static constexpr std::string_view MANDATORY_PARAM_NEW_TARGET = "4newTarget"; diff --git a/es2panda/binder/variable.h b/es2panda/binder/variable.h index 170055cf16f1c0147fffaf284151a9aa2ef2042e..65eb6a31fe7613a95b58902450076887c6641f61 100644 --- a/es2panda/binder/variable.h +++ b/es2panda/binder/variable.h @@ -282,6 +282,11 @@ public: return exportBindings_; } + const ExportBindings *GetExportBindings() const + { + return exportBindings_; + } + void SetExportBindings(ExportBindings *exportBindings) { exportBindings_ = exportBindings; diff --git a/es2panda/ir/base/classDefinition.h b/es2panda/ir/base/classDefinition.h index 43ae00c6db515daa0de0695ae88ab3108fec661b..acb577bb4020ca50de0adbeab4d22f74c3fa0ed9 100644 --- a/es2panda/ir/base/classDefinition.h +++ b/es2panda/ir/base/classDefinition.h @@ -111,6 +111,16 @@ public: return body_; } + TSTypeParameterDeclaration *TypeParams() + { + return typeParams_; + } + + const TSTypeParameterDeclaration *TypeParams() const + { + return typeParams_; + } + ArenaVector &Implements() { return implements_; @@ -121,6 +131,16 @@ public: return implements_; } + ArenaVector &IndexSignatures() + { + return indexSignatures_; + } + + const ArenaVector &IndexSignatures() const + { + return indexSignatures_; + } + MethodDefinition *Ctor() { ASSERT(ctor_ != nullptr); diff --git a/es2panda/ir/expressions/identifier.h b/es2panda/ir/expressions/identifier.h index 9a5f67d9c6cc6f0cd1f8c37baebb51bc27d324cf..8bf87b5d86b21a5feda989d25136a21123854548 100644 --- a/es2panda/ir/expressions/identifier.h +++ b/es2panda/ir/expressions/identifier.h @@ -101,6 +101,16 @@ public: flags_ |= IdentifierFlags::REFERENCE; } + const std::vector &TSVariables() const + { + return tsVariables_; + } + + void SetTSVariables(const std::vector &tsVariables) + { + tsVariables_ = tsVariables; + } + bool IsTdz() const { return (flags_ & IdentifierFlags::TDZ) != 0; @@ -126,6 +136,7 @@ private: util::StringView name_; Expression *typeAnnotation_ {}; IdentifierFlags flags_ {IdentifierFlags::NONE}; + std::vector tsVariables_; }; } // namespace panda::es2panda::ir diff --git a/es2panda/ir/ts/tsConstructorType.h b/es2panda/ir/ts/tsConstructorType.h index 01686e44ee7197b6a1e63314f838e1467c4b8251..4cbf4b615af383a96d80094bee0863ae3766df5f 100644 --- a/es2panda/ir/ts/tsConstructorType.h +++ b/es2panda/ir/ts/tsConstructorType.h @@ -63,7 +63,7 @@ public: return params_; } - const Expression *ReturnType() const + const Expression *ReturnTypeAnnotation() const { return returnType_; } diff --git a/es2panda/ir/ts/tsFunctionType.h b/es2panda/ir/ts/tsFunctionType.h index 7ce73b35f715529ee7ef880b4e2200304620e961..5080b8738aa493fc65d94d6fdabf947f3d9804c4 100644 --- a/es2panda/ir/ts/tsFunctionType.h +++ b/es2panda/ir/ts/tsFunctionType.h @@ -62,7 +62,7 @@ public: return params_; } - const Expression *ReturnType() const + const Expression *ReturnTypeAnnotation() const { return returnType_; } diff --git a/es2panda/ir/ts/tsIndexSignature.h b/es2panda/ir/ts/tsIndexSignature.h index 07fc83ebce7fd78fde957e71739bdeefe4abfe2e..a2c60853a66f8c651e3c5066ad89732cf2ad6dc0 100644 --- a/es2panda/ir/ts/tsIndexSignature.h +++ b/es2panda/ir/ts/tsIndexSignature.h @@ -46,11 +46,21 @@ public: return param_; } + Expression *Param() + { + return param_; + } + const Expression *TypeAnnotation() const { return typeAnnotation_; } + Expression *TypeAnnotation() + { + return typeAnnotation_; + } + bool Readonly() const { return readonly_; diff --git a/es2panda/parser/parserImpl.cpp b/es2panda/parser/parserImpl.cpp index c411dbefc67dd48b02b537a7a447b070ff60d29d..cce58af4b983c4e3aec671a5e25308b0e737af5b 100644 --- a/es2panda/parser/parserImpl.cpp +++ b/es2panda/parser/parserImpl.cpp @@ -2826,6 +2826,7 @@ ir::ClassDefinition *ParserImpl::ParseClassDefinition(bool isDeclaration, bool i ir::Expression *expr = AllocNode(lexer_->GetToken().Ident()); expr->SetRange(lexer_->GetToken().Loc()); + expr->AsIdentifier()->SetReference(); lexer_->NextToken(); diff --git a/es2panda/typescript/extractor/typeExtractor.cpp b/es2panda/typescript/extractor/typeExtractor.cpp index 32b987255f2dd3ea647a6b6bbed2a520d25a30b9..a23648674d6e5ce85a7ea51aea38a247917f8953 100644 --- a/es2panda/typescript/extractor/typeExtractor.cpp +++ b/es2panda/typescript/extractor/typeExtractor.cpp @@ -20,12 +20,18 @@ #include #include #include +#include #include #include +#include #include +#include +#include +#include #include #include #include +#include #include #include #include @@ -65,6 +71,10 @@ TypeExtractor::TypeExtractor(const ir::BlockStatement *rootNode, bool typeDtsExt std::bind(&TypeExtractor::GetTypeIndexFromClassDefinition, this, std::placeholders::_1, std::placeholders::_2); getterMap_[ir::AstNodeType::TS_INTERFACE_DECLARATION] = std::bind(&TypeExtractor::GetTypeIndexFromInterfaceNode, this, std::placeholders::_1, std::placeholders::_2); + getterMap_[ir::AstNodeType::FUNCTION_EXPRESSION] = + std::bind(&TypeExtractor::GetTypeIndexFromFunctionNode, this, std::placeholders::_1, std::placeholders::_2); + getterMap_[ir::AstNodeType::ARROW_FUNCTION_EXPRESSION] = + std::bind(&TypeExtractor::GetTypeIndexFromFunctionNode, this, std::placeholders::_1, std::placeholders::_2); getterMap_[ir::AstNodeType::IMPORT_NAMESPACE_SPECIFIER] = std::bind(&TypeExtractor::GetTypeIndexFromImportNode, this, std::placeholders::_1, std::placeholders::_2); getterMap_[ir::AstNodeType::IMPORT_SPECIFIER] = @@ -73,8 +83,14 @@ TypeExtractor::TypeExtractor(const ir::BlockStatement *rootNode, bool typeDtsExt std::bind(&TypeExtractor::GetTypeIndexFromImportNode, this, std::placeholders::_1, std::placeholders::_2); getterMap_[ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION] = std::bind(&TypeExtractor::GetTypeIndexFromTypeAliasNode, this, std::placeholders::_1, std::placeholders::_2); + getterMap_[ir::AstNodeType::TS_AS_EXPRESSION] = + std::bind(&TypeExtractor::GetTypeIndexFromAsNode, this, std::placeholders::_1, std::placeholders::_2); + getterMap_[ir::AstNodeType::TS_TYPE_ASSERTION] = + std::bind(&TypeExtractor::GetTypeIndexFromAssertionNode, this, std::placeholders::_1, std::placeholders::_2); getterMap_[ir::AstNodeType::MEMBER_EXPRESSION] = std::bind(&TypeExtractor::GetTypeIndexFromMemberNode, this, std::placeholders::_1, std::placeholders::_2); + getterMap_[ir::AstNodeType::TS_QUALIFIED_NAME] = + std::bind(&TypeExtractor::GetTypeIndexFromTSQualifiedNode, this, std::placeholders::_1, std::placeholders::_2); handlerMap_[ir::AstNodeType::VARIABLE_DECLARATION] = std::bind(&TypeExtractor::HandleVariableDeclaration, this, std::placeholders::_1); @@ -219,19 +235,6 @@ const ir::Identifier *TypeExtractor::GetIdentifierFromExpression(const ir::Expre switch (expression->Type()) { case ir::AstNodeType::IDENTIFIER: return expression->AsIdentifier(); - case ir::AstNodeType::TS_QUALIFIED_NAME: // : A.B - // TODO(extractor): consider property type suppport - return expression->AsTSQualifiedName()->Right(); - case ir::AstNodeType::TS_CLASS_IMPLEMENTS: { - auto expr = expression->AsTSClassImplements()->Expr(); - if (expr->IsIdentifier()) { - return expr->AsIdentifier(); - } else if (expr->IsTSQualifiedName()) { - // TODO(extractor): consider property type suppport - return expr->AsTSQualifiedName()->Right(); - } - return nullptr; - } case ir::AstNodeType::REST_ELEMENT: { auto argument = expression->AsRestElement()->Argument(); if (argument->IsIdentifier()) { @@ -246,16 +249,6 @@ const ir::Identifier *TypeExtractor::GetIdentifierFromExpression(const ir::Expre } return nullptr; } - case ir::AstNodeType::TS_INTERFACE_HERITAGE: { - auto expr = expression->AsTSInterfaceHeritage()->Expr(); - if (expr->IsIdentifier()) { - return expr->AsIdentifier(); - } else if (expr->IsTSQualifiedName()) { - // TODO(extractor): consider property type suppport - return expr->AsTSQualifiedName()->Right(); - } - return nullptr; - } default: return nullptr; } @@ -264,18 +257,34 @@ const ir::Identifier *TypeExtractor::GetIdentifierFromExpression(const ir::Expre const ir::AstNode *TypeExtractor::GetDeclNodeFromIdentifier(const ir::Identifier *identifier, const ir::Identifier **variable) { - if (identifier == nullptr || identifier->Variable() == nullptr || - identifier->Variable()->Declaration() == nullptr) { + if (identifier == nullptr) { return nullptr; } - auto res = identifier->Variable()->Declaration()->Node(); - if (res != nullptr) { - // Return reference identifier if it contains variable binding to decl node + std::vector variables; + variables.reserve(identifier->TSVariables().size() + 1U); + variables.emplace_back(identifier->Variable()); + for (const auto &v : identifier->TSVariables()) { + variables.emplace_back(v); + } + + for (const auto &v : variables) { + if (v != nullptr && v->Declaration() != nullptr && v->Declaration()->Node() == nullptr) { + continue; + } + + auto res = v->Declaration()->Node(); + // Save reference identifier if it contains variable binding to decl node + // TODO(extractor): consider js&ts decl node merging, for example + // class A { a : string = "aaa" } + // interface A { b : number } + // let a : A = new A() + // console.log(a.b) *variable = identifier; TLOG(res->Type(), identifier); + return res; } - return res; + return nullptr; } const ir::AstNode *TypeExtractor::GetDeclNodeFromInitializer(const ir::Expression *initializer, @@ -293,8 +302,21 @@ const ir::AstNode *TypeExtractor::GetDeclNodeFromInitializer(const ir::Expressio } break; } + case ir::AstNodeType::TS_CLASS_IMPLEMENTS: { // class a implements A {} + auto expr = initializer->AsTSClassImplements()->Expr(); + if (expr->IsIdentifier()) { + return GetDeclNodeFromIdentifier(expr->AsIdentifier(), variable); + } + ASSERT(expr->IsTSQualifiedName()); + return expr->AsTSQualifiedName(); + } case ir::AstNodeType::CLASS_EXPRESSION: // let a = class A {} - case ir::AstNodeType::MEMBER_EXPRESSION: // let a = ns.A / let a : ns.A + case ir::AstNodeType::FUNCTION_EXPRESSION: // let a = function func () {} + case ir::AstNodeType::ARROW_FUNCTION_EXPRESSION: // let a = () => {} + case ir::AstNodeType::MEMBER_EXPRESSION: // let a = ns.A + case ir::AstNodeType::TS_QUALIFIED_NAME: // let a : ns.A + case ir::AstNodeType::TS_AS_EXPRESSION: // let a = x as number + case ir::AstNodeType::TS_TYPE_ASSERTION: // let a = x return initializer; default: break; @@ -336,20 +358,18 @@ int64_t TypeExtractor::GetTypeIndexFromClassExpression(const ir::AstNode *node, int64_t TypeExtractor::GetTypeIndexFromClassDefinition(const ir::AstNode *node, bool isNewInstance) { - auto typeIndex = recorder_->GetNodeTypeIndex(node); - if (typeIndex == PrimitiveType::ANY) { - auto fn = [&node, &typeIndex, this](const util::StringView &name) { - ClassType classType(this, node->AsClassDefinition(), name); - typeIndex = classType.GetTypeIndexShift(); - }; + int64_t typeIndex = PrimitiveType::ANY; + auto fn = [&node, &typeIndex, this](const util::StringView &name) { + ClassType classType(this, node->AsClassDefinition(), name); + typeIndex = classType.GetTypeIndexShift(); + }; - auto identifier = node->AsClassDefinition()->Ident(); - if (identifier != nullptr) { - fn(identifier->Name()); - recorder_->SetIdentifierTypeIndex(identifier, typeIndex); - } else { - fn(std::move(DEFAULT_NAME)); - } + auto identifier = node->AsClassDefinition()->Ident(); + if (identifier != nullptr) { + fn(identifier->Name()); + recorder_->SetIdentifierTypeIndex(identifier, typeIndex); + } else { + fn(std::move(DEFAULT_NAME)); } if (isNewInstance) { @@ -362,24 +382,46 @@ int64_t TypeExtractor::GetTypeIndexFromClassDefinition(const ir::AstNode *node, int64_t TypeExtractor::GetTypeIndexFromInterfaceNode(const ir::AstNode *node, bool isNewInstance) { - auto typeIndex = recorder_->GetNodeTypeIndex(node); - if (typeIndex == PrimitiveType::ANY) { - auto fn = [&node, &typeIndex, this](const util::StringView &name) { - InterfaceType interfaceType(this, node->AsTSInterfaceDeclaration(), name); - typeIndex = interfaceType.GetTypeIndexShift(); - }; + int64_t typeIndex = PrimitiveType::ANY; + auto fn = [&node, &typeIndex, this](const util::StringView &name) { + InterfaceType interfaceType(this, node->AsTSInterfaceDeclaration(), name); + typeIndex = interfaceType.GetTypeIndexShift(); + }; + + auto identifier = node->AsTSInterfaceDeclaration()->Id(); + if (identifier != nullptr) { + fn(identifier->Name()); + recorder_->SetIdentifierTypeIndex(identifier, typeIndex); + } else { + fn(std::move(DEFAULT_NAME)); + } + + if (isNewInstance) { + typeIndex = GetTypeIndexFromClassInst(typeIndex); + } + + TLOG(node->Type(), typeIndex); + return typeIndex; +} - auto identifier = node->AsTSInterfaceDeclaration()->Id(); +int64_t TypeExtractor::GetTypeIndexFromFunctionNode(const ir::AstNode *node, [[maybe_unused]] bool isNewInstance) +{ + int64_t typeIndex = PrimitiveType::ANY; + auto fn = [&node, &typeIndex, this](const util::StringView &name) { + FunctionType functionType(this, node, name); + typeIndex = functionType.GetTypeIndexShift(); + }; + + if (node->IsFunctionExpression()) { + auto identifier = node->AsFunctionExpression()->Function()->Id(); if (identifier != nullptr) { fn(identifier->Name()); recorder_->SetIdentifierTypeIndex(identifier, typeIndex); } else { - fn(std::move(DEFAULT_NAME)); + fn(""); } - } - - if (isNewInstance) { - typeIndex = GetTypeIndexFromClassInst(typeIndex); + } else { + fn(""); } TLOG(node->Type(), typeIndex); @@ -400,6 +442,20 @@ int64_t TypeExtractor::GetTypeIndexFromTypeAliasNode(const ir::AstNode *node, [[ return typeIndex; } +int64_t TypeExtractor::GetTypeIndexFromAsNode(const ir::AstNode *node, [[maybe_unused]] bool isNewInstance) +{ + auto typeIndex = GetTypeIndexFromAnnotation(node->AsTSAsExpression()->TypeAnnotation()); + TLOG(node->Type(), typeIndex); + return typeIndex; +} + +int64_t TypeExtractor::GetTypeIndexFromAssertionNode(const ir::AstNode *node, [[maybe_unused]] bool isNewInstance) +{ + auto typeIndex = GetTypeIndexFromAnnotation(node->AsTSTypeAssertion()->TypeAnnotation()); + TLOG(node->Type(), typeIndex); + return typeIndex; +} + int64_t TypeExtractor::GetTypeIndexFromMemberNode(const ir::AstNode *node, [[maybe_unused]] bool isNewInstance) { int64_t typeIndex = PrimitiveType::ANY; @@ -416,6 +472,45 @@ int64_t TypeExtractor::GetTypeIndexFromMemberNode(const ir::AstNode *node, [[may return typeIndex; } +int64_t TypeExtractor::GetTypeIndexFromTSQualifiedNode(const ir::AstNode *node, bool isNewInstance) +{ + ArenaDeque identifiers(recorder_->Allocator()->Adapter()); + const ir::Expression *head = node->AsTSQualifiedName(); + while (head->IsTSQualifiedName()) { + identifiers.emplace_front(head->AsTSQualifiedName()->Right()); + head = head->AsTSQualifiedName()->Left(); + } + + ASSERT(head->IsIdentifier()); + ArenaVector variables(recorder_->Allocator()->Adapter()); + for (const auto &v : head->AsIdentifier()->TSVariables()) { + GetVariablesFromTSQualifiedNodes(v, identifiers, variables); + } + + int64_t typeIndex = PrimitiveType::ANY; + for (const auto &v : variables) { + if (v->Declaration() != nullptr && v->Declaration()->Node() != nullptr) { + typeIndex = GetTypeIndexFromDeclNode(v->Declaration()->Node(), isNewInstance); + if (typeIndex != PrimitiveType::ANY) { + break; + } + } + } + if (typeIndex == PrimitiveType::ANY) { + auto left = node->AsTSQualifiedName()->Left(); + auto right = node->AsTSQualifiedName()->Right(); + if (left->IsIdentifier()) { + auto redirectPath = recorder_->GetNamespacePath(std::string(left->AsIdentifier()->Name())); + if (redirectPath != "") { + ExternalType externalType(this, right->Name(), util::StringView(redirectPath)); + typeIndex = externalType.GetTypeIndexShift(); + } + } + } + TLOG(node->Type(), typeIndex); + return typeIndex; +} + int64_t TypeExtractor::GetTypeIndexFromAnnotation(const ir::Expression *typeAnnotation) { if (typeAnnotation == nullptr) { @@ -432,6 +527,8 @@ int64_t TypeExtractor::GetTypeIndexFromAnnotation(const ir::Expression *typeAnno case ir::AstNodeType::TS_NULL_KEYWORD: case ir::AstNodeType::TS_UNDEFINED_KEYWORD: return PRIMITIVE_TYPE_MAP.at(typeAnnotation->AsTypeNode()->Type()); + case ir::AstNodeType::TS_LITERAL_TYPE: + return GetTypeIndexFromTSLiteralType(typeAnnotation->AsTSLiteralType()); case ir::AstNodeType::TS_NEVER_KEYWORD: case ir::AstNodeType::TS_UNKNOWN_KEYWORD: return PrimitiveType::ANY; @@ -443,12 +540,18 @@ int64_t TypeExtractor::GetTypeIndexFromAnnotation(const ir::Expression *typeAnno UnionType unionType(this, typeAnnotation->AsTSUnionType()); return unionType.GetTypeIndexShift(); } - case ir::AstNodeType::TS_PARENT_TYPE: { // (UnionType) + case ir::AstNodeType::TS_PARENT_TYPE: { // (UnionType) / (FunctionType) auto type = typeAnnotation->AsTSParenthesizedType()->Type(); ASSERT(type != nullptr); if (type->IsTSUnionType()) { UnionType unionType(this, type->AsTSUnionType()); return unionType.GetTypeIndexShift(); + } else if (type->IsTSFunctionType()) { + FunctionType functionType(this, type->AsTSFunctionType(), ""); + return functionType.GetTypeIndexShift(); + } else if (type->IsTSConstructorType()) { + FunctionType functionType(this, type->AsTSConstructorType(), ""); + return functionType.GetTypeIndexShift(); } return PrimitiveType::ANY; } @@ -460,15 +563,20 @@ int64_t TypeExtractor::GetTypeIndexFromAnnotation(const ir::Expression *typeAnno ObjectType objectType(this, nullptr); // let a : object return objectType.GetTypeIndexShift(); } + case ir::AstNodeType::TS_FUNCTION_TYPE: { // FunctionType, let a : () => {} + FunctionType functionType(this, typeAnnotation->AsTSFunctionType(), ""); + return functionType.GetTypeIndexShift(); + } + case ir::AstNodeType::TS_CONSTRUCTOR_TYPE: { // FunctionType, let a : new () => {} + FunctionType functionType(this, typeAnnotation->AsTSConstructorType(), ""); + return functionType.GetTypeIndexShift(); + } case ir::AstNodeType::TS_BIGINT_KEYWORD: case ir::AstNodeType::TS_CONDITIONAL_TYPE: - case ir::AstNodeType::TS_CONSTRUCTOR_TYPE: - case ir::AstNodeType::TS_FUNCTION_TYPE: case ir::AstNodeType::TS_IMPORT_TYPE: case ir::AstNodeType::TS_INDEXED_ACCESS_TYPE: case ir::AstNodeType::TS_INTERSECTION_TYPE: case ir::AstNodeType::TS_INFER_TYPE: - case ir::AstNodeType::TS_LITERAL_TYPE: case ir::AstNodeType::TS_MAPPED_TYPE: case ir::AstNodeType::TS_OPTIONAL_TYPE: case ir::AstNodeType::TS_REST_TYPE: @@ -515,7 +623,12 @@ int64_t TypeExtractor::GetTypeIndexFromInitializer(const ir::Expression *initial // Identifier here is a reference identifier binding to decl node which also contains variable auto declNode = GetDeclNodeFromInitializer(initializer, &identifier); if (declNode != nullptr) { - typeIndex = GetTypeIndexFromDeclNode(declNode, initializer->IsNewExpression()); + if (initializer->IsNewExpression() && initializer->AsNewExpression()->TypeParams() != nullptr) { + typeIndex = GetTypeIndexFromGenericInst(GetTypeIndexFromDeclNode(declNode, false), + initializer->AsNewExpression()->TypeParams()); + } else { + typeIndex = GetTypeIndexFromDeclNode(declNode, initializer->IsNewExpression()); + } recorder_->SetIdentifierTypeIndex(identifier, recorder_->GetClassType(typeIndex)); } TLOG(initializer->Type(), typeIndex); @@ -646,11 +759,20 @@ int64_t TypeExtractor::GetTypeIndexFromTypeReference(const ir::TSTypeReference * auto typeName = typeReference->TypeName(); ASSERT(typeName != nullptr); if (typeName->IsIdentifier()) { - // Special case for Builtin - auto typeIndexBuiltin = GetTypeIndexFromBuiltin(typeName->AsIdentifier()->Name(), typeReference->TypeParams()); + const auto &name = typeName->AsIdentifier()->Name(); + // First, consider if the type identify is Builtin Type + auto typeIndexBuiltin = GetTypeIndexFromBuiltin(name, typeReference->TypeParams()); if (typeIndexBuiltin != PrimitiveType::ANY) { return typeIndexBuiltin; } + // Second, consider if the type identify is Generic Type + auto genericParamTypeMap = GetGenericParamTypeMap(); + if (genericParamTypeMap != nullptr) { + auto t = genericParamTypeMap->find(name); + if (t != genericParamTypeMap->end()) { + return t->second; + } + } } const ir::Identifier *identifier = nullptr; @@ -658,13 +780,35 @@ int64_t TypeExtractor::GetTypeIndexFromTypeReference(const ir::TSTypeReference * // Identifier here is a reference identifier binding to decl node which also contains variable auto declNode = GetDeclNodeFromInitializer(typeName, &identifier); if (declNode != nullptr) { - auto typeIndex = GetTypeIndexFromDeclNode(declNode, true); + int64_t typeIndex = PrimitiveType::ANY; + if (typeReference->TypeParams() != nullptr) { + typeIndex = GetTypeIndexFromGenericInst(GetTypeIndexFromDeclNode(declNode, false), + typeReference->TypeParams()); + } else { + typeIndex = GetTypeIndexFromDeclNode(declNode, true); + } recorder_->SetIdentifierTypeIndex(identifier, recorder_->GetClassType(typeIndex)); return typeIndex; } return PrimitiveType::ANY; } +int64_t TypeExtractor::GetTypeIndexFromTSLiteralType(const ir::TSLiteralType *tsLiteralType) +{ + switch (tsLiteralType->Literal()->Type()) { + case ir::AstNodeType::NUMBER_LITERAL: + return PrimitiveType::NUMBER; + case ir::AstNodeType::BOOLEAN_LITERAL: + return PrimitiveType::BOOLEAN; + case ir::AstNodeType::STRING_LITERAL: + return PrimitiveType::STRING; + case ir::AstNodeType::NULL_LITERAL: + return PrimitiveType::NUL; + default: + return PrimitiveType::ANY; + } +} + int64_t TypeExtractor::GetTypeIndexFromBuiltin(const util::StringView &name, const ir::TSTypeParameterInstantiation *node) { @@ -681,7 +825,7 @@ int64_t TypeExtractor::GetTypeIndexFromBuiltin(const util::StringView &name, int64_t TypeExtractor::GetTypeIndexFromBuiltinInst(int64_t typeIndexBuiltin, const ir::TSTypeParameterInstantiation *node) { - std::vector allTypes = { typeIndexBuiltin }; + std::vector allTypes = {typeIndexBuiltin}; for (const auto &t : node->Params()) { allTypes.emplace_back(GetTypeIndexFromAnnotation(t)); } @@ -695,6 +839,23 @@ int64_t TypeExtractor::GetTypeIndexFromBuiltinInst(int64_t typeIndexBuiltin, return GetTypeIndexFromClassInst(builtinInstType.GetTypeIndexShift()); } +int64_t TypeExtractor::GetTypeIndexFromGenericInst(int64_t typeIndexGeneric, + const ir::TSTypeParameterInstantiation *node) +{ + std::vector allTypes = {typeIndexGeneric}; + for (const auto &t : node->Params()) { + allTypes.emplace_back(GetTypeIndexFromAnnotation(t)); + } + auto typeIndex = recorder_->GetGenericInst(allTypes); + if (typeIndex != PrimitiveType::ANY) { + return typeIndex; + } + + // New instance for generic type + GenericInstType genericInstType(this, allTypes); + return GetTypeIndexFromClassInst(genericInstType.GetTypeIndexShift()); +} + bool TypeExtractor::IsExportNode(const ir::AstNode *node) const { auto parent = node->Parent(); @@ -727,6 +888,71 @@ bool TypeExtractor::IsDeclareNode(const ir::AstNode *node) const return false; } +void TypeExtractor::GetVariablesFromTSQualifiedNodes(const binder::Variable *variable, + ArenaDeque &identifiers, ArenaVector &variables) const +{ + ASSERT(variable != nullptr); + + if (identifiers.empty()) { + variables.emplace_back(variable); + return; + } + switch (variable->Type()) { + case binder::VariableType::ENUMLITERAL: { + auto name = identifiers.front()->Name(); + identifiers.pop_front(); + auto findRes = variable->AsEnumLiteralVariable()->FindEnumMemberVariable(name); + if (findRes != nullptr) { + GetVariablesFromTSQualifiedNodes(findRes, identifiers, variables); + } + break; + } + case binder::VariableType::NAMESPACE: { + auto exportBindings = variable->AsNamespaceVariable()->GetExportBindings(); + if (exportBindings != nullptr) { + ArenaVector findRes(recorder_->Allocator()->Adapter()); + auto fn = [&findRes](binder::Variable *variable) { + if (variable != nullptr) { + findRes.emplace_back(variable); + } + }; + + auto name = identifiers.front()->Name(); + if (identifiers.size() == 1U) { + fn(exportBindings->FindExportVariable(name)); + } else { + fn(exportBindings->FindExportTSVariable(name)); + } + fn(exportBindings->FindExportTSVariable(name)); + fn(exportBindings->FindExportTSVariable(name)); + + identifiers.pop_front(); + for (const auto &v : findRes) { + GetVariablesFromTSQualifiedNodes(v, identifiers, variables); + } + } + break; + } + case binder::VariableType::IMPORT_EQUALS: { + auto ref = variable->Declaration()->Node()->Parent()->AsTSImportEqualsDeclaration()->ModuleReference(); + while (ref->IsTSQualifiedName()) { + identifiers.emplace_front(ref->AsTSQualifiedName()->Right()); + ref = ref->AsTSQualifiedName()->Left(); + } + + ASSERT(ref->IsIdentifier()); + for (const auto &v : ref->AsIdentifier()->TSVariables()) { + if (v->Name() == ref->AsIdentifier()->Name()) { + GetVariablesFromTSQualifiedNodes(v, identifiers, variables); + } + } + break; + } + default: + break; + } +} + // static int64_t TypeExtractor::GetBuiltinTypeIndex(util::StringView name) { diff --git a/es2panda/typescript/extractor/typeExtractor.h b/es2panda/typescript/extractor/typeExtractor.h index 202afb937ed9164d97b435a110ac899f02fc2d79..51d4fd245b6e6e3abb1320d84be62b9f6acaab52 100644 --- a/es2panda/typescript/extractor/typeExtractor.h +++ b/es2panda/typescript/extractor/typeExtractor.h @@ -45,6 +45,16 @@ public: int64_t GetTypeIndexFromIdentifier(const ir::Identifier *identifier); int64_t GetTypeIndexFromInitializer(const ir::Expression *initializer); + void SetGenericParamTypeMap(const ArenaMap *genericParamTypeMap) + { + genericParamTypeMap_ = genericParamTypeMap; + } + + const ArenaMap *GetGenericParamTypeMap() const + { + return genericParamTypeMap_; + } + static int64_t GetBuiltinTypeIndex(util::StringView name); private: @@ -54,6 +64,7 @@ private: std::unique_ptr recorder_; std::unordered_map getterMap_; std::unordered_map handlerMap_; + const ArenaMap *genericParamTypeMap_; void ExtractNodesType(const ir::AstNode *parent); void ExtractNodeType(const ir::AstNode *parent, const ir::AstNode *childNode); @@ -68,9 +79,13 @@ private: int64_t GetTypeIndexFromClassExpression(const ir::AstNode *node, bool isNewInstance); int64_t GetTypeIndexFromClassDefinition(const ir::AstNode *node, bool isNewInstance); int64_t GetTypeIndexFromInterfaceNode(const ir::AstNode *node, bool isNewInstance); + int64_t GetTypeIndexFromFunctionNode(const ir::AstNode *node, [[maybe_unused]] bool isNewInstance); int64_t GetTypeIndexFromImportNode(const ir::AstNode *node, [[maybe_unused]] bool isNewInstance); int64_t GetTypeIndexFromTypeAliasNode(const ir::AstNode *node, [[maybe_unused]] bool isNewInstance); + int64_t GetTypeIndexFromAsNode(const ir::AstNode *node, [[maybe_unused]] bool isNewInstance); + int64_t GetTypeIndexFromAssertionNode(const ir::AstNode *node, [[maybe_unused]] bool isNewInstance); int64_t GetTypeIndexFromMemberNode(const ir::AstNode *node, [[maybe_unused]] bool isNewInstance); + int64_t GetTypeIndexFromTSQualifiedNode(const ir::AstNode *node, bool isNewInstance); void HandleVariableDeclaration(const ir::AstNode *node); void HandleFunctionDeclaration(const ir::AstNode *node); @@ -81,14 +96,41 @@ private: // Helpers int64_t GetTypeIndexFromClassInst(int64_t typeIndex); int64_t GetTypeIndexFromTypeReference(const ir::TSTypeReference *typeReference); + int64_t GetTypeIndexFromTSLiteralType(const ir::TSLiteralType *tsLiteralType); - // Builtin Helpers + // Builtin and Generic Helpers int64_t GetTypeIndexFromBuiltin(const util::StringView &name, const ir::TSTypeParameterInstantiation *node); int64_t GetTypeIndexFromBuiltinInst(int64_t typeIndexBuiltin, const ir::TSTypeParameterInstantiation *node); + int64_t GetTypeIndexFromGenericInst(int64_t typeIndexGeneric, const ir::TSTypeParameterInstantiation *node); // Other Helpers bool IsExportNode(const ir::AstNode *node) const; bool IsDeclareNode(const ir::AstNode *node) const; + void GetVariablesFromTSQualifiedNodes(const binder::Variable *variable, + ArenaDeque &identifiers, ArenaVector &variables) const; +}; + +class GenericParamTypeBindScope { +public: + GenericParamTypeBindScope() = delete; + + explicit GenericParamTypeBindScope(TypeExtractor *extractor, + const ArenaMap *genericParamTypeMap) : extractor_(extractor) + { + ASSERT(extractor_ != nullptr); + extractor_->SetGenericParamTypeMap(genericParamTypeMap); + } + + ~GenericParamTypeBindScope() + { + extractor_->SetGenericParamTypeMap(nullptr); + } + + NO_COPY_SEMANTIC(GenericParamTypeBindScope); + NO_MOVE_SEMANTIC(GenericParamTypeBindScope); + +private: + TypeExtractor *extractor_; }; } // namespace panda::es2panda::extractor diff --git a/es2panda/typescript/extractor/typeRecorder.cpp b/es2panda/typescript/extractor/typeRecorder.cpp index a09cfa91fa0312c3139286c1242af444872233ca..2098a409ba14884add857c4153a7a55f372a5506 100644 --- a/es2panda/typescript/extractor/typeRecorder.cpp +++ b/es2panda/typescript/extractor/typeRecorder.cpp @@ -174,6 +174,26 @@ void TypeRecorder::SetBuiltinInst(const std::vector &allTypes, int64_t builtinInst_[allTypes] = instIndex; } +int64_t TypeRecorder::GetGenericInst(const std::vector &allTypes) const +{ + return FindValue(genericInst_, allTypes, PRIMITIVETYPE_ANY); +} + +void TypeRecorder::SetGenericInst(const std::vector &allTypes, int64_t instIndex) +{ + genericInst_[allTypes] = instIndex; +} + +int64_t TypeRecorder::GetIndexSig(int64_t refIndex) const +{ + return FindValue(indexSig_, refIndex, PRIMITIVETYPE_ANY); +} + +void TypeRecorder::SetIndexSig(int64_t refIndex, int64_t indexSigIndex) +{ + indexSig_[refIndex] = indexSigIndex; +} + int64_t TypeRecorder::GetClassInst(int64_t classIndex) const { return FindValue(classInst_, classIndex, PRIMITIVETYPE_ANY); @@ -232,6 +252,16 @@ void TypeRecorder::SetObjectType(const std::string &objectStr, int64_t objectInd objectType_[objectStr] = objectIndex; } +int64_t TypeRecorder::GetFunctionType(const std::string &functionStr) const +{ + return FindValue(functionType_, functionStr, PRIMITIVETYPE_ANY); +} + +void TypeRecorder::SetFunctionType(const std::string &functionStr, int64_t functionIndex) +{ + functionType_[functionStr] = functionIndex; +} + int64_t TypeRecorder::GetExportType(const std::string &exportStr) const { return FindValue(exportType_, exportStr, PRIMITIVETYPE_ANY); @@ -306,7 +336,14 @@ ALWAYS_INLINE void TypeRecorder::Dump(const parser::Program *program) const for (const auto &p : t.first) { std::cout << p << " "; } - std::cout << t.second << std::endl; + std::cout << ": " << t.second << std::endl; + } + std::cout << "---------- genericInst_ ----------" << std::endl; + for (const auto &t : genericInst_) { + for (const auto &p : t.first) { + std::cout << p << " "; + } + std::cout << ": " << t.second << std::endl; } auto fn = [](const auto &map) { @@ -314,6 +351,9 @@ ALWAYS_INLINE void TypeRecorder::Dump(const parser::Program *program) const std::cout << t.first << " : " << t.second << std::endl; } }; + std::cout << "---------- indexSig_ ----------" << std::endl; + std::cout << "---- ref ---- | ---- indexSig ----" << std::endl; + fn(indexSig_); std::cout << "---------- classInst_ ----------" << std::endl; std::cout << "---- class ---- | ---- inst ----" << std::endl; fn(classInst_); @@ -326,6 +366,8 @@ ALWAYS_INLINE void TypeRecorder::Dump(const parser::Program *program) const fn(unionType_); std::cout << "---------- objectType_ ----------" << std::endl; fn(objectType_); + std::cout << "---------- functionType_ ----------" << std::endl; + fn(functionType_); std::cout << "---------- exportType_ ----------" << std::endl; fn(exportType_); std::cout << "---------- declareType_ ----------" << std::endl; diff --git a/es2panda/typescript/extractor/typeRecorder.h b/es2panda/typescript/extractor/typeRecorder.h index 31ac9350ae7ff03417e0fffba6ecc6159b083497..11519d490f113abe21265e59d17f8d1c64db0ab0 100644 --- a/es2panda/typescript/extractor/typeRecorder.h +++ b/es2panda/typescript/extractor/typeRecorder.h @@ -73,6 +73,12 @@ public: int64_t GetBuiltinInst(const std::vector &allTypes) const; void SetBuiltinInst(const std::vector &allTypes, int64_t instIndex); + int64_t GetGenericInst(const std::vector &allTypes) const; + void SetGenericInst(const std::vector &allTypes, int64_t instIndex); + + int64_t GetIndexSig(int64_t refIndex) const; + void SetIndexSig(int64_t refIndex, int64_t indexSigIndex); + int64_t GetClassInst(int64_t classIndex) const; void SetClassInst(int64_t classIndex, int64_t instIndex); @@ -88,6 +94,9 @@ public: int64_t GetObjectType(const std::string &objectStr) const; void SetObjectType(const std::string &objectStr, int64_t objectIndex); + int64_t GetFunctionType(const std::string &functionStr) const; + void SetFunctionType(const std::string &functionStr, int64_t functionIndex); + int64_t GetExportType(const std::string &exportStr) const; void SetExportType(const std::string &exportStr, int64_t exportIndex); @@ -118,11 +127,14 @@ private: std::unordered_map nodeTypeIndex_ {}; std::unordered_map variableTypeIndex_ {}; std::map, int64_t> builtinInst_ {}; + std::map, int64_t> genericInst_ {}; + std::unordered_map indexSig_ {}; std::unordered_map classInst_ {}; std::unordered_map classType_ {}; std::unordered_map arrayType_ {}; std::unordered_map unionType_ {}; std::unordered_map objectType_ {}; + std::unordered_map functionType_ {}; // Export symbols std::unordered_map exportType_ {}; std::unordered_map declareType_ {}; diff --git a/es2panda/typescript/extractor/typeSystem.h b/es2panda/typescript/extractor/typeSystem.h index c37d41029ff6964f094810cf7d4a308871c4afbe..c7fb96430c6e9958e1f3da3af5d33e4f3ff5f649 100644 --- a/es2panda/typescript/extractor/typeSystem.h +++ b/es2panda/typescript/extractor/typeSystem.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -42,7 +46,10 @@ #include #include #include +#include #include +#include +#include #include namespace panda::es2panda::extractor { @@ -210,14 +217,17 @@ enum UserType : uint8_t { OBJECT, EXTERNAL, INTERFACE, - BUILTININST + BUILTININST, + GENERICINST, + INDEXSIG }; enum Modifier : uint8_t { NONSTATIC = 0, STATIC = 1 << 2, ASYNC = 1 << 3, - GENERATOR = 1 << 4 + GENERATOR = 1 << 4, + ACCESSOR = 1 << 5 }; enum ModifierAB : uint8_t { @@ -297,6 +307,15 @@ protected: } return ss.str(); } + + void CalculateParamTypes(ArenaMap ¶mTypes, + const ir::TSTypeParameterDeclaration *typeParams) + { + int64_t index = 0; + for (const auto &t : typeParams->Params()) { + paramTypes[t->Name()->Name()] = (--index); + } + } }; class TypeCounter : public BaseType { @@ -344,16 +363,66 @@ private: int64_t typeIndexPlaceHolder_ = PrimitiveType::ANY; }; -// For { MethodDefinition / FunctionDeclaration / FunctionExpression } -> ScriptFunction / TSMethodSignature +class IndexSigType : public BaseType { +public: + explicit IndexSigType(TypeExtractor *extractor, int64_t typeIndexRefShift, + const ArenaMap *indexSignatures) + : BaseType(extractor), typeIndexRefShift_(typeIndexRefShift) + { + typeIndex_ = recorder_->AddLiteralBuffer(buffer_); + typeIndexShift_ = typeIndex_ + recorder_->GetUserTypeIndexShift(); + recorder_->SetIndexSig(typeIndexRefShift_, typeIndexShift_); + recorder_->AddUserType(typeIndexShift_); + + FillLiteralBuffer(indexSignatures); + } + ~IndexSigType() = default; + NO_COPY_SEMANTIC(IndexSigType); + NO_MOVE_SEMANTIC(IndexSigType); + + int64_t GetTypeIndexShift() const + { + return typeIndexShift_; + } + +private: + int64_t typeIndexRefShift_ = PrimitiveType::ANY; + int64_t typeIndex_ = PrimitiveType::ANY; + int64_t typeIndexShift_ = PrimitiveType::ANY; + + void FillLiteralBuffer(const ArenaMap *indexSignatures) + { + buffer_->Add(recorder_->Allocator()->New(UserType::INDEXSIG)); + buffer_->Add(recorder_->Allocator()->New(typeIndexRefShift_)); + + ASSERT(indexSignatures != nullptr); + buffer_->Add(recorder_->Allocator()->New(indexSignatures->size())); + std::for_each(indexSignatures->begin(), indexSignatures->end(), [this](const auto &t) { + buffer_->Add(recorder_->Allocator()->New(t.first)); + buffer_->Add(recorder_->Allocator()->New(t.second)); + }); + } +}; + +// 8 types of AstNode to create FunctionType +// For { MethodDefinition / FunctionDeclaration / FunctionExpression / ArrowFunctionExpression } +// which contains ScriptFunction +// For { TSMethodSignature / TSSignatureDeclaration / TSFunctionType / TSConstructorType } +// which only contains Signature class FunctionType : public BaseType { public: explicit FunctionType(TypeExtractor *extractor, const ir::AstNode *node, const util::StringView &name) : BaseType(extractor), paramsTypeIndex_(recorder_->Allocator()->Adapter()) { - CalculateIndex(name, typeIndex_, typeIndexShift_, !(node->IsTSMethodSignature())); name_ = name; auto fn = [this](const auto *func) { + typeIndexShift_ = recorder_->GetNodeTypeIndex(func); + if (typeIndexShift_ != PrimitiveType::ANY) { + return; + } + + CalculateIndex(name_, typeIndex_, typeIndexShift_, !(func->IsTSMethodSignature())); recorder_->SetNodeTypeIndex(func, typeIndexShift_); recorder_->AddUserType(typeIndexShift_); if constexpr (std::is_same_v) { @@ -366,6 +435,7 @@ public: FillReturn(func); FillLiteralBuffer(); }; + if (node->IsMethodDefinition()) { auto methodDef = node->AsMethodDefinition(); auto modifiers = methodDef->Modifiers(); @@ -378,13 +448,20 @@ public: if (methodDef->IsStatic()) { modifier_ += Modifier::STATIC; } - fn(node->AsMethodDefinition()->Function()); + if (methodDef->IsAccessor()) { + modifier_ += Modifier::ACCESSOR; + } + fn(methodDef->Function()); } else if (node->IsFunctionDeclaration()) { fn(node->AsFunctionDeclaration()->Function()); } else if (node->IsFunctionExpression()) { fn(node->AsFunctionExpression()->Function()); + } else if (node->IsArrowFunctionExpression()) { + fn(node->AsArrowFunctionExpression()->Function()); } else if (node->IsTSMethodSignature()) { fn(node->AsTSMethodSignature()); + } else if (node->IsTSSignatureDeclaration() || node->IsTSFunctionType() || node->IsTSConstructorType()) { + HandleFuncNodeWithoutName(node); } } ~FunctionType() = default; @@ -411,6 +488,33 @@ private: int64_t typeIndex_ = PrimitiveType::ANY; int64_t typeIndexShift_ = PrimitiveType::ANY; + void HandleFuncNodeWithoutName(const ir::AstNode *node) + { + ir::AstDumper dumper(node); + auto functionStr = dumper.Str(); + typeIndexShift_ = recorder_->GetFunctionType(functionStr); + if (typeIndexShift_ != PrimitiveType::ANY) { + return; + } + + typeIndex_ = recorder_->AddLiteralBuffer(buffer_); + typeIndexShift_ = typeIndex_ + recorder_->GetUserTypeIndexShift(); + recorder_->SetFunctionType(functionStr, typeIndexShift_); + recorder_->AddUserType(typeIndexShift_); + + if (node->IsTSSignatureDeclaration()) { + FillParameters(node->AsTSSignatureDeclaration()); + FillReturn(node->AsTSSignatureDeclaration()); + } else if (node->IsTSFunctionType()) { + FillParameters(node->AsTSFunctionType()); + FillReturn(node->AsTSFunctionType()); + } else { + FillParameters(node->AsTSConstructorType()); + FillReturn(node->AsTSConstructorType()); + } + FillLiteralBuffer(); + } + void FillModifier(const ir::ScriptFunction *scriptFunc) { if (scriptFunc->IsAsync()) { @@ -475,31 +579,46 @@ private: } }; -// For { ClassDeclaration / ClassExpression } -> ClassDefinition +// 2 types of AstNode to create ClassType +// For { ClassDeclaration / ClassExpression } +// which contains ClassDefinition class ClassType : public BaseType { public: explicit ClassType(TypeExtractor *extractor, const ir::ClassDefinition *classDef, const util::StringView &name) : BaseType(extractor), implementsHeritages_(recorder_->Allocator()->Adapter()), + paramTypes_(recorder_->Allocator()->Adapter()), staticFields_(recorder_->Allocator()->Adapter()), staticMethods_(recorder_->Allocator()->Adapter()), fields_(recorder_->Allocator()->Adapter()), - methods_(recorder_->Allocator()->Adapter()) + methods_(recorder_->Allocator()->Adapter()), + indexSignatures_(recorder_->Allocator()->Adapter()) { + typeIndexShift_ = recorder_->GetNodeTypeIndex(classDef); + if (typeIndexShift_ != PrimitiveType::ANY) { + return; + } + + if (classDef->TypeParams() != nullptr) { + CalculateParamTypes(paramTypes_, classDef->TypeParams()); + } + CalculateIndex(name, typeIndex_, typeIndexShift_, true); recorder_->SetNodeTypeIndex(classDef, typeIndexShift_); recorder_->AddUserType(typeIndexShift_); + GenericParamTypeBindScope scope(extractor, ¶mTypes_); FillModifier(classDef); FillHeritages(classDef); FillFieldsandMethods(classDef); + FillIndexSignatures(classDef); FillLiteralBuffer(); } ~ClassType() = default; NO_COPY_SEMANTIC(ClassType); NO_MOVE_SEMANTIC(ClassType); - int64_t GetTypeIndexShift() + int64_t GetTypeIndexShift() const { return typeIndexShift_; } @@ -508,12 +627,14 @@ private: ModifierAB modifierAB_ = ModifierAB::NONABSTRACT; int64_t extendsHeritage_ = PrimitiveType::ANY; ArenaVector implementsHeritages_; + ArenaMap paramTypes_; // 3 field infos, typeIndex / accessFlag / modifier ArenaMap> staticFields_; ArenaMap staticMethods_; // 3 field infos, typeIndex / accessFlag / modifier ArenaMap> fields_; ArenaMap methods_; + ArenaMap indexSignatures_; int64_t typeIndex_ = PrimitiveType::ANY; int64_t typeIndexShift_ = PrimitiveType::ANY; @@ -629,6 +750,21 @@ private: } } + void FillIndexSignatures(const ir::ClassDefinition *classDef) + { + for (const auto &t : classDef->IndexSignatures()) { + auto key = t->Param()->AsIdentifier()->TypeAnnotation(); + indexSignatures_[extractor_->GetTypeIndexFromAnnotation(key)] = + extractor_->GetTypeIndexFromAnnotation(t->TypeAnnotation()); + } + if (indexSignatures_.size() > 0U) { + // Update current type to IndexSignture Type + IndexSigType indexSigType(extractor_, typeIndexShift_, &indexSignatures_); + typeIndexShift_ = indexSigType.GetTypeIndexShift(); + recorder_->SetNodeTypeIndex(classDef, typeIndexShift_); + } + } + void FillFieldsLiteralBuffer(bool isStatic) { // 3 field infos, typeIndex / accessFlag / modifier @@ -723,31 +859,45 @@ public: const util::StringView &name) : BaseType(extractor), heritages_(recorder_->Allocator()->Adapter()), + paramTypes_(recorder_->Allocator()->Adapter()), fields_(recorder_->Allocator()->Adapter()), - methods_(recorder_->Allocator()->Adapter()) + methods_(recorder_->Allocator()->Adapter()), + indexSignatures_(recorder_->Allocator()->Adapter()) { + typeIndexShift_ = recorder_->GetNodeTypeIndex(interfaceDef); + if (typeIndexShift_ != PrimitiveType::ANY) { + return; + } + + if (interfaceDef->TypeParams() != nullptr) { + CalculateParamTypes(paramTypes_, interfaceDef->TypeParams()); + } + CalculateIndex(name, typeIndex_, typeIndexShift_, true); recorder_->SetNodeTypeIndex(interfaceDef, typeIndexShift_); recorder_->AddUserType(typeIndexShift_); + GenericParamTypeBindScope scope(extractor, ¶mTypes_); FillHeritages(interfaceDef); - FillFieldsandMethods(interfaceDef); + FillMembers(interfaceDef); FillLiteralBuffer(); } ~InterfaceType() = default; NO_COPY_SEMANTIC(InterfaceType); NO_MOVE_SEMANTIC(InterfaceType); - int64_t GetTypeIndexShift() + int64_t GetTypeIndexShift() const { return typeIndexShift_; } private: ArenaVector heritages_; + ArenaMap paramTypes_; // 3 field infos, typeIndex / accessFlag / modifier ArenaMap> fields_; - ArenaMap methods_; + ArenaVector methods_; + ArenaMap indexSignatures_; int64_t typeIndex_ = PrimitiveType::ANY; int64_t typeIndexShift_ = PrimitiveType::ANY; @@ -755,7 +905,8 @@ private: { for (const auto &t : interfaceDef->Extends()) { if (t != nullptr) { - heritages_.emplace_back(extractor_->GetTypeIndexFromInitializer(t)); + // TSTypeReference + heritages_.emplace_back(extractor_->GetTypeIndexFromAnnotation(t->Expr())); } } } @@ -790,27 +941,50 @@ private: if (std::holds_alternative(res)) { auto name = std::get(res); FunctionType functionType(extractor_, method, name); - methods_[name] = recorder_->GetNodeTypeIndex(method); + methods_.emplace_back(recorder_->GetNodeTypeIndex(method)); } else { auto identifier = std::get(res); if (identifier != nullptr) { auto name = identifier->Name(); FunctionType functionType(extractor_, method, name); recorder_->SetIdentifierTypeIndex(identifier, functionType.GetTypeIndexShift()); - methods_[name] = recorder_->GetNodeTypeIndex(method); + methods_.emplace_back(recorder_->GetNodeTypeIndex(method)); } } } - void FillFieldsandMethods(const ir::TSInterfaceDeclaration *interfaceDef) + void FillMethod(const ir::TSSignatureDeclaration *method) + { + FunctionType functionType(extractor_, method, ""); + methods_.emplace_back(recorder_->GetNodeTypeIndex(method)); + } + + void FillIndexSignature(const ir::TSIndexSignature *indexSignature) + { + auto key = indexSignature->Param()->AsIdentifier()->TypeAnnotation(); + indexSignatures_[extractor_->GetTypeIndexFromAnnotation(key)] = + extractor_->GetTypeIndexFromAnnotation(indexSignature->TypeAnnotation()); + } + + void FillMembers(const ir::TSInterfaceDeclaration *interfaceDef) { for (const auto &t : interfaceDef->Body()->Body()) { if (t->IsTSPropertySignature()) { FillField(t->AsTSPropertySignature()); } else if (t->IsTSMethodSignature()) { FillMethod(t->AsTSMethodSignature()); + } else if (t->IsTSSignatureDeclaration()) { + FillMethod(t->AsTSSignatureDeclaration()); + } else if (t->IsTSIndexSignature()) { + FillIndexSignature(t->AsTSIndexSignature()); } } + if (indexSignatures_.size() > 0U) { + // Update current type to IndexSignture Type + IndexSigType indexSigType(extractor_, typeIndexShift_, &indexSignatures_); + typeIndexShift_ = indexSigType.GetTypeIndexShift(); + recorder_->SetNodeTypeIndex(interfaceDef, typeIndexShift_); + } } void FillFieldsLiteralBuffer() @@ -828,8 +1002,7 @@ private: { buffer_->Add(recorder_->Allocator()->New(methods_.size())); std::for_each(methods_.begin(), methods_.end(), [this](const auto &t) { - buffer_->Add(recorder_->Allocator()->New(t.first)); - buffer_->Add(recorder_->Allocator()->New(t.second)); + buffer_->Add(recorder_->Allocator()->New(t)); }); } @@ -864,7 +1037,7 @@ public: NO_COPY_SEMANTIC(ExternalType); NO_MOVE_SEMANTIC(ExternalType); - int64_t GetTypeIndexShift() + int64_t GetTypeIndexShift() const { return typeIndexShift_; } @@ -904,7 +1077,7 @@ public: NO_COPY_SEMANTIC(UnionType); NO_MOVE_SEMANTIC(UnionType); - int64_t GetTypeIndexShift() + int64_t GetTypeIndexShift() const { return typeIndexShift_; } @@ -952,7 +1125,7 @@ public: NO_COPY_SEMANTIC(ArrayType); NO_MOVE_SEMANTIC(ArrayType); - int64_t GetTypeIndexShift() + int64_t GetTypeIndexShift() const { return typeIndexShift_; } @@ -972,7 +1145,10 @@ private: class ObjectType : public BaseType { public: explicit ObjectType(TypeExtractor *extractor, const ir::TSTypeLiteral *literalDef) - : BaseType(extractor), properties_(recorder_->Allocator()->Adapter()) + : BaseType(extractor), + properties_(recorder_->Allocator()->Adapter()), + methods_(recorder_->Allocator()->Adapter()), + indexSignatures_(recorder_->Allocator()->Adapter()) { std::string objectStr = "object"; if (literalDef != nullptr) { @@ -989,7 +1165,7 @@ public: recorder_->AddUserType(typeIndexShift_); if (literalDef != nullptr) { - FillMembers(literalDef); + FillMembers(literalDef, objectStr); } FillLiteralBuffer(); } @@ -997,17 +1173,50 @@ public: NO_COPY_SEMANTIC(ObjectType); NO_MOVE_SEMANTIC(ObjectType); - int64_t GetTypeIndexShift() + int64_t GetTypeIndexShift() const { return typeIndexShift_; } private: ArenaMap properties_; + ArenaVector methods_; + ArenaMap indexSignatures_; int64_t typeIndex_ = PrimitiveType::ANY; int64_t typeIndexShift_ = PrimitiveType::ANY; - void FillMembers(const ir::TSTypeLiteral *literalDef) + void FillMethod(const ir::TSMethodSignature *method) + { + auto res = CalculateName(method->Key()); + if (std::holds_alternative(res)) { + auto name = std::get(res); + FunctionType functionType(extractor_, method, name); + methods_.emplace_back(recorder_->GetNodeTypeIndex(method)); + } else { + auto identifier = std::get(res); + if (identifier != nullptr) { + auto name = identifier->Name(); + FunctionType functionType(extractor_, method, name); + recorder_->SetIdentifierTypeIndex(identifier, functionType.GetTypeIndexShift()); + methods_.emplace_back(recorder_->GetNodeTypeIndex(method)); + } + } + } + + void FillMethod(const ir::TSSignatureDeclaration *method) + { + FunctionType functionType(extractor_, method, ""); + methods_.emplace_back(recorder_->GetNodeTypeIndex(method)); + } + + void FillIndexSignature(const ir::TSIndexSignature *indexSignature) + { + auto key = indexSignature->Param()->AsIdentifier()->TypeAnnotation(); + indexSignatures_[extractor_->GetTypeIndexFromAnnotation(key)] = + extractor_->GetTypeIndexFromAnnotation(indexSignature->TypeAnnotation()); + } + + void FillMembers(const ir::TSTypeLiteral *literalDef, const std::string &objectStr) { auto fn = [this](const auto *property, int64_t typeIndex) { auto res = CalculateName(property->Key()); @@ -1028,11 +1237,20 @@ private: int64_t typeIndex = extractor_->GetTypeIndexFromAnnotation(property->TypeAnnotation()); fn(property, typeIndex); } else if (t->IsTSMethodSignature()) { - auto property = t->AsTSMethodSignature(); - int64_t typeIndex = extractor_->GetTypeIndexFromAnnotation(property->ReturnTypeAnnotation()); - fn(property, typeIndex); + FillMethod(t->AsTSMethodSignature()); + } else if (t->IsTSSignatureDeclaration()) { + FillMethod(t->AsTSSignatureDeclaration()); + } else if (t->IsTSIndexSignature()) { + FillIndexSignature(t->AsTSIndexSignature()); } } + + if (indexSignatures_.size() > 0U) { + // Update current type to IndexSignture Type + IndexSigType indexSigType(extractor_, typeIndexShift_, &indexSignatures_); + typeIndexShift_ = indexSigType.GetTypeIndexShift(); + recorder_->SetObjectType(objectStr, typeIndexShift_); + } } void FillLiteralBuffer() @@ -1043,6 +1261,10 @@ private: buffer_->Add(recorder_->Allocator()->New(t.first)); buffer_->Add(recorder_->Allocator()->New(t.second)); }); + buffer_->Add(recorder_->Allocator()->New(methods_.size())); + std::for_each(methods_.begin(), methods_.end(), [this](const auto &t) { + buffer_->Add(recorder_->Allocator()->New(t)); + }); } }; @@ -1064,7 +1286,7 @@ public: NO_COPY_SEMANTIC(BuiltinInstType); NO_MOVE_SEMANTIC(BuiltinInstType); - int64_t GetTypeIndexShift() + int64_t GetTypeIndexShift() const { return typeIndexShift_; } @@ -1093,6 +1315,53 @@ private: } }; +class GenericInstType : public BaseType { +public: + explicit GenericInstType(TypeExtractor *extractor, const std::vector &allTypes) + : BaseType(extractor), paramTypes_(recorder_->Allocator()->Adapter()) + { + typeIndexGeneric_ = allTypes[0]; + typeIndex_ = recorder_->AddLiteralBuffer(buffer_); + typeIndexShift_ = typeIndex_ + recorder_->GetUserTypeIndexShift(); + recorder_->SetGenericInst(allTypes, typeIndexShift_); + recorder_->AddUserType(typeIndexShift_); + + FillTypes(allTypes); + FillLiteralBuffer(); + } + ~GenericInstType() = default; + NO_COPY_SEMANTIC(GenericInstType); + NO_MOVE_SEMANTIC(GenericInstType); + + int64_t GetTypeIndexShift() const + { + return typeIndexShift_; + } + +private: + ArenaVector paramTypes_; + int64_t typeIndexGeneric_ = PrimitiveType::ANY; + int64_t typeIndex_ = PrimitiveType::ANY; + int64_t typeIndexShift_ = PrimitiveType::ANY; + + void FillTypes(const std::vector &allTypes) + { + for (size_t t = 1; t < allTypes.size(); t++) { + paramTypes_.emplace_back(allTypes[t]); + } + } + + void FillLiteralBuffer() + { + buffer_->Add(recorder_->Allocator()->New(UserType::GENERICINST)); + buffer_->Add(recorder_->Allocator()->New(typeIndexGeneric_)); + buffer_->Add(recorder_->Allocator()->New(paramTypes_.size())); + std::for_each(paramTypes_.begin(), paramTypes_.end(), [this](const auto &t) { + buffer_->Add(recorder_->Allocator()->New(t)); + }); + } +}; + } // namespace panda::es2panda::extractor #endif // ES2PANDA_TYPESCRIPT_EXACTOR_TYPESYSTEM_H