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