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 #include "ir/expressions/assignmentExpression.h"
17 #include "ir/expressions/binaryExpression.h"
18 #include "ir/expressions/memberExpression.h"
19 #include "ir/expressions/templateLiteral.h"
20 #include "ir/ts/tsQualifiedName.h"
21 
22 #include "checker/TSchecker.h"
23 
24 namespace ark::es2panda::checker {
ResolveLeftMostMemberExpression(ir::MemberExpression *expr)25 ir::MemberExpression *TSChecker::ResolveLeftMostMemberExpression(ir::MemberExpression *expr)
26 {
27     ir::MemberExpression *iter = expr;
28 
29     while (iter->Object()->IsMemberExpression()) {
30         iter = iter->Object()->AsMemberExpression();
31     }
32 
33     return iter;
34 }
35 
InAssignment(ir::AstNode *node)36 bool TSChecker::InAssignment(ir::AstNode *node)
37 {
38     ir::AstNode *parent = node;
39 
40     while (parent->Parent() != nullptr) {
41         if (parent->Parent()->IsAssignmentExpression()) {
42             return parent->Parent()->AsAssignmentExpression()->Left() == parent;
43         }
44 
45         if (parent->Parent()->IsBinaryExpression()) {
46             ir::BinaryExpression *binaryExpr = parent->Parent()->AsBinaryExpression();
47             return IsAssignmentOperator(binaryExpr->OperatorType()) && binaryExpr->Left() == parent;
48         }
49 
50         if (parent->Parent()->IsUpdateExpression()) {
51             return true;
52         }
53 
54         parent = parent->Parent();
55     }
56     return false;
57 }
58 
IsAssignmentOperator(lexer::TokenType op)59 bool TSChecker::IsAssignmentOperator(lexer::TokenType op)
60 {
61     switch (op) {
62         case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL:
63         case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL:
64         case lexer::TokenType::PUNCTUATOR_MULTIPLY_EQUAL:
65         case lexer::TokenType::PUNCTUATOR_EXPONENTIATION_EQUAL:
66         case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL:
67         case lexer::TokenType::PUNCTUATOR_MOD_EQUAL:
68         case lexer::TokenType::PUNCTUATOR_MINUS_EQUAL:
69         case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL:
70         case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL:
71         case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL:
72         case lexer::TokenType::PUNCTUATOR_BITWISE_AND_EQUAL:
73         case lexer::TokenType::PUNCTUATOR_BITWISE_OR_EQUAL:
74         case lexer::TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL:
75         case lexer::TokenType::PUNCTUATOR_PLUS_EQUAL:
76         case lexer::TokenType::PUNCTUATOR_SUBSTITUTION:
77             return true;
78         default:
79             return false;
80     }
81 }
82 
IsLiteralType(const Type *type)83 bool TSChecker::IsLiteralType(const Type *type)
84 {
85     if (type->IsBooleanType()) {
86         return true;
87     }
88 
89     if (type->IsUnionType()) {
90         auto &constituentTypes = type->AsUnionType()->ConstituentTypes();
91         bool result = true;
92         for (auto *it : constituentTypes) {
93             result &= it->HasTypeFlag(TypeFlag::UNIT);
94         }
95         return result;
96     }
97 
98     return type->HasTypeFlag(TypeFlag::UNIT);
99 }
100 
FindAncestorUntilGivenType(ir::AstNode *node, ir::AstNodeType stop)101 ir::AstNode *TSChecker::FindAncestorUntilGivenType(ir::AstNode *node, ir::AstNodeType stop)
102 {
103     while (node->Parent()->Type() != stop) {
104         if (node->Parent() != nullptr) {
105             node = node->Parent();
106             continue;
107         }
108 
109         return nullptr;
110     }
111 
112     return node;
113 }
114 
MaybeTypeOfKind(const Type *type, TypeFlag flags)115 bool TSChecker::MaybeTypeOfKind(const Type *type, TypeFlag flags)
116 {
117     if (type->HasTypeFlag(flags)) {
118         return true;
119     }
120 
121     if (type->HasTypeFlag(TypeFlag::UNION_OR_INTERSECTION) && type->IsUnionType()) {
122         const auto &constituentTypes = type->AsUnionType()->ConstituentTypes();
123         for (auto *it : constituentTypes) {
124             if (MaybeTypeOfKind(it, flags)) {
125                 return true;
126             }
127         }
128     }
129 
130     return false;
131 }
132 
MaybeTypeOfKind(const Type *type, ObjectType::ObjectTypeKind kind)133 bool TSChecker::MaybeTypeOfKind(const Type *type, ObjectType::ObjectTypeKind kind)
134 {
135     if (type->IsObjectType() && type->AsObjectType()->Kind() == kind) {
136         return true;
137     }
138 
139     if (type->HasTypeFlag(TypeFlag::UNION_OR_INTERSECTION) && type->IsUnionType()) {
140         const auto &constituentTypes = type->AsUnionType()->ConstituentTypes();
141         for (auto *it : constituentTypes) {
142             if (MaybeTypeOfKind(it, kind)) {
143                 return true;
144             }
145         }
146     }
147 
148     return false;
149 }
150 
IsConstantMemberAccess(ir::Expression *expr)151 bool TSChecker::IsConstantMemberAccess(ir::Expression *expr)
152 {
153     switch (expr->Type()) {
154         case ir::AstNodeType::IDENTIFIER: {
155             return true;
156         }
157         case ir::AstNodeType::MEMBER_EXPRESSION: {
158             bool res = IsConstantMemberAccess(expr->AsMemberExpression()->Object());
159             return !expr->AsMemberExpression()->IsComputed()
160                        ? res
161                        : (res && IsStringLike(expr->AsMemberExpression()->Property()));
162         }
163         default:
164             return false;
165     }
166 }
167 
IsStringLike(ir::Expression *expr)168 bool TSChecker::IsStringLike(ir::Expression *expr)
169 {
170     if (expr->IsStringLiteral()) {
171         return true;
172     }
173 
174     if (expr->IsTemplateLiteral() && expr->AsTemplateLiteral()->Quasis().empty()) {
175         return true;
176     }
177 
178     return false;
179 }
180 }  // namespace ark::es2panda::checker
181