13af6ab5fSopenharmony_ci 23af6ab5fSopenharmony_ci/** 33af6ab5fSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 43af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 53af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License. 63af6ab5fSopenharmony_ci * You may obtain a copy of the License at 73af6ab5fSopenharmony_ci * 83af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 93af6ab5fSopenharmony_ci * 103af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 113af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 123af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and 143af6ab5fSopenharmony_ci * limitations under the License. 153af6ab5fSopenharmony_ci */ 163af6ab5fSopenharmony_ci 173af6ab5fSopenharmony_ci#include "etsWarningAnalyzer.h" 183af6ab5fSopenharmony_ci 193af6ab5fSopenharmony_ci#include "parser/program/program.h" 203af6ab5fSopenharmony_ci#include "util/options.h" 213af6ab5fSopenharmony_ci#include "ir/expressions/binaryExpression.h" 223af6ab5fSopenharmony_ci#include "ir/base/methodDefinition.h" 233af6ab5fSopenharmony_ci#include "ir/base/scriptFunction.h" 243af6ab5fSopenharmony_ci#include "ir/statements/classDeclaration.h" 253af6ab5fSopenharmony_ci#include "ir/statements/expressionStatement.h" 263af6ab5fSopenharmony_ci#include "ir/statements/blockStatement.h" 273af6ab5fSopenharmony_ci#include "ir/expressions/assignmentExpression.h" 283af6ab5fSopenharmony_ci#include "ir/expressions/callExpression.h" 293af6ab5fSopenharmony_ci#include "ir/expressions/identifier.h" 303af6ab5fSopenharmony_ci#include "ir/expressions/memberExpression.h" 313af6ab5fSopenharmony_ci#include "ir/ets/etsTypeReferencePart.h" 323af6ab5fSopenharmony_ci#include "ir/ets/etsTypeReference.h" 333af6ab5fSopenharmony_ci#include "ir/base/classDefinition.h" 343af6ab5fSopenharmony_ci#include "ir/statements/forOfStatement.h" 353af6ab5fSopenharmony_ci#include "ir/statements/variableDeclarator.h" 363af6ab5fSopenharmony_ci#include "ir/statements/variableDeclaration.h" 373af6ab5fSopenharmony_ci#include "ir/expressions/updateExpression.h" 383af6ab5fSopenharmony_ci 393af6ab5fSopenharmony_cinamespace ark::es2panda::checker { 403af6ab5fSopenharmony_ci 413af6ab5fSopenharmony_civoid ETSWarningAnalyzer::AnalyzeClassDefForFinalModifier(const ir::ClassDefinition *classDef) 423af6ab5fSopenharmony_ci{ 433af6ab5fSopenharmony_ci ASSERT(classDef != nullptr); 443af6ab5fSopenharmony_ci 453af6ab5fSopenharmony_ci if (program_ == nullptr || classDef->IsFinal() || classDef->IsAbstract() || classDef->IsStatic() || 463af6ab5fSopenharmony_ci classDef->IsGlobal() || classDef->IsExported()) { 473af6ab5fSopenharmony_ci return; 483af6ab5fSopenharmony_ci } 493af6ab5fSopenharmony_ci 503af6ab5fSopenharmony_ci const auto statements = program_->Ast()->Statements(); 513af6ab5fSopenharmony_ci for (const auto *it : statements) { 523af6ab5fSopenharmony_ci if (!it->IsClassDeclaration() || 533af6ab5fSopenharmony_ci classDef->Ident()->Name() == it->AsClassDeclaration()->Definition()->Ident()->Name()) { 543af6ab5fSopenharmony_ci continue; 553af6ab5fSopenharmony_ci } 563af6ab5fSopenharmony_ci 573af6ab5fSopenharmony_ci const auto *itAsClassDef = it->AsClassDeclaration()->Definition(); 583af6ab5fSopenharmony_ci 593af6ab5fSopenharmony_ci if (!itAsClassDef->IsGlobal()) { 603af6ab5fSopenharmony_ci const auto *superClass = itAsClassDef->Super(); 613af6ab5fSopenharmony_ci 623af6ab5fSopenharmony_ci if (superClass == nullptr) { 633af6ab5fSopenharmony_ci continue; 643af6ab5fSopenharmony_ci } 653af6ab5fSopenharmony_ci 663af6ab5fSopenharmony_ci if (superClass->IsETSTypeReference() && superClass->AsETSTypeReference()->Part()->Name()->IsIdentifier() && 673af6ab5fSopenharmony_ci superClass->AsETSTypeReference()->Part()->Name()->AsIdentifier()->Name() == classDef->Ident()->Name()) { 683af6ab5fSopenharmony_ci return; 693af6ab5fSopenharmony_ci } 703af6ab5fSopenharmony_ci } 713af6ab5fSopenharmony_ci } 723af6ab5fSopenharmony_ci 733af6ab5fSopenharmony_ci ETSThrowWarning("Suggest 'final' modifier for class", classDef->Ident()->Start()); 743af6ab5fSopenharmony_ci} 753af6ab5fSopenharmony_ci 763af6ab5fSopenharmony_civoid ETSWarningAnalyzer::AnalyzeClassMethodForFinalModifier(const ir::MethodDefinition *methodDef, 773af6ab5fSopenharmony_ci const ir::ClassDefinition *classDef) 783af6ab5fSopenharmony_ci{ 793af6ab5fSopenharmony_ci ASSERT(methodDef != nullptr && classDef != nullptr); 803af6ab5fSopenharmony_ci 813af6ab5fSopenharmony_ci if (methodDef->IsAbstract() || methodDef->IsStatic() || classDef->IsFinal() || program_ == nullptr || 823af6ab5fSopenharmony_ci methodDef->IsFinal() || methodDef->IsConstructor() || classDef->IsGlobal()) { 833af6ab5fSopenharmony_ci return; 843af6ab5fSopenharmony_ci } 853af6ab5fSopenharmony_ci 863af6ab5fSopenharmony_ci bool suggestFinal = true; 873af6ab5fSopenharmony_ci 883af6ab5fSopenharmony_ci const auto statements = program_->Ast()->Statements(); 893af6ab5fSopenharmony_ci for (const auto *it : statements) { 903af6ab5fSopenharmony_ci if (!it->IsClassDeclaration() || it->AsClassDeclaration()->Definition()->IsGlobal() || 913af6ab5fSopenharmony_ci classDef->Ident()->Name() == it->AsClassDeclaration()->Definition()->Ident()->Name()) { 923af6ab5fSopenharmony_ci continue; 933af6ab5fSopenharmony_ci } 943af6ab5fSopenharmony_ci 953af6ab5fSopenharmony_ci const auto *statementDef = it->AsClassDeclaration()->Definition(); 963af6ab5fSopenharmony_ci for (const auto *bodyPart : statementDef->Body()) { 973af6ab5fSopenharmony_ci if (!bodyPart->IsMethodDefinition()) { 983af6ab5fSopenharmony_ci continue; 993af6ab5fSopenharmony_ci } 1003af6ab5fSopenharmony_ci static auto classAsETSObject = classDef->TsType()->AsETSObjectType(); 1013af6ab5fSopenharmony_ci static auto potentialDescendant = statementDef->TsType()->AsETSObjectType(); 1023af6ab5fSopenharmony_ci if (!potentialDescendant->IsDescendantOf(classAsETSObject)) { 1033af6ab5fSopenharmony_ci continue; 1043af6ab5fSopenharmony_ci } 1053af6ab5fSopenharmony_ci const util::StringView bodyMethodName = 1063af6ab5fSopenharmony_ci ETSChecker::GetSignatureFromMethodDefinition(bodyPart->AsMethodDefinition())->Function()->Id()->Name(); 1073af6ab5fSopenharmony_ci if (bodyPart->IsOverride() && bodyMethodName != compiler::Signatures::CTOR && 1083af6ab5fSopenharmony_ci bodyMethodName == methodDef->Function()->Id()->Name()) { 1093af6ab5fSopenharmony_ci suggestFinal = false; 1103af6ab5fSopenharmony_ci break; 1113af6ab5fSopenharmony_ci } 1123af6ab5fSopenharmony_ci } 1133af6ab5fSopenharmony_ci } 1143af6ab5fSopenharmony_ci 1153af6ab5fSopenharmony_ci if (suggestFinal) { 1163af6ab5fSopenharmony_ci ETSThrowWarning("Suggest 'final' modifier for method", methodDef->Function()->Start()); 1173af6ab5fSopenharmony_ci } 1183af6ab5fSopenharmony_ci} 1193af6ab5fSopenharmony_ci 1203af6ab5fSopenharmony_civoid ETSWarningAnalyzer::ETSWarningSuggestFinal(const ir::AstNode *node) 1213af6ab5fSopenharmony_ci{ 1223af6ab5fSopenharmony_ci if (node->IsClassDeclaration() && !program_->NodeContainsETSNolint(node, ETSWarnings::SUGGEST_FINAL)) { 1233af6ab5fSopenharmony_ci if (node->AsClassDeclaration()->Definition()->IsClassDefinition()) { 1243af6ab5fSopenharmony_ci AnalyzeClassDefForFinalModifier(node->AsClassDeclaration()->Definition()); 1253af6ab5fSopenharmony_ci } 1263af6ab5fSopenharmony_ci 1273af6ab5fSopenharmony_ci const auto classBody = node->AsClassDeclaration()->Definition()->Body(); 1283af6ab5fSopenharmony_ci for (const auto *it : classBody) { 1293af6ab5fSopenharmony_ci if (it->IsMethodDefinition()) { 1303af6ab5fSopenharmony_ci AnalyzeClassMethodForFinalModifier(it->AsMethodDefinition(), node->AsClassDeclaration()->Definition()); 1313af6ab5fSopenharmony_ci } 1323af6ab5fSopenharmony_ci } 1333af6ab5fSopenharmony_ci } 1343af6ab5fSopenharmony_ci node->Iterate([&](auto *childNode) { ETSWarningSuggestFinal(childNode); }); 1353af6ab5fSopenharmony_ci} 1363af6ab5fSopenharmony_ci 1373af6ab5fSopenharmony_civoid ETSWarningAnalyzer::CheckTopLevelExpressions(const ir::Expression *expression) 1383af6ab5fSopenharmony_ci{ 1393af6ab5fSopenharmony_ci if (expression->IsCallExpression()) { 1403af6ab5fSopenharmony_ci const auto exprCallee = expression->AsCallExpression()->Callee(); 1413af6ab5fSopenharmony_ci lexer::SourcePosition pos = exprCallee->Start(); 1423af6ab5fSopenharmony_ci if (exprCallee->IsMemberExpression()) { 1433af6ab5fSopenharmony_ci pos = exprCallee->AsMemberExpression()->Object()->Start(); 1443af6ab5fSopenharmony_ci ETSThrowWarning("Prohibit top-level statements", pos); 1453af6ab5fSopenharmony_ci } 1463af6ab5fSopenharmony_ci } else if (expression->IsAssignmentExpression()) { 1473af6ab5fSopenharmony_ci const auto assignmentExpr = expression->AsAssignmentExpression(); 1483af6ab5fSopenharmony_ci ETSThrowWarning("Prohibit top-level statements", assignmentExpr->Left()->Start()); 1493af6ab5fSopenharmony_ci } 1503af6ab5fSopenharmony_ci} 1513af6ab5fSopenharmony_ci 1523af6ab5fSopenharmony_civoid ETSWarningAnalyzer::CheckProhibitedTopLevelStatements(const ir::Statement *statement) 1533af6ab5fSopenharmony_ci{ 1543af6ab5fSopenharmony_ci switch (statement->Type()) { 1553af6ab5fSopenharmony_ci case ir::AstNodeType::ARROW_FUNCTION_EXPRESSION: 1563af6ab5fSopenharmony_ci case ir::AstNodeType::FUNCTION_DECLARATION: 1573af6ab5fSopenharmony_ci case ir::AstNodeType::SCRIPT_FUNCTION: 1583af6ab5fSopenharmony_ci case ir::AstNodeType::ETS_FUNCTION_TYPE: 1593af6ab5fSopenharmony_ci case ir::AstNodeType::IMPORT_NAMESPACE_SPECIFIER: 1603af6ab5fSopenharmony_ci case ir::AstNodeType::CLASS_DECLARATION: 1613af6ab5fSopenharmony_ci case ir::AstNodeType::CLASS_EXPRESSION: 1623af6ab5fSopenharmony_ci case ir::AstNodeType::VARIABLE_DECLARATION: 1633af6ab5fSopenharmony_ci case ir::AstNodeType::CLASS_DEFINITION: 1643af6ab5fSopenharmony_ci case ir::AstNodeType::CLASS_PROPERTY: 1653af6ab5fSopenharmony_ci break; 1663af6ab5fSopenharmony_ci default: 1673af6ab5fSopenharmony_ci ETSThrowWarning("Prohibit top-level statements", statement->Start()); 1683af6ab5fSopenharmony_ci break; 1693af6ab5fSopenharmony_ci } 1703af6ab5fSopenharmony_ci} 1713af6ab5fSopenharmony_ci 1723af6ab5fSopenharmony_civoid ETSWarningAnalyzer::ETSWarningsProhibitTopLevelStatements(const ir::AstNode *node) 1733af6ab5fSopenharmony_ci{ 1743af6ab5fSopenharmony_ci if (!node->IsClassDeclaration() || 1753af6ab5fSopenharmony_ci program_->NodeContainsETSNolint(node, ETSWarnings::PROHIBIT_TOP_LEVEL_STATEMENTS)) { 1763af6ab5fSopenharmony_ci node->Iterate([&](auto *childNode) { ETSWarningsProhibitTopLevelStatements(childNode); }); 1773af6ab5fSopenharmony_ci return; 1783af6ab5fSopenharmony_ci } 1793af6ab5fSopenharmony_ci 1803af6ab5fSopenharmony_ci const auto *classDef = node->AsClassDeclaration()->Definition(); 1813af6ab5fSopenharmony_ci if (!classDef->IsGlobal()) { 1823af6ab5fSopenharmony_ci node->Iterate([&](auto *childNode) { ETSWarningsProhibitTopLevelStatements(childNode); }); 1833af6ab5fSopenharmony_ci return; 1843af6ab5fSopenharmony_ci } 1853af6ab5fSopenharmony_ci 1863af6ab5fSopenharmony_ci for (const auto *itBody : classDef->Body()) { 1873af6ab5fSopenharmony_ci if (!itBody->IsMethodDefinition() || 1883af6ab5fSopenharmony_ci itBody->AsMethodDefinition()->Id()->Name() != compiler::Signatures::INIT_METHOD) { 1893af6ab5fSopenharmony_ci continue; 1903af6ab5fSopenharmony_ci } 1913af6ab5fSopenharmony_ci 1923af6ab5fSopenharmony_ci for (const auto *statement : 1933af6ab5fSopenharmony_ci itBody->AsMethodDefinition()->Function()->Body()->AsBlockStatement()->Statements()) { 1943af6ab5fSopenharmony_ci if (program_->NodeContainsETSNolint(statement, ETSWarnings::PROHIBIT_TOP_LEVEL_STATEMENTS)) { 1953af6ab5fSopenharmony_ci continue; 1963af6ab5fSopenharmony_ci } 1973af6ab5fSopenharmony_ci 1983af6ab5fSopenharmony_ci if (!statement->IsExpressionStatement()) { 1993af6ab5fSopenharmony_ci CheckProhibitedTopLevelStatements(statement); 2003af6ab5fSopenharmony_ci continue; 2013af6ab5fSopenharmony_ci } 2023af6ab5fSopenharmony_ci 2033af6ab5fSopenharmony_ci // Rewrite this part after fixing AST issue about tiop-level 2043af6ab5fSopenharmony_ci CheckTopLevelExpressions(statement->AsExpressionStatement()->GetExpression()); 2053af6ab5fSopenharmony_ci } 2063af6ab5fSopenharmony_ci } 2073af6ab5fSopenharmony_ci} 2083af6ab5fSopenharmony_ci 2093af6ab5fSopenharmony_civoid ETSWarningAnalyzer::ETSWarningBoostEqualityStatement(const ir::AstNode *node) 2103af6ab5fSopenharmony_ci{ 2113af6ab5fSopenharmony_ci ASSERT(node != nullptr); 2123af6ab5fSopenharmony_ci 2133af6ab5fSopenharmony_ci if (node->IsBinaryExpression() && !program_->NodeContainsETSNolint(node, ETSWarnings::BOOST_EQUALITY_STATEMENT)) { 2143af6ab5fSopenharmony_ci const auto binExpr = node->AsBinaryExpression(); 2153af6ab5fSopenharmony_ci if (binExpr->OperatorType() == lexer::TokenType::PUNCTUATOR_EQUAL || 2163af6ab5fSopenharmony_ci binExpr->OperatorType() == lexer::TokenType::PUNCTUATOR_NOT_EQUAL) { 2173af6ab5fSopenharmony_ci if (binExpr->Right()->IsNullLiteral() && !binExpr->Left()->IsNullLiteral()) { 2183af6ab5fSopenharmony_ci ETSThrowWarning("Boost Equality Statement. Change sides of binary expression", node->Start()); 2193af6ab5fSopenharmony_ci } 2203af6ab5fSopenharmony_ci } 2213af6ab5fSopenharmony_ci } 2223af6ab5fSopenharmony_ci node->Iterate([&](auto *childNode) { ETSWarningBoostEqualityStatement(childNode); }); 2233af6ab5fSopenharmony_ci} 2243af6ab5fSopenharmony_ci 2253af6ab5fSopenharmony_civoid ETSWarningAnalyzer::ETSWarningRemoveAsync(const ir::AstNode *node) 2263af6ab5fSopenharmony_ci{ 2273af6ab5fSopenharmony_ci if (node->IsMethodDefinition() && !program_->NodeContainsETSNolint(node, ETSWarnings::REMOVE_ASYNC_FUNCTIONS)) { 2283af6ab5fSopenharmony_ci const auto methodDefinition = node->AsMethodDefinition(); 2293af6ab5fSopenharmony_ci if (methodDefinition->IsAsync()) { 2303af6ab5fSopenharmony_ci ETSThrowWarning("Replace asynchronous function with coroutine", methodDefinition->Start()); 2313af6ab5fSopenharmony_ci } 2323af6ab5fSopenharmony_ci } 2333af6ab5fSopenharmony_ci node->Iterate([&](auto *childNode) { ETSWarningRemoveAsync(childNode); }); 2343af6ab5fSopenharmony_ci} 2353af6ab5fSopenharmony_ci 2363af6ab5fSopenharmony_civoid ETSWarningAnalyzer::ETSWarningRemoveLambda(const ir::AstNode *node) 2373af6ab5fSopenharmony_ci{ 2383af6ab5fSopenharmony_ci ASSERT(node != nullptr); 2393af6ab5fSopenharmony_ci 2403af6ab5fSopenharmony_ci if (node->IsArrowFunctionExpression() && !program_->NodeContainsETSNolint(node, ETSWarnings::REMOVE_LAMBDA)) { 2413af6ab5fSopenharmony_ci ETSThrowWarning("Replace the lambda function with a regular function", node->Start()); 2423af6ab5fSopenharmony_ci } 2433af6ab5fSopenharmony_ci node->Iterate([&](auto *childNode) { ETSWarningRemoveLambda(childNode); }); 2443af6ab5fSopenharmony_ci} 2453af6ab5fSopenharmony_ci 2463af6ab5fSopenharmony_civoid ETSWarningAnalyzer::CheckTypeOfBoxing(const ir::AstNode *node) 2473af6ab5fSopenharmony_ci{ 2483af6ab5fSopenharmony_ci ASSERT(node != nullptr); 2493af6ab5fSopenharmony_ci const auto flags = node->GetBoxingUnboxingFlags(); 2503af6ab5fSopenharmony_ci if ((flags & ir::BoxingUnboxingFlags::BOXING_FLAG) != 0) { 2513af6ab5fSopenharmony_ci switch (static_cast<ir::BoxingUnboxingFlags>(flags & ir::BoxingUnboxingFlags::BOXING_FLAG)) { 2523af6ab5fSopenharmony_ci case ir::BoxingUnboxingFlags::BOX_TO_INT: 2533af6ab5fSopenharmony_ci ETSThrowWarning("Implicit Boxing to Int" + GetBoxingUnboxingType(node), node->Start()); 2543af6ab5fSopenharmony_ci break; 2553af6ab5fSopenharmony_ci case ir::BoxingUnboxingFlags::BOX_TO_BOOLEAN: 2563af6ab5fSopenharmony_ci ETSThrowWarning("Implicit Boxing to Boolean" + GetBoxingUnboxingType(node), node->Start()); 2573af6ab5fSopenharmony_ci break; 2583af6ab5fSopenharmony_ci case ir::BoxingUnboxingFlags::BOX_TO_BYTE: 2593af6ab5fSopenharmony_ci ETSThrowWarning("Implicit Boxing to Byte" + GetBoxingUnboxingType(node), node->Start()); 2603af6ab5fSopenharmony_ci break; 2613af6ab5fSopenharmony_ci case ir::BoxingUnboxingFlags::BOX_TO_CHAR: 2623af6ab5fSopenharmony_ci ETSThrowWarning("Implicit Boxing to Char" + GetBoxingUnboxingType(node), node->Start()); 2633af6ab5fSopenharmony_ci break; 2643af6ab5fSopenharmony_ci case ir::BoxingUnboxingFlags::BOX_TO_DOUBLE: 2653af6ab5fSopenharmony_ci ETSThrowWarning("Implicit Boxing to Double" + GetBoxingUnboxingType(node), node->Start()); 2663af6ab5fSopenharmony_ci break; 2673af6ab5fSopenharmony_ci case ir::BoxingUnboxingFlags::BOX_TO_FLOAT: 2683af6ab5fSopenharmony_ci ETSThrowWarning("Implicit Boxing to Float" + GetBoxingUnboxingType(node), node->Start()); 2693af6ab5fSopenharmony_ci break; 2703af6ab5fSopenharmony_ci case ir::BoxingUnboxingFlags::BOX_TO_LONG: 2713af6ab5fSopenharmony_ci ETSThrowWarning("Implicit Boxing to Long" + GetBoxingUnboxingType(node), node->Start()); 2723af6ab5fSopenharmony_ci break; 2733af6ab5fSopenharmony_ci case ir::BoxingUnboxingFlags::BOX_TO_SHORT: 2743af6ab5fSopenharmony_ci ETSThrowWarning("Implicit Boxing to Short" + GetBoxingUnboxingType(node), node->Start()); 2753af6ab5fSopenharmony_ci break; 2763af6ab5fSopenharmony_ci default: 2773af6ab5fSopenharmony_ci break; 2783af6ab5fSopenharmony_ci } 2793af6ab5fSopenharmony_ci } 2803af6ab5fSopenharmony_ci} 2813af6ab5fSopenharmony_ci 2823af6ab5fSopenharmony_civoid ETSWarningAnalyzer::CheckTypeOfUnboxing(const ir::AstNode *node) 2833af6ab5fSopenharmony_ci{ 2843af6ab5fSopenharmony_ci ASSERT(node != nullptr); 2853af6ab5fSopenharmony_ci const auto flags = node->GetBoxingUnboxingFlags(); 2863af6ab5fSopenharmony_ci if ((flags & ir::BoxingUnboxingFlags::UNBOXING_FLAG) != 0) { 2873af6ab5fSopenharmony_ci switch (static_cast<ir::BoxingUnboxingFlags>(flags & ir::BoxingUnboxingFlags::UNBOXING_FLAG)) { 2883af6ab5fSopenharmony_ci case ir::BoxingUnboxingFlags::UNBOX_TO_INT: 2893af6ab5fSopenharmony_ci ETSThrowWarning("Implicit Unboxing to int" + GetBoxingUnboxingType(node), node->Start()); 2903af6ab5fSopenharmony_ci break; 2913af6ab5fSopenharmony_ci case ir::BoxingUnboxingFlags::UNBOX_TO_BOOLEAN: 2923af6ab5fSopenharmony_ci ETSThrowWarning("Implicit Unboxing to boolean" + GetBoxingUnboxingType(node), node->Start()); 2933af6ab5fSopenharmony_ci break; 2943af6ab5fSopenharmony_ci case ir::BoxingUnboxingFlags::UNBOX_TO_BYTE: 2953af6ab5fSopenharmony_ci ETSThrowWarning("Implicit Unboxing to byte" + GetBoxingUnboxingType(node), node->Start()); 2963af6ab5fSopenharmony_ci break; 2973af6ab5fSopenharmony_ci case ir::BoxingUnboxingFlags::UNBOX_TO_CHAR: 2983af6ab5fSopenharmony_ci ETSThrowWarning("Implicit Unboxing to char" + GetBoxingUnboxingType(node), node->Start()); 2993af6ab5fSopenharmony_ci break; 3003af6ab5fSopenharmony_ci case ir::BoxingUnboxingFlags::UNBOX_TO_DOUBLE: 3013af6ab5fSopenharmony_ci ETSThrowWarning("Implicit Unboxing to double" + GetBoxingUnboxingType(node), node->Start()); 3023af6ab5fSopenharmony_ci break; 3033af6ab5fSopenharmony_ci case ir::BoxingUnboxingFlags::UNBOX_TO_FLOAT: 3043af6ab5fSopenharmony_ci ETSThrowWarning("Implicit Unboxing to float" + GetBoxingUnboxingType(node), node->Start()); 3053af6ab5fSopenharmony_ci break; 3063af6ab5fSopenharmony_ci case ir::BoxingUnboxingFlags::UNBOX_TO_LONG: 3073af6ab5fSopenharmony_ci ETSThrowWarning("Implicit Unboxing to long" + GetBoxingUnboxingType(node), node->Start()); 3083af6ab5fSopenharmony_ci break; 3093af6ab5fSopenharmony_ci case ir::BoxingUnboxingFlags::UNBOX_TO_SHORT: 3103af6ab5fSopenharmony_ci ETSThrowWarning("Implicit Unboxing to short" + GetBoxingUnboxingType(node), node->Start()); 3113af6ab5fSopenharmony_ci break; 3123af6ab5fSopenharmony_ci default: 3133af6ab5fSopenharmony_ci break; 3143af6ab5fSopenharmony_ci } 3153af6ab5fSopenharmony_ci } 3163af6ab5fSopenharmony_ci} 3173af6ab5fSopenharmony_ci 3183af6ab5fSopenharmony_civoid ETSWarningAnalyzer::CheckTypeOfBoxingUnboxing(const ir::AstNode *node) 3193af6ab5fSopenharmony_ci{ 3203af6ab5fSopenharmony_ci ASSERT(node != nullptr); 3213af6ab5fSopenharmony_ci 3223af6ab5fSopenharmony_ci CheckTypeOfBoxing(node); 3233af6ab5fSopenharmony_ci CheckTypeOfUnboxing(node); 3243af6ab5fSopenharmony_ci} 3253af6ab5fSopenharmony_ci 3263af6ab5fSopenharmony_cistd::string ETSWarningAnalyzer::GetBoxingUnboxingType(const ir::AstNode *node) 3273af6ab5fSopenharmony_ci{ 3283af6ab5fSopenharmony_ci ASSERT(node->Parent() != nullptr); 3293af6ab5fSopenharmony_ci switch (node->Parent()->Type()) { 3303af6ab5fSopenharmony_ci case ir::AstNodeType::VARIABLE_DECLARATOR: { 3313af6ab5fSopenharmony_ci return " in Variable Declaration"; 3323af6ab5fSopenharmony_ci } 3333af6ab5fSopenharmony_ci case ir::AstNodeType::CALL_EXPRESSION: { 3343af6ab5fSopenharmony_ci return " in Call Method/Function"; 3353af6ab5fSopenharmony_ci } 3363af6ab5fSopenharmony_ci case ir::AstNodeType::SWITCH_STATEMENT: { 3373af6ab5fSopenharmony_ci return " in Switch-case Statement"; 3383af6ab5fSopenharmony_ci } 3393af6ab5fSopenharmony_ci case ir::AstNodeType::ASSIGNMENT_EXPRESSION: { 3403af6ab5fSopenharmony_ci return " in Assignment Expression"; 3413af6ab5fSopenharmony_ci } 3423af6ab5fSopenharmony_ci case ir::AstNodeType::BINARY_EXPRESSION: { 3433af6ab5fSopenharmony_ci return " in Binary Expression"; 3443af6ab5fSopenharmony_ci } 3453af6ab5fSopenharmony_ci case ir::AstNodeType::UNARY_EXPRESSION: { 3463af6ab5fSopenharmony_ci return " in Unary Expression"; 3473af6ab5fSopenharmony_ci } 3483af6ab5fSopenharmony_ci case ir::AstNodeType::UPDATE_EXPRESSION: { 3493af6ab5fSopenharmony_ci return " in Update Expression"; 3503af6ab5fSopenharmony_ci } 3513af6ab5fSopenharmony_ci case ir::AstNodeType::MEMBER_EXPRESSION: { 3523af6ab5fSopenharmony_ci return " in Member Expression"; 3533af6ab5fSopenharmony_ci } 3543af6ab5fSopenharmony_ci default: 3553af6ab5fSopenharmony_ci return ""; 3563af6ab5fSopenharmony_ci } 3573af6ab5fSopenharmony_ci} 3583af6ab5fSopenharmony_ci 3593af6ab5fSopenharmony_civoid ETSWarningAnalyzer::ETSWarningImplicitBoxingUnboxing(const ir::AstNode *node) 3603af6ab5fSopenharmony_ci{ 3613af6ab5fSopenharmony_ci ASSERT(node != nullptr); 3623af6ab5fSopenharmony_ci 3633af6ab5fSopenharmony_ci switch (node->Type()) { 3643af6ab5fSopenharmony_ci case ir::AstNodeType::VARIABLE_DECLARATOR: 3653af6ab5fSopenharmony_ci case ir::AstNodeType::SWITCH_STATEMENT: 3663af6ab5fSopenharmony_ci case ir::AstNodeType::CALL_EXPRESSION: 3673af6ab5fSopenharmony_ci case ir::AstNodeType::BINARY_EXPRESSION: 3683af6ab5fSopenharmony_ci case ir::AstNodeType::ASSIGNMENT_EXPRESSION: 3693af6ab5fSopenharmony_ci case ir::AstNodeType::UNARY_EXPRESSION: 3703af6ab5fSopenharmony_ci case ir::AstNodeType::UPDATE_EXPRESSION: 3713af6ab5fSopenharmony_ci case ir::AstNodeType::MEMBER_EXPRESSION: { 3723af6ab5fSopenharmony_ci if (!program_->NodeContainsETSNolint(node, ETSWarnings::IMPLICIT_BOXING_UNBOXING)) { 3733af6ab5fSopenharmony_ci node->Iterate([this](auto *childNode) { CheckTypeOfBoxingUnboxing(childNode); }); 3743af6ab5fSopenharmony_ci } 3753af6ab5fSopenharmony_ci break; 3763af6ab5fSopenharmony_ci } 3773af6ab5fSopenharmony_ci default: { 3783af6ab5fSopenharmony_ci break; 3793af6ab5fSopenharmony_ci } 3803af6ab5fSopenharmony_ci } 3813af6ab5fSopenharmony_ci 3823af6ab5fSopenharmony_ci node->Iterate([&](auto *childNode) { ETSWarningImplicitBoxingUnboxing(childNode); }); 3833af6ab5fSopenharmony_ci} 3843af6ab5fSopenharmony_ci 3853af6ab5fSopenharmony_civoid ETSWarningAnalyzer::ETSThrowWarning(const std::string &message, const lexer::SourcePosition &pos) 3863af6ab5fSopenharmony_ci{ 3873af6ab5fSopenharmony_ci lexer::LineIndex index(program_->SourceCode()); 3883af6ab5fSopenharmony_ci lexer::SourceLocation location = index.GetLocation(pos); 3893af6ab5fSopenharmony_ci 3903af6ab5fSopenharmony_ci if (etsWerror_) { 3913af6ab5fSopenharmony_ci throw Error(ErrorType::ETS_WARNING, ark::es2panda::util::BaseName(program_->SourceFilePath().Utf8()), message, 3923af6ab5fSopenharmony_ci location.line, location.col); 3933af6ab5fSopenharmony_ci } 3943af6ab5fSopenharmony_ci 3953af6ab5fSopenharmony_ci std::cout << "ETS Warning: " << message << "." 3963af6ab5fSopenharmony_ci << " [" << ark::es2panda::util::BaseName(program_->SourceFilePath().Utf8()) << ":" << location.line << ":" 3973af6ab5fSopenharmony_ci << location.col << "]" << std::endl; 3983af6ab5fSopenharmony_ci} 3993af6ab5fSopenharmony_ci 4003af6ab5fSopenharmony_ci} // namespace ark::es2panda::checker 401