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 
26 namespace ark::es2panda::varbinder {
BoundContext(RecordTable *recordTable, ir::ClassDefinition *classDef, bool force)27 BoundContext::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 
BoundContext(RecordTable *recordTable, ir::TSInterfaceDeclaration *interfaceDecl, bool force)45 BoundContext::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 
~BoundContext()63 BoundContext::~BoundContext()
64 {
65     recordTable_->record_ = savedRecord_;
66     recordTable_->boundCtx_ = prev_;
67 }
68 
FormRecordName() const69 util::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 
RecordName() const99 util::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