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 24namespace ark::es2panda::checker { 25ir::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 36bool 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 59bool 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 83bool 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 101ir::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 115bool 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 133bool 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 151bool 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 168bool 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