13af6ab5fSopenharmony_ci/**
23af6ab5fSopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License.
53af6ab5fSopenharmony_ci * You may obtain a copy of the License at
63af6ab5fSopenharmony_ci *
73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
83af6ab5fSopenharmony_ci *
93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and
133af6ab5fSopenharmony_ci * limitations under the License.
143af6ab5fSopenharmony_ci */
153af6ab5fSopenharmony_ci
163af6ab5fSopenharmony_ci#ifndef ES2PANDA_CHECKER_CHECKER_H
173af6ab5fSopenharmony_ci#define ES2PANDA_CHECKER_CHECKER_H
183af6ab5fSopenharmony_ci
193af6ab5fSopenharmony_ci#include "es2panda.h"
203af6ab5fSopenharmony_ci
213af6ab5fSopenharmony_ci#include "checker/checkerContext.h"
223af6ab5fSopenharmony_ci#include "checker/SemanticAnalyzer.h"
233af6ab5fSopenharmony_ci#include "util/errorLogger.h"
243af6ab5fSopenharmony_ci
253af6ab5fSopenharmony_cinamespace ark::es2panda::parser {
263af6ab5fSopenharmony_ciclass Program;
273af6ab5fSopenharmony_ci}  // namespace ark::es2panda::parser
283af6ab5fSopenharmony_ci
293af6ab5fSopenharmony_cinamespace ark::es2panda::ir {
303af6ab5fSopenharmony_ciclass AstNode;
313af6ab5fSopenharmony_ciclass Expression;
323af6ab5fSopenharmony_ciclass BlockStatement;
333af6ab5fSopenharmony_cienum class AstNodeType;
343af6ab5fSopenharmony_ci}  // namespace ark::es2panda::ir
353af6ab5fSopenharmony_ci
363af6ab5fSopenharmony_cinamespace ark::es2panda::varbinder {
373af6ab5fSopenharmony_ciclass VarBinder;
383af6ab5fSopenharmony_ciclass Decl;
393af6ab5fSopenharmony_ciclass EnumVariable;
403af6ab5fSopenharmony_ciclass FunctionDecl;
413af6ab5fSopenharmony_ciclass LocalVariable;
423af6ab5fSopenharmony_ciclass Scope;
433af6ab5fSopenharmony_ciclass Variable;
443af6ab5fSopenharmony_ci}  // namespace ark::es2panda::varbinder
453af6ab5fSopenharmony_ci
463af6ab5fSopenharmony_cinamespace ark::es2panda::checker {
473af6ab5fSopenharmony_ciclass ETSChecker;
483af6ab5fSopenharmony_ciclass InterfaceType;
493af6ab5fSopenharmony_ciclass GlobalTypesHolder;
503af6ab5fSopenharmony_ci
513af6ab5fSopenharmony_ciusing StringLiteralPool = std::unordered_map<util::StringView, Type *>;
523af6ab5fSopenharmony_ciusing NumberLiteralPool = std::unordered_map<double, Type *>;
533af6ab5fSopenharmony_ciusing FunctionParamsResolveResult = std::variant<std::vector<varbinder::LocalVariable *> &, bool>;
543af6ab5fSopenharmony_ciusing InterfacePropertyMap =
553af6ab5fSopenharmony_ci    std::unordered_map<util::StringView, std::pair<varbinder::LocalVariable *, InterfaceType *>>;
563af6ab5fSopenharmony_ciusing TypeOrNode = std::variant<Type *, ir::AstNode *>;
573af6ab5fSopenharmony_ciusing IndexInfoTypePair = std::pair<Type *, Type *>;
583af6ab5fSopenharmony_ciusing PropertyMap = std::unordered_map<util::StringView, varbinder::LocalVariable *>;
593af6ab5fSopenharmony_ciusing ArgRange = std::pair<uint32_t, uint32_t>;
603af6ab5fSopenharmony_ci
613af6ab5fSopenharmony_ciclass Checker {
623af6ab5fSopenharmony_cipublic:
633af6ab5fSopenharmony_ci    explicit Checker();
643af6ab5fSopenharmony_ci    virtual ~Checker() = default;
653af6ab5fSopenharmony_ci
663af6ab5fSopenharmony_ci    NO_COPY_SEMANTIC(Checker);
673af6ab5fSopenharmony_ci    NO_MOVE_SEMANTIC(Checker);
683af6ab5fSopenharmony_ci
693af6ab5fSopenharmony_ci    [[nodiscard]] ArenaAllocator *Allocator() noexcept
703af6ab5fSopenharmony_ci    {
713af6ab5fSopenharmony_ci        return &allocator_;
723af6ab5fSopenharmony_ci    }
733af6ab5fSopenharmony_ci
743af6ab5fSopenharmony_ci    [[nodiscard]] varbinder::Scope *Scope() const noexcept
753af6ab5fSopenharmony_ci    {
763af6ab5fSopenharmony_ci        return scope_;
773af6ab5fSopenharmony_ci    }
783af6ab5fSopenharmony_ci
793af6ab5fSopenharmony_ci    [[nodiscard]] CheckerContext &Context() noexcept
803af6ab5fSopenharmony_ci    {
813af6ab5fSopenharmony_ci        return context_;
823af6ab5fSopenharmony_ci    }
833af6ab5fSopenharmony_ci
843af6ab5fSopenharmony_ci    [[nodiscard]] bool HasStatus(CheckerStatus status) noexcept
853af6ab5fSopenharmony_ci    {
863af6ab5fSopenharmony_ci        return (context_.Status() & status) != 0;
873af6ab5fSopenharmony_ci    }
883af6ab5fSopenharmony_ci
893af6ab5fSopenharmony_ci    void RemoveStatus(CheckerStatus status) noexcept
903af6ab5fSopenharmony_ci    {
913af6ab5fSopenharmony_ci        context_.Status() &= ~status;
923af6ab5fSopenharmony_ci    }
933af6ab5fSopenharmony_ci
943af6ab5fSopenharmony_ci    void AddStatus(CheckerStatus status) noexcept
953af6ab5fSopenharmony_ci    {
963af6ab5fSopenharmony_ci        context_.Status() |= status;
973af6ab5fSopenharmony_ci    }
983af6ab5fSopenharmony_ci
993af6ab5fSopenharmony_ci    [[nodiscard]] TypeRelation *Relation() const noexcept
1003af6ab5fSopenharmony_ci    {
1013af6ab5fSopenharmony_ci        return relation_;
1023af6ab5fSopenharmony_ci    }
1033af6ab5fSopenharmony_ci
1043af6ab5fSopenharmony_ci    [[nodiscard]] GlobalTypesHolder *GetGlobalTypesHolder() const noexcept
1053af6ab5fSopenharmony_ci    {
1063af6ab5fSopenharmony_ci        return globalTypes_;
1073af6ab5fSopenharmony_ci    }
1083af6ab5fSopenharmony_ci
1093af6ab5fSopenharmony_ci    [[nodiscard]] RelationHolder &IdenticalResults() noexcept
1103af6ab5fSopenharmony_ci    {
1113af6ab5fSopenharmony_ci        return identicalResults_;
1123af6ab5fSopenharmony_ci    }
1133af6ab5fSopenharmony_ci
1143af6ab5fSopenharmony_ci    [[nodiscard]] RelationHolder &AssignableResults() noexcept
1153af6ab5fSopenharmony_ci    {
1163af6ab5fSopenharmony_ci        return assignableResults_;
1173af6ab5fSopenharmony_ci    }
1183af6ab5fSopenharmony_ci
1193af6ab5fSopenharmony_ci    [[nodiscard]] RelationHolder &ComparableResults() noexcept
1203af6ab5fSopenharmony_ci    {
1213af6ab5fSopenharmony_ci        return comparableResults_;
1223af6ab5fSopenharmony_ci    }
1233af6ab5fSopenharmony_ci
1243af6ab5fSopenharmony_ci    [[nodiscard]] RelationHolder &UncheckedCastableResult() noexcept
1253af6ab5fSopenharmony_ci    {
1263af6ab5fSopenharmony_ci        return uncheckedCastableResults_;
1273af6ab5fSopenharmony_ci    }
1283af6ab5fSopenharmony_ci
1293af6ab5fSopenharmony_ci    [[nodiscard]] RelationHolder &SupertypeResults() noexcept
1303af6ab5fSopenharmony_ci    {
1313af6ab5fSopenharmony_ci        return supertypeResults_;
1323af6ab5fSopenharmony_ci    }
1333af6ab5fSopenharmony_ci
1343af6ab5fSopenharmony_ci    [[nodiscard]] std::unordered_set<const void *> &TypeStack() noexcept
1353af6ab5fSopenharmony_ci    {
1363af6ab5fSopenharmony_ci        return typeStack_;
1373af6ab5fSopenharmony_ci    }
1383af6ab5fSopenharmony_ci
1393af6ab5fSopenharmony_ci    [[nodiscard]] std::unordered_set<Type *> &NamedTypeStack() noexcept
1403af6ab5fSopenharmony_ci    {
1413af6ab5fSopenharmony_ci        return namedTypeStack_;
1423af6ab5fSopenharmony_ci    }
1433af6ab5fSopenharmony_ci
1443af6ab5fSopenharmony_ci    [[nodiscard]] virtual bool IsETSChecker() const noexcept
1453af6ab5fSopenharmony_ci    {
1463af6ab5fSopenharmony_ci        return false;
1473af6ab5fSopenharmony_ci    }
1483af6ab5fSopenharmony_ci
1493af6ab5fSopenharmony_ci    [[nodiscard]] ETSChecker *AsETSChecker()
1503af6ab5fSopenharmony_ci    {
1513af6ab5fSopenharmony_ci        ASSERT(IsETSChecker());
1523af6ab5fSopenharmony_ci        return reinterpret_cast<ETSChecker *>(this);
1533af6ab5fSopenharmony_ci    }
1543af6ab5fSopenharmony_ci
1553af6ab5fSopenharmony_ci    [[nodiscard]] const ETSChecker *AsETSChecker() const
1563af6ab5fSopenharmony_ci    {
1573af6ab5fSopenharmony_ci        ASSERT(IsETSChecker());
1583af6ab5fSopenharmony_ci        return reinterpret_cast<const ETSChecker *>(this);
1593af6ab5fSopenharmony_ci    }
1603af6ab5fSopenharmony_ci
1613af6ab5fSopenharmony_ci    virtual bool StartChecker([[maybe_unused]] varbinder::VarBinder *varbinder, const CompilerOptions &options) = 0;
1623af6ab5fSopenharmony_ci    virtual Type *CheckTypeCached(ir::Expression *expr) = 0;
1633af6ab5fSopenharmony_ci    virtual Type *GetTypeOfVariable(varbinder::Variable *var) = 0;
1643af6ab5fSopenharmony_ci    virtual void ResolveStructuredTypeMembers(Type *type) = 0;
1653af6ab5fSopenharmony_ci
1663af6ab5fSopenharmony_ci    std::string FormatMsg(std::initializer_list<TypeErrorMessageElement> list);
1673af6ab5fSopenharmony_ci    [[noreturn]] void ThrowTypeError(std::string_view message, const lexer::SourcePosition &pos);
1683af6ab5fSopenharmony_ci    [[noreturn]] void ThrowTypeError(std::initializer_list<TypeErrorMessageElement> list,
1693af6ab5fSopenharmony_ci                                     const lexer::SourcePosition &pos);
1703af6ab5fSopenharmony_ci    void LogTypeError(std::string_view message, const lexer::SourcePosition &pos);
1713af6ab5fSopenharmony_ci    void LogTypeError(std::initializer_list<TypeErrorMessageElement> list, const lexer::SourcePosition &pos);
1723af6ab5fSopenharmony_ci    void Warning(std::string_view message, const lexer::SourcePosition &pos) const;
1733af6ab5fSopenharmony_ci    void ReportWarning(std::initializer_list<TypeErrorMessageElement> list, const lexer::SourcePosition &pos);
1743af6ab5fSopenharmony_ci
1753af6ab5fSopenharmony_ci    bool IsTypeIdenticalTo(Type *source, Type *target);
1763af6ab5fSopenharmony_ci    bool IsTypeIdenticalTo(Type *source, Type *target, const std::string &errMsg, const lexer::SourcePosition &errPos);
1773af6ab5fSopenharmony_ci    bool IsTypeIdenticalTo(Type *source, Type *target, std::initializer_list<TypeErrorMessageElement> list,
1783af6ab5fSopenharmony_ci                           const lexer::SourcePosition &errPos);
1793af6ab5fSopenharmony_ci    bool IsTypeAssignableTo(Type *source, Type *target);
1803af6ab5fSopenharmony_ci    bool IsTypeAssignableTo(Type *source, Type *target, const std::string &errMsg, const lexer::SourcePosition &errPos);
1813af6ab5fSopenharmony_ci    bool IsTypeAssignableTo(Type *source, Type *target, std::initializer_list<TypeErrorMessageElement> list,
1823af6ab5fSopenharmony_ci                            const lexer::SourcePosition &errPos);
1833af6ab5fSopenharmony_ci    bool IsTypeComparableTo(Type *source, Type *target);
1843af6ab5fSopenharmony_ci    bool IsTypeComparableTo(Type *source, Type *target, const std::string &errMsg, const lexer::SourcePosition &errPos);
1853af6ab5fSopenharmony_ci    bool IsTypeComparableTo(Type *source, Type *target, std::initializer_list<TypeErrorMessageElement> list,
1863af6ab5fSopenharmony_ci                            const lexer::SourcePosition &errPos);
1873af6ab5fSopenharmony_ci    bool AreTypesComparable(Type *source, Type *target);
1883af6ab5fSopenharmony_ci    bool IsTypeEqualityComparableTo(Type *source, Type *target);
1893af6ab5fSopenharmony_ci    bool IsAllTypesAssignableTo(Type *source, Type *target);
1903af6ab5fSopenharmony_ci    void SetAnalyzer(SemanticAnalyzer *analyzer);
1913af6ab5fSopenharmony_ci    checker::SemanticAnalyzer *GetAnalyzer() const;
1923af6ab5fSopenharmony_ci
1933af6ab5fSopenharmony_ci    friend class ScopeContext;
1943af6ab5fSopenharmony_ci    friend class TypeStackElement;
1953af6ab5fSopenharmony_ci    friend class NamedTypeStackElement;
1963af6ab5fSopenharmony_ci    friend class SavedCheckerContext;
1973af6ab5fSopenharmony_ci    friend class NamedTypeStackElement;
1983af6ab5fSopenharmony_ci
1993af6ab5fSopenharmony_ci    varbinder::VarBinder *VarBinder() const;
2003af6ab5fSopenharmony_ci
2013af6ab5fSopenharmony_ci    util::ErrorLogger *ErrorLogger()
2023af6ab5fSopenharmony_ci    {
2033af6ab5fSopenharmony_ci        return &errorLogger_;
2043af6ab5fSopenharmony_ci    }
2053af6ab5fSopenharmony_ci
2063af6ab5fSopenharmony_ci    // NOTE: required only for evaluate.
2073af6ab5fSopenharmony_ci    void Initialize(varbinder::VarBinder *varbinder);
2083af6ab5fSopenharmony_ci
2093af6ab5fSopenharmony_ciprotected:
2103af6ab5fSopenharmony_ci    parser::Program *Program() const;
2113af6ab5fSopenharmony_ci    void SetProgram(parser::Program *program);
2123af6ab5fSopenharmony_ci
2133af6ab5fSopenharmony_ciprivate:
2143af6ab5fSopenharmony_ci    ArenaAllocator allocator_;
2153af6ab5fSopenharmony_ci    CheckerContext context_;
2163af6ab5fSopenharmony_ci    GlobalTypesHolder *globalTypes_;
2173af6ab5fSopenharmony_ci    TypeRelation *relation_;
2183af6ab5fSopenharmony_ci    SemanticAnalyzer *analyzer_ {};
2193af6ab5fSopenharmony_ci    varbinder::VarBinder *varbinder_ {};
2203af6ab5fSopenharmony_ci    parser::Program *program_ {};
2213af6ab5fSopenharmony_ci    varbinder::Scope *scope_ {};
2223af6ab5fSopenharmony_ci    util::ErrorLogger errorLogger_;
2233af6ab5fSopenharmony_ci
2243af6ab5fSopenharmony_ci    RelationHolder identicalResults_ {{}, RelationType::IDENTICAL};
2253af6ab5fSopenharmony_ci    RelationHolder assignableResults_ {{}, RelationType::ASSIGNABLE};
2263af6ab5fSopenharmony_ci    RelationHolder comparableResults_ {{}, RelationType::COMPARABLE};
2273af6ab5fSopenharmony_ci    RelationHolder uncheckedCastableResults_ {{}, RelationType::UNCHECKED_CASTABLE};
2283af6ab5fSopenharmony_ci    RelationHolder supertypeResults_ {{}, RelationType::SUPERTYPE};
2293af6ab5fSopenharmony_ci
2303af6ab5fSopenharmony_ci    std::unordered_set<const void *> typeStack_;
2313af6ab5fSopenharmony_ci    std::unordered_set<Type *> namedTypeStack_;
2323af6ab5fSopenharmony_ci};
2333af6ab5fSopenharmony_ci
2343af6ab5fSopenharmony_ciclass NamedTypeStackElement {
2353af6ab5fSopenharmony_cipublic:
2363af6ab5fSopenharmony_ci    explicit NamedTypeStackElement(Checker *checker, Type *element) : checker_(checker), element_(element)
2373af6ab5fSopenharmony_ci    {
2383af6ab5fSopenharmony_ci        checker_->namedTypeStack_.insert(element);
2393af6ab5fSopenharmony_ci    }
2403af6ab5fSopenharmony_ci
2413af6ab5fSopenharmony_ci    ~NamedTypeStackElement()
2423af6ab5fSopenharmony_ci    {
2433af6ab5fSopenharmony_ci        checker_->namedTypeStack_.erase(element_);
2443af6ab5fSopenharmony_ci    }
2453af6ab5fSopenharmony_ci    NO_COPY_SEMANTIC(NamedTypeStackElement);
2463af6ab5fSopenharmony_ci    NO_MOVE_SEMANTIC(NamedTypeStackElement);
2473af6ab5fSopenharmony_ci
2483af6ab5fSopenharmony_ciprivate:
2493af6ab5fSopenharmony_ci    Checker *checker_;
2503af6ab5fSopenharmony_ci    Type *element_;
2513af6ab5fSopenharmony_ci};
2523af6ab5fSopenharmony_ci
2533af6ab5fSopenharmony_ciclass TypeStackElement {
2543af6ab5fSopenharmony_cipublic:
2553af6ab5fSopenharmony_ci    explicit TypeStackElement(Checker *checker, void *element, std::initializer_list<TypeErrorMessageElement> list,
2563af6ab5fSopenharmony_ci                              const lexer::SourcePosition &pos)
2573af6ab5fSopenharmony_ci        : checker_(checker), element_(element), hasErrorChecker_(false)
2583af6ab5fSopenharmony_ci    {
2593af6ab5fSopenharmony_ci        if (!checker->typeStack_.insert(element).second) {
2603af6ab5fSopenharmony_ci            checker_->LogTypeError(list, pos);
2613af6ab5fSopenharmony_ci            element_ = nullptr;
2623af6ab5fSopenharmony_ci        }
2633af6ab5fSopenharmony_ci    }
2643af6ab5fSopenharmony_ci
2653af6ab5fSopenharmony_ci    explicit TypeStackElement(Checker *checker, void *element, std::string_view err, const lexer::SourcePosition &pos)
2663af6ab5fSopenharmony_ci        : checker_(checker), element_(element), hasErrorChecker_(false)
2673af6ab5fSopenharmony_ci    {
2683af6ab5fSopenharmony_ci        if (!checker->typeStack_.insert(element).second) {
2693af6ab5fSopenharmony_ci            checker_->LogTypeError(err, pos);
2703af6ab5fSopenharmony_ci            element_ = nullptr;
2713af6ab5fSopenharmony_ci        }
2723af6ab5fSopenharmony_ci    }
2733af6ab5fSopenharmony_ci
2743af6ab5fSopenharmony_ci    bool HasTypeError()
2753af6ab5fSopenharmony_ci    {
2763af6ab5fSopenharmony_ci        hasErrorChecker_ = true;
2773af6ab5fSopenharmony_ci        return element_ == nullptr;
2783af6ab5fSopenharmony_ci    }
2793af6ab5fSopenharmony_ci
2803af6ab5fSopenharmony_ci    ~TypeStackElement()
2813af6ab5fSopenharmony_ci    {
2823af6ab5fSopenharmony_ci        ASSERT(hasErrorChecker_);
2833af6ab5fSopenharmony_ci        if (element_ != nullptr) {
2843af6ab5fSopenharmony_ci            checker_->typeStack_.erase(element_);
2853af6ab5fSopenharmony_ci        }
2863af6ab5fSopenharmony_ci    }
2873af6ab5fSopenharmony_ci
2883af6ab5fSopenharmony_ci    NO_COPY_SEMANTIC(TypeStackElement);
2893af6ab5fSopenharmony_ci    NO_MOVE_SEMANTIC(TypeStackElement);
2903af6ab5fSopenharmony_ci
2913af6ab5fSopenharmony_ciprivate:
2923af6ab5fSopenharmony_ci    Checker *checker_;
2933af6ab5fSopenharmony_ci    void *element_;
2943af6ab5fSopenharmony_ci    bool hasErrorChecker_;
2953af6ab5fSopenharmony_ci};
2963af6ab5fSopenharmony_ci
2973af6ab5fSopenharmony_ciclass ScopeContext {
2983af6ab5fSopenharmony_cipublic:
2993af6ab5fSopenharmony_ci    explicit ScopeContext(Checker *checker, varbinder::Scope *newScope)
3003af6ab5fSopenharmony_ci        : checker_(checker), prevScope_(checker_->scope_)
3013af6ab5fSopenharmony_ci    {
3023af6ab5fSopenharmony_ci        checker_->scope_ = newScope;
3033af6ab5fSopenharmony_ci    }
3043af6ab5fSopenharmony_ci
3053af6ab5fSopenharmony_ci    ~ScopeContext()
3063af6ab5fSopenharmony_ci    {
3073af6ab5fSopenharmony_ci        checker_->scope_ = prevScope_;
3083af6ab5fSopenharmony_ci    }
3093af6ab5fSopenharmony_ci
3103af6ab5fSopenharmony_ci    NO_COPY_SEMANTIC(ScopeContext);
3113af6ab5fSopenharmony_ci    NO_MOVE_SEMANTIC(ScopeContext);
3123af6ab5fSopenharmony_ci
3133af6ab5fSopenharmony_ciprivate:
3143af6ab5fSopenharmony_ci    Checker *checker_;
3153af6ab5fSopenharmony_ci    varbinder::Scope *prevScope_;
3163af6ab5fSopenharmony_ci};
3173af6ab5fSopenharmony_ci
3183af6ab5fSopenharmony_ciclass SavedCheckerContext {
3193af6ab5fSopenharmony_cipublic:
3203af6ab5fSopenharmony_ci    explicit SavedCheckerContext(Checker *checker, CheckerStatus newStatus)
3213af6ab5fSopenharmony_ci        : SavedCheckerContext(checker, newStatus, nullptr)
3223af6ab5fSopenharmony_ci    {
3233af6ab5fSopenharmony_ci    }
3243af6ab5fSopenharmony_ci
3253af6ab5fSopenharmony_ci    explicit SavedCheckerContext(Checker *checker, CheckerStatus newStatus, const ETSObjectType *containingClass)
3263af6ab5fSopenharmony_ci        : SavedCheckerContext(checker, newStatus, containingClass, nullptr)
3273af6ab5fSopenharmony_ci    {
3283af6ab5fSopenharmony_ci    }
3293af6ab5fSopenharmony_ci
3303af6ab5fSopenharmony_ci    explicit SavedCheckerContext(Checker *checker, CheckerStatus newStatus, const ETSObjectType *containingClass,
3313af6ab5fSopenharmony_ci                                 Signature *containingSignature)
3323af6ab5fSopenharmony_ci        : checker_(checker), prev_(checker->context_)
3333af6ab5fSopenharmony_ci    {
3343af6ab5fSopenharmony_ci        const bool inExternal = checker->HasStatus(CheckerStatus::IN_EXTERNAL);
3353af6ab5fSopenharmony_ci        checker_->context_ = CheckerContext(checker, newStatus, containingClass, containingSignature);
3363af6ab5fSopenharmony_ci        if (inExternal) {
3373af6ab5fSopenharmony_ci            // handled here instead of at call sites to make things more foolproof
3383af6ab5fSopenharmony_ci            checker_->context_.Status() |= CheckerStatus::IN_EXTERNAL;
3393af6ab5fSopenharmony_ci        }
3403af6ab5fSopenharmony_ci    }
3413af6ab5fSopenharmony_ci
3423af6ab5fSopenharmony_ci    NO_COPY_SEMANTIC(SavedCheckerContext);
3433af6ab5fSopenharmony_ci    DEFAULT_MOVE_SEMANTIC(SavedCheckerContext);
3443af6ab5fSopenharmony_ci
3453af6ab5fSopenharmony_ci    ~SavedCheckerContext()
3463af6ab5fSopenharmony_ci    {
3473af6ab5fSopenharmony_ci        checker_->context_ = prev_;
3483af6ab5fSopenharmony_ci    }
3493af6ab5fSopenharmony_ci
3503af6ab5fSopenharmony_ciprivate:
3513af6ab5fSopenharmony_ci    Checker *checker_;
3523af6ab5fSopenharmony_ci    CheckerContext prev_;
3533af6ab5fSopenharmony_ci};
3543af6ab5fSopenharmony_ci
3553af6ab5fSopenharmony_ci}  // namespace ark::es2panda::checker
3563af6ab5fSopenharmony_ci
3573af6ab5fSopenharmony_ci#endif /* CHECKER_H */
358