• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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