• 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 "objectType.h"
17 
18 #include <typescript/checker.h>
19 
20 namespace panda::es2panda::checker {
21 
EachSignatureRelatedToSomeSignature(TypeRelation * relation,const ArenaVector<Signature * > & sourceSignatures,const ArenaVector<Signature * > & targetSignatures)22 bool ObjectType::EachSignatureRelatedToSomeSignature(TypeRelation *relation,
23                                                      const ArenaVector<Signature *> &sourceSignatures,
24                                                      const ArenaVector<Signature *> &targetSignatures)
25 {
26     ArenaVector<Signature *> targetCopy = targetSignatures;
27 
28     return std::all_of(sourceSignatures.begin(), sourceSignatures.end(), [relation, &targetCopy](Signature *source) {
29         return SignatureRelatedToSomeSignature(relation, source, &targetCopy);
30     });
31 }
32 
SignatureRelatedToSomeSignature(TypeRelation * relation,Signature * sourceSignature,ArenaVector<Signature * > * targetSignatures)33 bool ObjectType::SignatureRelatedToSomeSignature(TypeRelation *relation, Signature *sourceSignature,
34                                                  ArenaVector<Signature *> *targetSignatures)
35 {
36     for (auto it = targetSignatures->begin(); it != targetSignatures->end();) {
37         if (relation->IsIdenticalTo(sourceSignature, *it)) {
38             targetSignatures->erase(it);
39             return true;
40         }
41 
42         it++;
43     }
44 
45     return false;
46 }
47 
IsPropertiesIdentical(TypeRelation * relation,ObjectType * otherObj)48 bool ObjectType::IsPropertiesIdentical(TypeRelation *relation, ObjectType *otherObj)
49 {
50     for (auto *it : desc_->properties) {
51         binder::LocalVariable *found = otherObj->Desc()->FindProperty(it->Name());
52         if (!found) {
53             relation->Result(false);
54             return false;
55         }
56 
57         relation->IsIdenticalTo(it->TsType(), found->TsType());
58 
59         if (!relation->IsTrue()) {
60             return false;
61         }
62 
63         if (it->Flags() != found->Flags()) {
64             relation->Result(false);
65             return false;
66         }
67     }
68 
69     return true;
70 }
71 
IsIndexInfosIdentical(TypeRelation * relation,IndexInfo * descIndexInfo,IndexInfo * otherIndexInfo)72 bool ObjectType::IsIndexInfosIdentical(TypeRelation *relation, IndexInfo *descIndexInfo, IndexInfo *otherIndexInfo)
73 {
74     if (descIndexInfo) {
75         relation->IsIdenticalTo(descIndexInfo, otherIndexInfo);
76         if (!relation->IsTrue()) {
77             return false;
78         }
79     }
80 
81     return true;
82 }
83 
Identical(TypeRelation * relation,Type * other)84 void ObjectType::Identical(TypeRelation *relation, Type *other)
85 {
86     if (!other->IsObjectType() || kind_ != other->AsObjectType()->Kind()) {
87         return;
88     }
89 
90     ObjectType *otherObj = other->AsObjectType();
91     if (desc_->properties.size() != otherObj->Properties().size() ||
92         CallSignatures().size() != otherObj->CallSignatures().size() ||
93         ConstructSignatures().size() != otherObj->ConstructSignatures().size() ||
94         (desc_->numberIndexInfo && !otherObj->NumberIndexInfo()) ||
95         (!desc_->numberIndexInfo && otherObj->NumberIndexInfo()) ||
96         (desc_->stringIndexInfo && !otherObj->StringIndexInfo()) ||
97         (!desc_->stringIndexInfo && otherObj->StringIndexInfo())) {
98         relation->Result(false);
99         return;
100     }
101 
102     if (!IsPropertiesIdentical(relation, otherObj)) {
103         return;
104     }
105 
106     if (!EachSignatureRelatedToSomeSignature(relation, CallSignatures(), otherObj->CallSignatures()) ||
107         !EachSignatureRelatedToSomeSignature(relation, otherObj->CallSignatures(), CallSignatures())) {
108         return;
109     }
110 
111     if (!EachSignatureRelatedToSomeSignature(relation, ConstructSignatures(), otherObj->ConstructSignatures()) ||
112         !EachSignatureRelatedToSomeSignature(relation, otherObj->ConstructSignatures(), ConstructSignatures())) {
113         return;
114     }
115 
116     if (!IsIndexInfosIdentical(relation, desc_->numberIndexInfo, otherObj->NumberIndexInfo())||
117         !IsIndexInfosIdentical(relation, desc_->stringIndexInfo, otherObj->StringIndexInfo())) {
118         return;
119     }
120 }
121 
AssignProperties(TypeRelation * relation,ObjectType * source)122 void ObjectType::AssignProperties(TypeRelation *relation, ObjectType *source)
123 {
124     const ArenaVector<binder::LocalVariable *> &targetProperties = Properties();
125     IndexInfo *numberInfo = NumberIndexInfo();
126     IndexInfo *stringInfo = StringIndexInfo();
127 
128     for (auto *it : targetProperties) {
129         binder::LocalVariable *found = source->GetProperty(it->Name(), true);
130         Type *targetType = relation->GetChecker()->GetTypeOfVariable(it);
131 
132         if (found) {
133             Type *sourceType = relation->GetChecker()->GetTypeOfVariable(found);
134 
135             if (!relation->IsAssignableTo(sourceType, targetType)) {
136                 return;
137             }
138 
139             if (found->HasFlag(binder::VariableFlags::OPTIONAL) && !it->HasFlag(binder::VariableFlags::OPTIONAL)) {
140                 relation->Result(false);
141                 return;
142             }
143 
144             continue;
145         }
146 
147         if (numberInfo && it->HasFlag(binder::VariableFlags::NUMERIC_NAME) &&
148             !relation->IsAssignableTo(numberInfo->GetType(), targetType)) {
149             return;
150         }
151 
152         if (stringInfo && !relation->IsAssignableTo(stringInfo->GetType(), targetType)) {
153             return;
154         }
155 
156         if (!it->HasFlag(binder::VariableFlags::OPTIONAL)) {
157             relation->Result(false);
158             return;
159         }
160     }
161 }
162 
AssignSignatures(TypeRelation * relation,ObjectType * source,bool assignCallSignatures)163 void ObjectType::AssignSignatures(TypeRelation *relation, ObjectType *source, bool assignCallSignatures)
164 {
165     ArenaVector<Signature *> targetSignatures = assignCallSignatures ? CallSignatures() : ConstructSignatures();
166     ArenaVector<Signature *> sourceSignatures =
167         assignCallSignatures ? source->CallSignatures() : source->ConstructSignatures();
168 
169     for (auto *targetSignature : targetSignatures) {
170         bool foundCompatible = false;
171         for (auto *sourceSignature : sourceSignatures) {
172             targetSignature->AssignmentTarget(relation, sourceSignature);
173 
174             if (relation->IsTrue()) {
175                 foundCompatible = true;
176                 break;
177             }
178         }
179 
180         if (!foundCompatible) {
181             relation->Result(false);
182             return;
183         }
184     }
185 }
186 
AssignIndexInfo(TypeRelation * relation,ObjectType * source,bool assignNumberInfo)187 void ObjectType::AssignIndexInfo([[maybe_unused]] TypeRelation *relation, ObjectType *source, bool assignNumberInfo)
188 {
189     IndexInfo *targetInfo = assignNumberInfo ? NumberIndexInfo() : StringIndexInfo();
190     IndexInfo *sourceInfo = assignNumberInfo ? source->NumberIndexInfo() : source->StringIndexInfo();
191 
192     if (targetInfo) {
193         if (sourceInfo) {
194             targetInfo->AssignmentTarget(relation, sourceInfo);
195             return;
196         }
197 
198         for (auto *it : source->Properties()) {
199             if (assignNumberInfo && !it->HasFlag(binder::VariableFlags::NUMERIC_NAME)) {
200                 continue;
201             }
202 
203             if (!relation->IsAssignableTo(relation->GetChecker()->GetTypeOfVariable(it), targetInfo->GetType())) {
204                 return;
205             }
206         }
207     }
208 }
209 
checkExcessProperties(TypeRelation * relation,ObjectType * source)210 void ObjectType::checkExcessProperties(TypeRelation *relation, ObjectType *source)
211 {
212     for (auto *it : source->Properties()) {
213         auto *found = GetProperty(it->Name(), true);
214 
215         if (found || (it->HasFlag(binder::VariableFlags::NUMERIC_NAME) && NumberIndexInfo()) || StringIndexInfo()) {
216             continue;
217         }
218 
219         relation->Result(false);
220         return;
221     }
222 }
223 
AssignmentTarget(TypeRelation * relation,Type * source)224 void ObjectType::AssignmentTarget(TypeRelation *relation, Type *source)
225 {
226     if (!source->IsObjectType()) {
227         relation->Result(false);
228         return;
229     }
230 
231     relation->Result(true);
232 
233     ObjectType *sourceObj = source->AsObjectType();
234 
235     if (sourceObj->HasObjectFlag(ObjectFlags::CHECK_EXCESS_PROPS)) {
236         checkExcessProperties(relation, sourceObj);
237     }
238 
239     if (relation->IsTrue()) {
240         AssignProperties(relation, sourceObj);
241 
242         if (relation->IsTrue()) {
243             AssignSignatures(relation, sourceObj);
244 
245             if (relation->IsTrue()) {
246                 AssignSignatures(relation, sourceObj, false);
247 
248                 if (relation->IsTrue()) {
249                     AssignIndexInfo(relation, sourceObj);
250 
251                     if (relation->IsTrue()) {
252                         AssignIndexInfo(relation, sourceObj, false);
253                     }
254                 }
255             }
256         }
257     }
258 }
259 
260 }  // namespace panda::es2panda::checker
261