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