1 /**
2 * Copyright (c) 2021 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 "interfaceType.h"
17
18 #include <typescript/checker.h>
19
20 namespace panda::es2panda::checker {
21
ToString(std::stringstream & ss) const22 void InterfaceType::ToString(std::stringstream &ss) const
23 {
24 ss << name_;
25
26 if (!typeParamTypes_.empty()) {
27 ss << "<";
28
29 for (auto it = typeParamTypes_.begin(); it != typeParamTypes_.end(); it++) {
30 (*it)->ToString(ss);
31
32 if (std::next(it) != typeParamTypes_.end()) {
33 ss << ", ";
34 }
35 }
36
37 ss << ">";
38 }
39 }
40
IsPropertiesIdentical(TypeRelation * relation,InterfaceType * other)41 bool InterfaceType::IsPropertiesIdentical(TypeRelation *relation, InterfaceType *other)
42 {
43 const ArenaVector<binder::LocalVariable *> &targetProperties = Properties();
44 const ArenaVector<binder::LocalVariable *> &sourceProperties = other->Properties();
45 if (targetProperties.size() != sourceProperties.size()) {
46 relation->Result(false);
47 return false;
48 }
49
50 for (auto *targetProp : targetProperties) {
51 bool foundProp =
52 std::any_of(sourceProperties.begin(), sourceProperties.end(),
53 [targetProp, relation](binder::LocalVariable *sourceProp) {
54 if (targetProp->Name() == sourceProp->Name()) {
55 Type *targetType = relation->GetChecker()->GetTypeOfVariable(targetProp);
56 Type *sourceType = relation->GetChecker()->GetTypeOfVariable(sourceProp);
57 return relation->IsIdenticalTo(targetType, sourceType);
58 }
59
60 return false;
61 });
62 if (!foundProp) {
63 relation->Result(false);
64 return false;
65 }
66 }
67
68 return true;
69 }
70
IsIndexInfoIdentical(TypeRelation * relation,InterfaceType * other)71 bool InterfaceType::IsIndexInfoIdentical(TypeRelation *relation, InterfaceType *other)
72 {
73 IndexInfo *targetNumberInfo = NumberIndexInfo();
74 IndexInfo *sourceNumberInfo = other->NumberIndexInfo();
75 if ((targetNumberInfo && !sourceNumberInfo) || (!targetNumberInfo && sourceNumberInfo)) {
76 relation->Result(false);
77 return false;
78 }
79
80 relation->IsIdenticalTo(targetNumberInfo, sourceNumberInfo);
81
82 if (relation->IsTrue()) {
83 IndexInfo *targetStringInfo = StringIndexInfo();
84 IndexInfo *sourceStringInfo = other->StringIndexInfo();
85
86 if ((targetStringInfo && !sourceStringInfo) || (!targetStringInfo && sourceStringInfo)) {
87 relation->Result(false);
88 return false;
89 }
90
91 relation->IsIdenticalTo(targetStringInfo, sourceStringInfo);
92 }
93
94 return true;
95 }
96
Identical(TypeRelation * relation,Type * other)97 void InterfaceType::Identical(TypeRelation *relation, Type *other)
98 {
99 if (!other->IsObjectType() || !other->AsObjectType()->IsInterfaceType()) {
100 return;
101 }
102
103 InterfaceType *otherInterface = other->AsObjectType()->AsInterfaceType();
104 if (!IsPropertiesIdentical(relation, otherInterface)) {
105 return;
106 }
107
108 const ArenaVector<Signature *> &targetCallSignatures = CallSignatures();
109 const ArenaVector<Signature *> &sourceCallSignatures = otherInterface->CallSignatures();
110 if (targetCallSignatures.size() != sourceCallSignatures.size()) {
111 relation->Result(false);
112 return;
113 }
114
115 if (!EachSignatureRelatedToSomeSignature(relation, targetCallSignatures, sourceCallSignatures) ||
116 !EachSignatureRelatedToSomeSignature(relation, sourceCallSignatures, targetCallSignatures)) {
117 return;
118 }
119
120 const ArenaVector<Signature *> &targetConstructSignatures = ConstructSignatures();
121 const ArenaVector<Signature *> &sourceConstructSignatures = otherInterface->ConstructSignatures();
122 if (targetConstructSignatures.size() != sourceConstructSignatures.size()) {
123 relation->Result(false);
124 return;
125 }
126
127 if (!EachSignatureRelatedToSomeSignature(relation, targetConstructSignatures, sourceConstructSignatures) ||
128 !EachSignatureRelatedToSomeSignature(relation, sourceConstructSignatures, targetConstructSignatures)) {
129 return;
130 }
131
132 if (!IsIndexInfoIdentical(relation, otherInterface)) {
133 return;
134 }
135 }
136
Instantiate(ArenaAllocator * allocator,TypeRelation * relation,GlobalTypesHolder * globalTypes)137 Type *InterfaceType::Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes)
138 {
139 ObjectDescriptor *copiedDesc = allocator->New<ObjectDescriptor>(allocator);
140
141 desc_->Copy(allocator, copiedDesc, relation, globalTypes);
142
143 Type *newInterfaceType = allocator->New<InterfaceType>(allocator, name_, copiedDesc);
144 CHECK_NOT_NULL(newInterfaceType);
145 for (auto *it : bases_) {
146 newInterfaceType->AsObjectType()->AsInterfaceType()->AddBase(
147 it->Instantiate(allocator, relation, globalTypes)->AsObjectType());
148 }
149
150 return newInterfaceType;
151 }
152
CollectSignatures(ArenaVector<Signature * > * collectedSignatures,bool collectCallSignatures) const153 void InterfaceType::CollectSignatures(ArenaVector<Signature *> *collectedSignatures, bool collectCallSignatures) const
154 {
155 if (collectCallSignatures) {
156 for (auto *it : desc_->callSignatures) {
157 collectedSignatures->push_back(it);
158 }
159 } else {
160 for (auto *it : desc_->constructSignatures) {
161 collectedSignatures->push_back(it);
162 }
163 }
164
165 for (auto *it : bases_) {
166 it->AsInterfaceType()->CollectSignatures(collectedSignatures, collectCallSignatures);
167 }
168 }
169
CollectProperties(ArenaVector<binder::LocalVariable * > * collectedPropeties) const170 void InterfaceType::CollectProperties(ArenaVector<binder::LocalVariable *> *collectedPropeties) const
171 {
172 for (auto *currentProp : desc_->properties) {
173 bool propAlreadyCollected = false;
174 for (auto *collectedProp : *collectedPropeties) {
175 if (currentProp->Name() == collectedProp->Name()) {
176 propAlreadyCollected = true;
177 break;
178 }
179 }
180
181 if (propAlreadyCollected) {
182 continue;
183 }
184
185 collectedPropeties->push_back(currentProp);
186 }
187
188 for (auto *it : bases_) {
189 it->AsInterfaceType()->CollectProperties(collectedPropeties);
190 }
191 }
192
FindIndexInfo(bool findNumberInfo) const193 const IndexInfo *InterfaceType::FindIndexInfo(bool findNumberInfo) const
194 {
195 const IndexInfo *foundInfo = nullptr;
196
197 if (findNumberInfo && desc_->numberIndexInfo) {
198 foundInfo = desc_->numberIndexInfo;
199 } else if (!findNumberInfo && desc_->stringIndexInfo) {
200 foundInfo = desc_->stringIndexInfo;
201 }
202
203 for (auto it = bases_.begin(); it != bases_.end() && !foundInfo; it++) {
204 foundInfo = (*it)->AsInterfaceType()->FindIndexInfo(findNumberInfo);
205 }
206
207 return foundInfo;
208 }
209
FindIndexInfo(bool findNumberInfo)210 IndexInfo *InterfaceType::FindIndexInfo(bool findNumberInfo)
211 {
212 IndexInfo *foundInfo = nullptr;
213
214 if (findNumberInfo && desc_->numberIndexInfo) {
215 foundInfo = desc_->numberIndexInfo;
216 } else if (!findNumberInfo && desc_->stringIndexInfo) {
217 foundInfo = desc_->stringIndexInfo;
218 }
219
220 for (auto it = bases_.begin(); it != bases_.end() && !foundInfo; it++) {
221 foundInfo = (*it)->AsInterfaceType()->FindIndexInfo(findNumberInfo);
222 }
223
224 return foundInfo;
225 }
226
GetTypeFacts() const227 TypeFacts InterfaceType::GetTypeFacts() const
228 {
229 if (desc_->properties.empty() && desc_->callSignatures.empty() && desc_->constructSignatures.empty() &&
230 !desc_->stringIndexInfo && !desc_->numberIndexInfo) {
231 if (bases_.empty()) {
232 return TypeFacts::EMPTY_OBJECT_FACTS;
233 }
234
235 bool isEmpty = true;
236 for (auto it = bases_.begin(); isEmpty && it != bases_.end(); it++) {
237 if (!(*it)->Properties().empty() || !(*it)->CallSignatures().empty() ||
238 !(*it)->ConstructSignatures().empty() || (*it)->StringIndexInfo() || (*it)->NumberIndexInfo()) {
239 isEmpty = false;
240 }
241 }
242
243 if (isEmpty) {
244 return TypeFacts::EMPTY_OBJECT_FACTS;
245 }
246 }
247
248 return TypeFacts::OBJECT_FACTS;
249 }
250
251 } // namespace panda::es2panda::checker
252