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
24namespace ark::es2panda::ir {
25class Expression;
26class SpreadElement;
27}  // namespace ark::es2panda::ir
28
29namespace ark::es2panda::checker {
30class Type;
31
32class DestructuringContext {
33public:
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
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
53    void SetInferredType(Type *type)
54    {
55        inferredType_ = type;
56    }
57
58    void SetSignatureInfo(SignatureInfo *info)
59    {
60        signatureInfo_ = info;
61    }
62
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
88protected:
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
101class ArrayDestructuringContext : public DestructuringContext {
102public:
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
118private:
119    uint32_t index_ {0};
120};
121
122class ObjectDestructuringContext : public DestructuringContext {
123public:
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