1 /** 2 * Copyright (c) 2021 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_COMPILER_TYPESCRIPT_CHECKER_H 17 #define ES2PANDA_COMPILER_TYPESCRIPT_CHECKER_H 18 19 #include <binder/enumMemberResult.h> 20 #include <typescript/types/globalTypesHolder.h> 21 #include <typescript/types/typeRelation.h> 22 #include <typescript/types/types.h> 23 #include <typescript/core/checkerContext.h> 24 #include <macros.h> 25 #include <util/enumbitops.h> 26 #include <util/ustring.h> 27 28 #include <cstdint> 29 #include <initializer_list> 30 #include <unordered_map> 31 #include <unordered_set> 32 33 namespace panda::es2panda::binder { 34 class Binder; 35 class Decl; 36 class EnumVariable; 37 class FunctionDecl; 38 class LocalVariable; 39 class Scope; 40 class Variable; 41 } // namespace panda::es2panda::binder 42 43 namespace panda::es2panda::ir { 44 class AstNode; 45 class SpreadElement; 46 class AssignmentExpression; 47 class Property; 48 class Expression; 49 class ScriptFunction; 50 class UnaryExpression; 51 class BinaryExpression; 52 class Identifier; 53 class MemberExpression; 54 class TSEnumDeclaration; 55 class TSInterfaceDeclaration; 56 class ObjectExpression; 57 class TSArrayType; 58 class TSUnionType; 59 class TSFunctionType; 60 class TSConstructorType; 61 class TSTypeLiteral; 62 class TSTypeReference; 63 class TSQualifiedName; 64 class TSIndexedAccessType; 65 class TSInterfaceHeritage; 66 class TSTypeQuery; 67 class TSTupleType; 68 class ArrayExpression; 69 class Statement; 70 class TSTypeParameterDeclaration; 71 class TSTypeParameterInstantiation; 72 class BlockStatement; 73 class VariableDeclaration; 74 class IfStatement; 75 class DoWhileStatement; 76 class WhileStatement; 77 class ForUpdateStatement; 78 class ForInStatement; 79 class ForOfStatement; 80 class ReturnStatement; 81 class SwitchStatement; 82 class LabelledStatement; 83 class ThrowStatement; 84 class TryStatement; 85 class TSTypeAliasDeclaration; 86 class TSAsExpression; 87 class ThisExpression; 88 class NewExpression; 89 class FunctionExpression; 90 class AwaitExpression; 91 class UpdateExpression; 92 class ConditionalExpression; 93 class YieldExpression; 94 class ArrowFunctionExpression; 95 class TemplateLiteral; 96 class TaggedTemplateExpression; 97 class TSIndexSignature; 98 class TSSignatureDeclaration; 99 class TSPropertySignature; 100 class TSMethodSignature; 101 class ChainExpression; 102 class VariableDeclarator; 103 104 enum class AstNodeType; 105 } // namespace panda::es2panda::ir 106 107 namespace panda::es2panda::checker { 108 109 using StringLiteralPool = std::unordered_map<util::StringView, Type *>; 110 using NumberLiteralPool = std::unordered_map<double, Type *>; 111 using FunctionParamsResolveResult = std::variant<std::vector<binder::LocalVariable *> &, bool>; 112 using InterfacePropertyMap = std::unordered_map<util::StringView, std::pair<binder::LocalVariable *, InterfaceType *>>; 113 using TypeOrNode = std::variant<Type *, const ir::AstNode *>; 114 using IndexInfoTypePair = std::pair<Type *, Type *>; 115 using PropertyMap = std::unordered_map<util::StringView, binder::LocalVariable *>; 116 using ArgRange = std::pair<uint32_t, uint32_t>; 117 118 class Checker { 119 public: 120 explicit Checker(ArenaAllocator *allocator, binder::Binder *binder); 121 ~Checker() = default; 122 NO_COPY_SEMANTIC(Checker); 123 NO_MOVE_SEMANTIC(Checker); 124 Allocator()125 ArenaAllocator *Allocator() const 126 { 127 return allocator_; 128 } 129 Binder()130 binder::Binder *Binder() 131 { 132 return binder_; 133 } 134 Scope()135 binder::Scope *Scope() const 136 { 137 return scope_; 138 } 139 GlobalNumberType()140 Type *GlobalNumberType() 141 { 142 return globalTypes_->GlobalNumberType(); 143 } 144 GlobalAnyType()145 Type *GlobalAnyType() 146 { 147 return globalTypes_->GlobalAnyType(); 148 } 149 GlobalStringType()150 Type *GlobalStringType() 151 { 152 return globalTypes_->GlobalStringType(); 153 } 154 GlobalSymbolType()155 Type *GlobalSymbolType() 156 { 157 return globalTypes_->GlobalSymbolType(); 158 } 159 GlobalBooleanType()160 Type *GlobalBooleanType() 161 { 162 return globalTypes_->GlobalBooleanType(); 163 } 164 GlobalVoidType()165 Type *GlobalVoidType() 166 { 167 return globalTypes_->GlobalVoidType(); 168 } 169 GlobalNullType()170 Type *GlobalNullType() 171 { 172 return globalTypes_->GlobalNullType(); 173 } 174 GlobalUndefinedType()175 Type *GlobalUndefinedType() 176 { 177 return globalTypes_->GlobalUndefinedType(); 178 } 179 GlobalUnknownType()180 Type *GlobalUnknownType() 181 { 182 return globalTypes_->GlobalUnknownType(); 183 } 184 GlobalNeverType()185 Type *GlobalNeverType() 186 { 187 return globalTypes_->GlobalNeverType(); 188 } 189 GlobalNonPrimitiveType()190 Type *GlobalNonPrimitiveType() 191 { 192 return globalTypes_->GlobalNonPrimitiveType(); 193 } 194 GlobalBigintType()195 Type *GlobalBigintType() 196 { 197 return globalTypes_->GlobalBigintType(); 198 } 199 GlobalFalseType()200 Type *GlobalFalseType() 201 { 202 return globalTypes_->GlobalFalseType(); 203 } 204 GlobalTrueType()205 Type *GlobalTrueType() 206 { 207 return globalTypes_->GlobalTrueType(); 208 } 209 GlobalNumberOrBigintType()210 Type *GlobalNumberOrBigintType() 211 { 212 return globalTypes_->GlobalNumberOrBigintType(); 213 } 214 GlobalStringOrNumberType()215 Type *GlobalStringOrNumberType() 216 { 217 return globalTypes_->GlobalStringOrNumberType(); 218 } 219 GlobalZeroType()220 Type *GlobalZeroType() 221 { 222 return globalTypes_->GlobalZeroType(); 223 } 224 GlobalEmptyStringType()225 Type *GlobalEmptyStringType() 226 { 227 return globalTypes_->GlobalEmptyStringType(); 228 } 229 GlobalZeroBigintType()230 Type *GlobalZeroBigintType() 231 { 232 return globalTypes_->GlobalZeroBigintType(); 233 } 234 GlobalPrimitiveType()235 Type *GlobalPrimitiveType() 236 { 237 return globalTypes_->GlobalPrimitiveType(); 238 } 239 GlobalEmptyTupleType()240 Type *GlobalEmptyTupleType() 241 { 242 return globalTypes_->GlobalEmptyTupleType(); 243 } 244 GlobalEmptyObjectType()245 Type *GlobalEmptyObjectType() 246 { 247 return globalTypes_->GlobalEmptyObjectType(); 248 } 249 GlobalResolvingReturnType()250 Type *GlobalResolvingReturnType() 251 { 252 return globalTypes_->GlobalResolvingReturnType(); 253 } 254 GlobalErrorType()255 Type *GlobalErrorType() 256 { 257 return globalTypes_->GlobalErrorType(); 258 } 259 Context()260 CheckerContext Context() const 261 { 262 return context_; 263 } 264 HasStatus(CheckerStatus status)265 bool HasStatus(CheckerStatus status) 266 { 267 return (context_.Status() & status) != 0; 268 } 269 RemoveStatus(CheckerStatus status)270 void RemoveStatus(CheckerStatus status) 271 { 272 context_.Status() &= ~status; 273 } 274 AddStatus(CheckerStatus status)275 void AddStatus(CheckerStatus status) 276 { 277 context_.Status() |= status; 278 } 279 NumberLiteralMap()280 NumberLiteralPool &NumberLiteralMap() 281 { 282 return numberLiteralMap_; 283 } 284 StringLiteralMap()285 StringLiteralPool &StringLiteralMap() 286 { 287 return stringLiteralMap_; 288 } 289 BigintLiteralMap()290 StringLiteralPool &BigintLiteralMap() 291 { 292 return bigintLiteralMap_; 293 } 294 Relation()295 TypeRelation *Relation() 296 { 297 return relation_; 298 } 299 IdenticalResults()300 RelationHolder &IdenticalResults() 301 { 302 return identicalResults_; 303 } 304 AssignableResults()305 RelationHolder &AssignableResults() 306 { 307 return assignableResults_; 308 } 309 ComparableResults()310 RelationHolder &ComparableResults() 311 { 312 return comparableResults_; 313 } 314 TypeStack()315 std::unordered_set<const void *> &TypeStack() 316 { 317 return typeStack_; 318 } 319 NodeCache()320 std::unordered_map<const ir::AstNode *, Type *> &NodeCache() 321 { 322 return nodeCache_; 323 } 324 325 void StartChecker(); 326 327 Type *CheckTypeCached(const ir::Expression *expr); 328 329 [[noreturn]] void ThrowTypeError(std::string_view message, const lexer::SourcePosition &pos); 330 [[noreturn]] void ThrowTypeError(std::initializer_list<TypeErrorMessageElement> list, 331 const lexer::SourcePosition &pos); 332 333 // Util 334 static bool InAssignment(const ir::AstNode *node); 335 static bool IsAssignmentOperator(lexer::TokenType op); 336 static bool IsLiteralType(const Type *type); 337 static const ir::AstNode *FindAncestorGivenByType(const ir::AstNode *node, ir::AstNodeType type); 338 static const ir::AstNode *FindAncestorUntilGivenType(const ir::AstNode *node, ir::AstNodeType stop); 339 static bool MaybeTypeOfKind(const Type *type, TypeFlag flags); 340 static bool MaybeTypeOfKind(const Type *type, ObjectType::ObjectTypeKind kind); 341 static bool IsConstantMemberAccess(const ir::Expression *expr); 342 static bool IsStringLike(const ir::Expression *expr); 343 static const ir::TSQualifiedName *ResolveLeftMostQualifiedName(const ir::TSQualifiedName *qualifiedName); 344 static const ir::MemberExpression *ResolveLeftMostMemberExpression(const ir::MemberExpression *expr); 345 346 // Helpers 347 void CheckTruthinessOfType(Type *type, lexer::SourcePosition lineInfo); 348 Type *CheckNonNullType(Type *type, lexer::SourcePosition lineInfo); 349 Type *GetBaseTypeOfLiteralType(Type *type); 350 void CheckReferenceExpression(const ir::Expression *expr, const char *invalidReferenceMsg, 351 const char *invalidOptionalChainMsg); 352 void CheckTestingKnownTruthyCallableOrAwaitableType(const ir::Expression *condExpr, Type *type, 353 const ir::AstNode *body); 354 Type *ExtractDefinitelyFalsyTypes(Type *type); 355 Type *RemoveDefinitelyFalsyTypes(Type *type); 356 TypeFlag GetFalsyFlags(Type *type); 357 bool IsVariableUsedInConditionBody(const ir::AstNode *parent, binder::Variable *searchVar); 358 bool FindVariableInBinaryExpressionChain(const ir::AstNode *parent, binder::Variable *searchVar); 359 bool IsVariableUsedInBinaryExpressionChain(const ir::AstNode *parent, binder::Variable *searchVar); 360 [[noreturn]] void ThrowBinaryLikeError(lexer::TokenType op, Type *leftType, Type *rightType, 361 lexer::SourcePosition lineInfo); 362 [[noreturn]] void ThrowAssignmentError(Type *source, Type *target, lexer::SourcePosition lineInfo, 363 bool isAsSrcLeftType = false); 364 void ElaborateElementwise(Type *targetType, const ir::Expression *sourceNode, const lexer::SourcePosition &pos); 365 void InferSimpleVariableDeclaratorType(const ir::VariableDeclarator *declarator); 366 Type *GetTypeOfVariable(binder::Variable *var); 367 Type *GetUnaryResultType(Type *operandType); 368 Type *GetTypeFromClassOrInterfaceReference(const ir::TSTypeReference *node, binder::Variable *var); 369 Type *GetTypeFromTypeAliasReference(const ir::TSTypeReference *node, binder::Variable *var); 370 Type *GetTypeReferenceType(const ir::TSTypeReference *node, binder::Variable *var); 371 372 // Type creation 373 Type *CreateNumberLiteralType(double value); 374 Type *CreateBigintLiteralType(const util::StringView &str, bool negative); 375 Type *CreateStringLiteralType(const util::StringView &str); 376 Type *CreateFunctionTypeWithSignature(Signature *callSignature); 377 Type *CreateConstructorTypeWithSignature(Signature *constructSignature); 378 Type *CreateTupleType(ObjectDescriptor *desc, ArenaVector<ElementFlags> &&elementFlags, ElementFlags combinedFlags, 379 uint32_t minLength, uint32_t fixedLength, bool readonly); 380 Type *CreateTupleType(ObjectDescriptor *desc, ArenaVector<ElementFlags> &&elementFlags, ElementFlags combinedFlags, 381 uint32_t minLength, uint32_t fixedLength, bool readonly, NamedTupleMemberPool &&namedMembers); 382 Type *CreateUnionType(std::initializer_list<Type *> constituentTypes); 383 Type *CreateUnionType(ArenaVector<Type *> &&constituentTypes); 384 Type *CreateUnionType(ArenaVector<Type *> &constituentTypes); 385 Type *CreateObjectTypeWithCallSignature(Signature *callSignature); 386 Type *CreateObjectTypeWithConstructSignature(Signature *constructSignature); 387 388 // Object 389 void ResolvePropertiesOfObjectType(ObjectType *type, const ir::Expression *member, 390 ArenaVector<const ir::TSSignatureDeclaration *> &signatureDeclarations, 391 ArenaVector<const ir::TSIndexSignature *> &indexDeclarations, bool isInterface); 392 void ResolveSignaturesOfObjectType(ObjectType *type, 393 ArenaVector<const ir::TSSignatureDeclaration *> &signatureDeclarations); 394 void ResolveIndexInfosOfObjectType(ObjectType *type, ArenaVector<const ir::TSIndexSignature *> &indexDeclarations); 395 void ResolveDeclaredMembers(InterfaceType *type); 396 bool ValidateInterfaceMemberRedeclaration(ObjectType *type, binder::Variable *prop, 397 const lexer::SourcePosition &locInfo); 398 binder::Variable *GetPropertyOfType(Type *type, const util::StringView &name, bool getPartial = false, 399 binder::VariableFlags propagateFlags = binder::VariableFlags::NONE); 400 binder::Variable *GetPropertyOfUnionType(UnionType *type, const util::StringView &name, bool getPartial, 401 binder::VariableFlags propagateFlags); 402 void CheckIndexConstraints(Type *type); 403 void ResolveStructuredTypeMembers(Type *type); 404 void ResolveUnionTypeMembers(UnionType *type); 405 void ResolveObjectTypeMembers(ObjectType *type); 406 void ResolveInterfaceOrClassTypeMembers(InterfaceType *type); 407 Type *CheckComputedPropertyName(const ir::Expression *key); 408 Type *GetPropertyTypeForIndexType(Type *type, Type *indexType); 409 IndexInfo *GetApplicableIndexInfo(Type *type, Type *indexType); 410 ArenaVector<ObjectType *> GetBaseTypes(InterfaceType *type); 411 412 // Function 413 Type *HandleFunctionReturn(const ir::ScriptFunction *func); 414 void CheckFunctionParameterDeclarations(const ArenaVector<ir::Expression *> ¶ms, SignatureInfo *signatureInfo); 415 std::tuple<binder::LocalVariable *, binder::LocalVariable *, bool> CheckFunctionParameter( 416 const ir::Expression *param, SignatureInfo *signatureInfo); 417 std::tuple<binder::LocalVariable *, binder::LocalVariable *, bool> CheckFunctionIdentifierParameter( 418 const ir::Identifier *param); 419 std::tuple<binder::LocalVariable *, binder::LocalVariable *, bool> CheckFunctionAssignmentPatternParameter( 420 const ir::AssignmentExpression *param); 421 std::tuple<binder::LocalVariable *, binder::LocalVariable *, bool> CheckFunctionRestParameter( 422 const ir::SpreadElement *param, SignatureInfo *signatureInfo); 423 std::tuple<binder::LocalVariable *, binder::LocalVariable *, bool> CheckFunctionArrayPatternParameter( 424 const ir::ArrayExpression *param); 425 std::tuple<binder::LocalVariable *, binder::LocalVariable *, bool> CheckFunctionObjectPatternParameter( 426 const ir::ObjectExpression *param); 427 void InferFunctionDeclarationType(const binder::FunctionDecl *decl, binder::Variable *funcVar); 428 void CollectTypesFromReturnStatements(const ir::AstNode *parent, ArenaVector<Type *> *returnTypes); 429 void CheckAllCodePathsInNonVoidFunctionReturnOrThrow(const ir::ScriptFunction *func, lexer::SourcePosition lineInfo, 430 const char *errMsg); 431 void CreatePatternParameterName(const ir::AstNode *node, std::stringstream &ss); 432 void ThrowReturnTypeCircularityError(const ir::ScriptFunction *func); 433 ArgRange GetArgRange(const ArenaVector<Signature *> &signatures, ArenaVector<Signature *> *potentialSignatures, 434 uint32_t callArgsSize, bool *haveSignatureWithRest); 435 bool CallMatchesSignature(const ArenaVector<ir::Expression *> &args, Signature *signature, bool throwError); 436 Type *resolveCallOrNewExpression(const ArenaVector<Signature *> &signatures, 437 ArenaVector<ir::Expression *> arguments, const lexer::SourcePosition &errPos); 438 Type *CreateParameterTypeForArrayAssignmentPattern(const ir::ArrayExpression *arrayPattern, Type *inferedType); 439 Type *CreateParameterTypeForObjectAssignmentPattern(const ir::ObjectExpression *objectPattern, Type *inferedType); 440 441 // Type relation 442 bool IsTypeIdenticalTo(Type *source, Type *target); 443 bool IsTypeIdenticalTo(Type *source, Type *target, const std::string &errMsg, const lexer::SourcePosition &errPos); 444 bool IsTypeIdenticalTo(Type *source, Type *target, std::initializer_list<TypeErrorMessageElement> list, 445 const lexer::SourcePosition &errPos); 446 bool IsTypeAssignableTo(Type *source, Type *target); 447 bool IsTypeAssignableTo(Type *source, Type *target, const std::string &errMsg, const lexer::SourcePosition &errPos); 448 bool IsTypeAssignableTo(Type *source, Type *target, std::initializer_list<TypeErrorMessageElement> list, 449 const lexer::SourcePosition &errPos); 450 bool IsTypeComparableTo(Type *source, Type *target); 451 bool IsTypeComparableTo(Type *source, Type *target, const std::string &errMsg, const lexer::SourcePosition &errPos); 452 bool IsTypeComparableTo(Type *source, Type *target, std::initializer_list<TypeErrorMessageElement> list, 453 const lexer::SourcePosition &errPos); 454 bool AreTypesComparable(Type *source, Type *target); 455 bool IsTypeEqualityComparableTo(Type *source, Type *target); 456 bool IsAllTypesAssignableTo(Type *source, Type *target); 457 458 // Binary like expression 459 Type *CheckBinaryOperator(Type *leftType, Type *rightType, const ir::Expression *leftExpr, 460 const ir::Expression *rightExpr, const ir::AstNode *expr, lexer::TokenType op); 461 Type *CheckPlusOperator(Type *leftType, Type *rightType, const ir::Expression *leftExpr, 462 const ir::Expression *rightExpr, const ir::AstNode *expr, lexer::TokenType op); 463 Type *CheckCompareOperator(Type *leftType, Type *rightType, const ir::Expression *leftExpr, 464 const ir::Expression *rightExpr, const ir::AstNode *expr, lexer::TokenType op); 465 Type *CheckAndOperator(Type *leftType, Type *rightType, const ir::Expression *leftExpr); 466 Type *CheckOrOperator(Type *leftType, Type *rightType, const ir::Expression *leftExpr); 467 Type *CheckInstanceofExpression(Type *leftType, Type *rightType, const ir::Expression *rightExpr, 468 const ir::AstNode *expr); 469 Type *CheckInExpression(Type *leftType, Type *rightType, const ir::Expression *leftExpr, 470 const ir::Expression *rightExpr, const ir::AstNode *expr); 471 void CheckAssignmentOperator(lexer::TokenType op, const ir::Expression *leftExpr, Type *leftType, Type *valueType); 472 473 friend class ScopeContext; 474 friend class SavedCheckerContext; 475 476 private: 477 ArenaAllocator *allocator_; 478 binder::Binder *binder_; 479 const ir::BlockStatement *rootNode_; 480 binder::Scope *scope_; 481 CheckerContext context_; 482 GlobalTypesHolder *globalTypes_; 483 484 NumberLiteralPool numberLiteralMap_; 485 StringLiteralPool stringLiteralMap_; 486 StringLiteralPool bigintLiteralMap_; 487 488 TypeRelation *relation_; 489 490 RelationHolder identicalResults_; 491 RelationHolder assignableResults_; 492 RelationHolder comparableResults_; 493 494 std::unordered_set<const void *> typeStack_; 495 std::unordered_map<const ir::AstNode *, Type *> nodeCache_; 496 std::vector<binder::Scope *> scopeStack_; 497 }; 498 499 class ScopeContext { 500 public: ScopeContext(Checker * checker,binder::Scope * newScope)501 explicit ScopeContext(Checker *checker, binder::Scope *newScope) : checker_(checker), prevScope_(checker_->scope_) 502 { 503 checker_->scope_ = newScope; 504 } 505 ~ScopeContext()506 ~ScopeContext() 507 { 508 checker_->scope_ = prevScope_; 509 } 510 511 NO_COPY_SEMANTIC(ScopeContext); 512 NO_MOVE_SEMANTIC(ScopeContext); 513 514 private: 515 Checker *checker_; 516 binder::Scope *prevScope_; 517 }; 518 519 class SavedCheckerContext { 520 public: SavedCheckerContext(Checker * checker,CheckerStatus newStatus)521 explicit SavedCheckerContext(Checker *checker, CheckerStatus newStatus) 522 : checker_(checker), prev_(checker->context_) 523 { 524 checker_->context_ = CheckerContext(newStatus); 525 } 526 527 NO_COPY_SEMANTIC(SavedCheckerContext); 528 DEFAULT_MOVE_SEMANTIC(SavedCheckerContext); 529 ~SavedCheckerContext()530 ~SavedCheckerContext() 531 { 532 checker_->context_ = prev_; 533 } 534 535 private: 536 Checker *checker_; 537 CheckerContext prev_; 538 }; 539 540 } // namespace panda::es2panda::checker 541 542 #endif /* CHECKER_H */ 543