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 "recordTable.h"
17#include "parser/program/program.h"
18#include "varbinder/ETSBinder.h"
19#include "ir/base/classDefinition.h"
20#include "ir/expressions/identifier.h"
21#include "ir/ts/tsEnumDeclaration.h"
22#include "ir/ts/tsInterfaceDeclaration.h"
23#include "checker/types/ets/etsObjectType.h"
24#include "generated/signatures.h"
25
26namespace ark::es2panda::varbinder {
27BoundContext::BoundContext(RecordTable *recordTable, ir::ClassDefinition *classDef, bool force)
28    : prev_(recordTable->boundCtx_),
29      recordTable_(recordTable),
30      currentRecord_(classDef),
31      savedRecord_(recordTable->record_)
32{
33    if (classDef == nullptr || (!force && !recordTable_->classDefinitions_.insert(classDef).second)) {
34        return;
35    }
36
37    recordTable_->boundCtx_ = this;
38    recordTable_->record_ = classDef;
39    recordIdent_ = classDef->Ident();
40    if (classDef->InternalName().Empty()) {
41        classDef->SetInternalName(FormRecordName());
42    }
43}
44
45BoundContext::BoundContext(RecordTable *recordTable, ir::TSInterfaceDeclaration *interfaceDecl, bool force)
46    : prev_(recordTable->boundCtx_),
47      recordTable_(recordTable),
48      currentRecord_(interfaceDecl),
49      savedRecord_(recordTable->record_)
50{
51    if (interfaceDecl == nullptr || (!force && !recordTable_->interfaceDeclarations_.insert(interfaceDecl).second)) {
52        return;
53    }
54
55    recordTable_->boundCtx_ = this;
56    recordTable_->record_ = interfaceDecl;
57    recordIdent_ = interfaceDecl->Id();
58    if (interfaceDecl->InternalName() == "") {
59        interfaceDecl->SetInternalName(FormRecordName());
60    }
61}
62
63BoundContext::~BoundContext()
64{
65    recordTable_->record_ = savedRecord_;
66    recordTable_->boundCtx_ = prev_;
67}
68
69util::StringView BoundContext::FormRecordName() const
70{
71    if (prev_ == nullptr) {
72        if (recordTable_->program_->OmitModuleName()) {
73            return recordIdent_->Name();
74        }
75
76        const auto &moduleName = recordTable_->program_->ModuleName();
77
78        // concatenate the module name with the record ident
79        return util::UString(moduleName.Mutf8() + compiler::Signatures::METHOD_SEPARATOR.data() +
80                                 recordIdent_->Name().Mutf8(),
81                             recordTable_->program_->Allocator())
82            .View();
83    }
84
85    util::UString recordName(recordTable_->program_->Allocator());
86    recordName.Append(prev_->FormRecordName());
87    recordName.Append(compiler::Signatures::METHOD_SEPARATOR);
88    if (std::holds_alternative<ir::ClassDefinition *>(currentRecord_)) {
89        const auto *classDef = std::get<ir::ClassDefinition *>(currentRecord_);
90        if (classDef->IsLocal()) {
91            recordName.Append(classDef->LocalPrefix());
92        }
93    }
94
95    recordName.Append(recordIdent_->Name());
96    return recordName.View();
97}
98
99util::StringView RecordTable::RecordName() const
100{
101    if (std::holds_alternative<ir::ClassDefinition *>(record_)) {
102        return std::get<ir::ClassDefinition *>(record_)->InternalName();
103    }
104
105    ASSERT(std::holds_alternative<ir::TSInterfaceDeclaration *>(record_));
106    return std::get<ir::TSInterfaceDeclaration *>(record_)->InternalName();
107}
108
109}  // namespace ark::es2panda::varbinder
110