1 /** 2 * Copyright (c) 2021-2024 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_CHECKER_TS_DESTRUCTURING_CONTEXT_H 17 #define ES2PANDA_CHECKER_TS_DESTRUCTURING_CONTEXT_H 18 19 #include "checker/TSchecker.h" 20 #include "ir/expression.h" 21 22 #include <macros.h> 23 24 namespace ark::es2panda::ir { 25 class Expression; 26 class SpreadElement; 27 } // namespace ark::es2panda::ir 28 29 namespace ark::es2panda::checker { 30 class Type; 31 32 class DestructuringContext { 33 public: 34 // Struct to reduce number of constructor arguments to pass code checker 35 struct DestructuringContextArguments { 36 TSChecker *checker; 37 ir::Expression *id; 38 bool inAssignment; 39 bool convertTupleToArray; 40 ir::TypeNode *typeAnnotation; 41 ir::Expression *initializer; 42 }; 43 DestructuringContext(const DestructuringContextArguments &data)44 explicit DestructuringContext(const DestructuringContextArguments &data) 45 : checker_(data.checker), 46 id_(data.id), 47 inAssignment_(data.inAssignment), 48 convertTupleToArray_(data.convertTupleToArray) 49 { 50 Prepare(data.typeAnnotation, data.initializer, data.id->Start()); 51 } 52 SetInferredType(Type *type)53 void SetInferredType(Type *type) 54 { 55 inferredType_ = type; 56 } 57 SetSignatureInfo(SignatureInfo *info)58 void SetSignatureInfo(SignatureInfo *info) 59 { 60 signatureInfo_ = info; 61 } 62 InferredType()63 Type *InferredType() 64 { 65 return inferredType_; 66 } 67 68 void ValidateObjectLiteralType(ObjectType *objType, ir::ObjectExpression *objPattern); 69 void HandleDestructuringAssignment(ir::Identifier *ident, Type *inferredType, Type *defaultType); 70 void HandleAssignmentPattern(ir::AssignmentExpression *assignmentPattern, Type *inferredType, bool validateDefault); 71 void HandleAssignmentPatternArrayPattern(ir::AssignmentExpression *assignmentPattern, Type *inferredType); 72 void HandleAssignmentPatternIdentifier(ir::AssignmentExpression *assignmentPattern, Type *defaultType, 73 Type *inferredType); 74 void SetInferredTypeForVariable(varbinder::Variable *var, Type *inferredType, const lexer::SourcePosition &loc); 75 void Prepare(ir::TypeNode *typeAnnotation, ir::Expression *initializer, const lexer::SourcePosition &loc); 76 77 DEFAULT_COPY_SEMANTIC(DestructuringContext); 78 DEFAULT_MOVE_SEMANTIC(DestructuringContext); 79 virtual ~DestructuringContext() = default; 80 81 virtual void Start() = 0; 82 virtual void ValidateInferredType() = 0; 83 virtual Type *NextInferredType([[maybe_unused]] const util::StringView &searchName, bool throwError) = 0; 84 virtual void HandleRest(ir::SpreadElement *rest) = 0; 85 virtual Type *GetRestType([[maybe_unused]] const lexer::SourcePosition &loc) = 0; 86 virtual Type *ConvertTupleTypeToArrayTypeIfNecessary(ir::AstNode *node, Type *type) = 0; 87 88 protected: 89 // NOLINTBEGIN(misc-non-private-member-variables-in-classes) 90 TSChecker *checker_; 91 ir::Expression *id_; 92 bool inAssignment_; 93 bool convertTupleToArray_; 94 Type *inferredType_ {}; 95 SignatureInfo *signatureInfo_ {}; 96 bool validateObjectPatternInitializer_ {true}; 97 bool validateTypeAnnotation_ {}; 98 // NOLINTEND(misc-non-private-member-variables-in-classes) 99 }; 100 101 class ArrayDestructuringContext : public DestructuringContext { 102 public: ArrayDestructuringContext(const DestructuringContextArguments &data)103 explicit ArrayDestructuringContext(const DestructuringContextArguments &data) : DestructuringContext(data) {} 104 105 Type *GetTypeFromTupleByIndex(TupleType *tuple); 106 Type *CreateArrayTypeForRest(UnionType *inferredType); 107 Type *CreateTupleTypeForRest(TupleType *tuple); 108 void SetRemainingParameterTypes(); 109 110 void Start() override; 111 void HandleElement(ir::Expression *element, Type *nextInferredType); 112 void ValidateInferredType() override; 113 Type *NextInferredType([[maybe_unused]] const util::StringView &searchName, bool throwError) override; 114 void HandleRest(ir::SpreadElement *rest) override; 115 Type *GetRestType([[maybe_unused]] const lexer::SourcePosition &loc) override; 116 Type *ConvertTupleTypeToArrayTypeIfNecessary(ir::AstNode *node, Type *type) override; 117 118 private: 119 uint32_t index_ {0}; 120 }; 121 122 class ObjectDestructuringContext : public DestructuringContext { 123 public: ObjectDestructuringContext(const DestructuringContextArguments &data)124 explicit ObjectDestructuringContext(const DestructuringContextArguments &data) : DestructuringContext(data) {} 125 126 Type *CreateObjectTypeForRest(ObjectType *objType); 127 128 void Start() override; 129 void ValidateInferredType() override; 130 Type *NextInferredType([[maybe_unused]] const util::StringView &searchName, bool throwError) override; 131 void HandleRest(ir::SpreadElement *rest) override; 132 Type *GetRestType([[maybe_unused]] const lexer::SourcePosition &loc) override; 133 Type *ConvertTupleTypeToArrayTypeIfNecessary(ir::AstNode *node, Type *type) override; 134 }; 135 } // namespace ark::es2panda::checker 136 137 #endif 138