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