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