• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *> &params, 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