/** * Copyright (c) 2021-2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "ir/expressions/assignmentExpression.h" #include "ir/expressions/binaryExpression.h" #include "ir/expressions/memberExpression.h" #include "ir/expressions/templateLiteral.h" #include "ir/ts/tsQualifiedName.h" #include "checker/TSchecker.h" namespace ark::es2panda::checker { ir::MemberExpression *TSChecker::ResolveLeftMostMemberExpression(ir::MemberExpression *expr) { ir::MemberExpression *iter = expr; while (iter->Object()->IsMemberExpression()) { iter = iter->Object()->AsMemberExpression(); } return iter; } bool TSChecker::InAssignment(ir::AstNode *node) { ir::AstNode *parent = node; while (parent->Parent() != nullptr) { if (parent->Parent()->IsAssignmentExpression()) { return parent->Parent()->AsAssignmentExpression()->Left() == parent; } if (parent->Parent()->IsBinaryExpression()) { ir::BinaryExpression *binaryExpr = parent->Parent()->AsBinaryExpression(); return IsAssignmentOperator(binaryExpr->OperatorType()) && binaryExpr->Left() == parent; } if (parent->Parent()->IsUpdateExpression()) { return true; } parent = parent->Parent(); } return false; } bool TSChecker::IsAssignmentOperator(lexer::TokenType op) { switch (op) { case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL: case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL: case lexer::TokenType::PUNCTUATOR_MULTIPLY_EQUAL: case lexer::TokenType::PUNCTUATOR_EXPONENTIATION_EQUAL: case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL: case lexer::TokenType::PUNCTUATOR_MOD_EQUAL: case lexer::TokenType::PUNCTUATOR_MINUS_EQUAL: case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL: case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL: case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL: case lexer::TokenType::PUNCTUATOR_BITWISE_AND_EQUAL: case lexer::TokenType::PUNCTUATOR_BITWISE_OR_EQUAL: case lexer::TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL: case lexer::TokenType::PUNCTUATOR_PLUS_EQUAL: case lexer::TokenType::PUNCTUATOR_SUBSTITUTION: return true; default: return false; } } bool TSChecker::IsLiteralType(const Type *type) { if (type->IsBooleanType()) { return true; } if (type->IsUnionType()) { auto &constituentTypes = type->AsUnionType()->ConstituentTypes(); bool result = true; for (auto *it : constituentTypes) { result &= it->HasTypeFlag(TypeFlag::UNIT); } return result; } return type->HasTypeFlag(TypeFlag::UNIT); } ir::AstNode *TSChecker::FindAncestorUntilGivenType(ir::AstNode *node, ir::AstNodeType stop) { while (node->Parent()->Type() != stop) { if (node->Parent() != nullptr) { node = node->Parent(); continue; } return nullptr; } return node; } bool TSChecker::MaybeTypeOfKind(const Type *type, TypeFlag flags) { if (type->HasTypeFlag(flags)) { return true; } if (type->HasTypeFlag(TypeFlag::UNION_OR_INTERSECTION) && type->IsUnionType()) { const auto &constituentTypes = type->AsUnionType()->ConstituentTypes(); for (auto *it : constituentTypes) { if (MaybeTypeOfKind(it, flags)) { return true; } } } return false; } bool TSChecker::MaybeTypeOfKind(const Type *type, ObjectType::ObjectTypeKind kind) { if (type->IsObjectType() && type->AsObjectType()->Kind() == kind) { return true; } if (type->HasTypeFlag(TypeFlag::UNION_OR_INTERSECTION) && type->IsUnionType()) { const auto &constituentTypes = type->AsUnionType()->ConstituentTypes(); for (auto *it : constituentTypes) { if (MaybeTypeOfKind(it, kind)) { return true; } } } return false; } bool TSChecker::IsConstantMemberAccess(ir::Expression *expr) { switch (expr->Type()) { case ir::AstNodeType::IDENTIFIER: { return true; } case ir::AstNodeType::MEMBER_EXPRESSION: { bool res = IsConstantMemberAccess(expr->AsMemberExpression()->Object()); return !expr->AsMemberExpression()->IsComputed() ? res : (res && IsStringLike(expr->AsMemberExpression()->Property())); } default: return false; } } bool TSChecker::IsStringLike(ir::Expression *expr) { if (expr->IsStringLiteral()) { return true; } if (expr->IsTemplateLiteral() && expr->AsTemplateLiteral()->Quasis().empty()) { return true; } return false; } } // namespace ark::es2panda::checker