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