OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /// Functions for asserting equivalence across serialization. | 5 /// Functions for asserting equivalence across serialization. |
6 | 6 |
7 library dart2js.serialization.equivalence; | 7 library dart2js.serialization.equivalence; |
8 | 8 |
9 import '../common/resolution.dart'; | 9 import '../common/resolution.dart'; |
10 import '../constants/expressions.dart'; | 10 import '../constants/expressions.dart'; |
11 import '../dart_types.dart'; | 11 import '../dart_types.dart'; |
12 import '../elements/elements.dart'; | 12 import '../elements/elements.dart'; |
13 import '../elements/visitor.dart'; | 13 import '../elements/visitor.dart'; |
14 import '../universe/selector.dart'; | 14 import '../universe/selector.dart'; |
15 import '../universe/use.dart'; | 15 import '../universe/use.dart'; |
16 | 16 |
17 /// Equality based equivalence function. | 17 /// Equality based equivalence function. |
18 bool equality(a, b) => a == b; | 18 bool equality(a, b) => a == b; |
19 | 19 |
20 /// Returns `true` if the elements in [a] and [b] are pair-wise equivalent | 20 /// Returns `true` if the elements in [a] and [b] are pair-wise equivalent |
21 /// according to [elementEquivalence]. | 21 /// according to [elementEquivalence]. |
22 bool areListsEquivalent( | 22 bool areListsEquivalent(List a, List b, |
23 List a, | |
24 List b, | |
25 [bool elementEquivalence(a, b) = equality]) { | 23 [bool elementEquivalence(a, b) = equality]) { |
26 | |
27 if (a.length != b.length) return false; | 24 if (a.length != b.length) return false; |
28 for (int i = 0; i < a.length && i < b.length; i++) { | 25 for (int i = 0; i < a.length && i < b.length; i++) { |
29 if (!elementEquivalence(a[i], b[i])) { | 26 if (!elementEquivalence(a[i], b[i])) { |
30 return false; | 27 return false; |
31 } | 28 } |
32 } | 29 } |
33 return true; | 30 return true; |
34 } | 31 } |
35 | 32 |
36 /// Returns `true` if the elements in [a] and [b] are equivalent as sets using | 33 /// Returns `true` if the elements in [a] and [b] are equivalent as sets using |
37 /// [elementEquivalence] to determine element equivalence. | 34 /// [elementEquivalence] to determine element equivalence. |
38 bool areSetsEquivalent( | 35 bool areSetsEquivalent(Iterable set1, Iterable set2, |
39 Iterable set1, | |
40 Iterable set2, | |
41 [bool elementEquivalence(a, b) = equality]) { | 36 [bool elementEquivalence(a, b) = equality]) { |
42 Set remaining = set2.toSet(); | 37 Set remaining = set2.toSet(); |
43 for (var element1 in set1) { | 38 for (var element1 in set1) { |
44 bool found = false; | 39 bool found = false; |
45 for (var element2 in set2) { | 40 for (var element2 in set2) { |
46 if (elementEquivalence(element1, element2)) { | 41 if (elementEquivalence(element1, element2)) { |
47 found = true; | 42 found = true; |
48 remaining.remove(element2); | 43 remaining.remove(element2); |
49 break; | 44 break; |
50 } | 45 } |
(...skipping 30 matching lines...) Expand all Loading... |
81 bool areElementListsEquivalent(List<Element> a, List<Element> b) { | 76 bool areElementListsEquivalent(List<Element> a, List<Element> b) { |
82 return areListsEquivalent(a, b, areElementsEquivalent); | 77 return areListsEquivalent(a, b, areElementsEquivalent); |
83 } | 78 } |
84 | 79 |
85 /// Returns `true` if the lists of types, [a] and [b], are equivalent. | 80 /// Returns `true` if the lists of types, [a] and [b], are equivalent. |
86 bool areTypeListsEquivalent(List<DartType> a, List<DartType> b) { | 81 bool areTypeListsEquivalent(List<DartType> a, List<DartType> b) { |
87 return areListsEquivalent(a, b, areTypesEquivalent); | 82 return areListsEquivalent(a, b, areTypesEquivalent); |
88 } | 83 } |
89 | 84 |
90 /// Returns `true` if the lists of constants, [a] and [b], are equivalent. | 85 /// Returns `true` if the lists of constants, [a] and [b], are equivalent. |
91 bool areConstantListsEquivalent(List<ConstantExpression> a, | 86 bool areConstantListsEquivalent( |
92 List<ConstantExpression> b) { | 87 List<ConstantExpression> a, List<ConstantExpression> b) { |
93 return areListsEquivalent(a, b, areConstantsEquivalent); | 88 return areListsEquivalent(a, b, areConstantsEquivalent); |
94 } | 89 } |
95 | 90 |
96 /// Returns `true` if the selectors [a] and [b] are equivalent. | 91 /// Returns `true` if the selectors [a] and [b] are equivalent. |
97 bool areSelectorsEquivalent(Selector a, Selector b) { | 92 bool areSelectorsEquivalent(Selector a, Selector b) { |
98 return a.kind == b.kind && | 93 return a.kind == b.kind && |
99 a.callStructure == b.callStructure && | 94 a.callStructure == b.callStructure && |
100 areNamesEquivalent(a.memberName, b.memberName); | 95 areNamesEquivalent(a.memberName, b.memberName); |
101 } | 96 } |
102 | 97 |
103 /// Returns `true` if the names [a] and [b] are equivalent. | 98 /// Returns `true` if the names [a] and [b] are equivalent. |
104 bool areNamesEquivalent(Name a, Name b) { | 99 bool areNamesEquivalent(Name a, Name b) { |
105 return a.text == b.text && | 100 return a.text == b.text && |
106 a.isSetter == b.isSetter && | 101 a.isSetter == b.isSetter && |
107 areElementsEquivalent(a.library, b.library); | 102 areElementsEquivalent(a.library, b.library); |
108 } | 103 } |
109 | 104 |
110 /// Returns `true` if the dynamic uses [a] and [b] are equivalent. | 105 /// Returns `true` if the dynamic uses [a] and [b] are equivalent. |
111 bool areDynamicUsesEquivalent(DynamicUse a, DynamicUse b) { | 106 bool areDynamicUsesEquivalent(DynamicUse a, DynamicUse b) { |
112 return areSelectorsEquivalent(a.selector, b.selector); | 107 return areSelectorsEquivalent(a.selector, b.selector); |
113 } | 108 } |
114 | 109 |
115 /// Returns `true` if the static uses [a] and [b] are equivalent. | 110 /// Returns `true` if the static uses [a] and [b] are equivalent. |
116 bool areStaticUsesEquivalent(StaticUse a, StaticUse b) { | 111 bool areStaticUsesEquivalent(StaticUse a, StaticUse b) { |
117 return a.kind == b.kind && | 112 return a.kind == b.kind && areElementsEquivalent(a.element, b.element); |
118 areElementsEquivalent(a.element, b.element); | |
119 } | 113 } |
120 | 114 |
121 /// Returns `true` if the type uses [a] and [b] are equivalent. | 115 /// Returns `true` if the type uses [a] and [b] are equivalent. |
122 bool areTypeUsesEquivalent(TypeUse a, TypeUse b) { | 116 bool areTypeUsesEquivalent(TypeUse a, TypeUse b) { |
123 return a.kind == b.kind && | 117 return a.kind == b.kind && areTypesEquivalent(a.type, b.type); |
124 areTypesEquivalent(a.type, b.type); | |
125 } | 118 } |
126 | 119 |
127 /// Returns `true` if the list literal uses [a] and [b] are equivalent. | 120 /// Returns `true` if the list literal uses [a] and [b] are equivalent. |
128 bool areListLiteralUsesEquivalent(ListLiteralUse a, ListLiteralUse b) { | 121 bool areListLiteralUsesEquivalent(ListLiteralUse a, ListLiteralUse b) { |
129 return areTypesEquivalent(a.type, b.type) && | 122 return areTypesEquivalent(a.type, b.type) && |
130 a.isConstant == b.isConstant && | 123 a.isConstant == b.isConstant && |
131 a.isEmpty == b.isEmpty; | 124 a.isEmpty == b.isEmpty; |
132 } | 125 } |
133 | 126 |
134 /// Returns `true` if the map literal uses [a] and [b] are equivalent. | 127 /// Returns `true` if the map literal uses [a] and [b] are equivalent. |
135 bool areMapLiteralUsesEquivalent(MapLiteralUse a, MapLiteralUse b) { | 128 bool areMapLiteralUsesEquivalent(MapLiteralUse a, MapLiteralUse b) { |
136 return areTypesEquivalent(a.type, b.type) && | 129 return areTypesEquivalent(a.type, b.type) && |
137 a.isConstant == b.isConstant && | 130 a.isConstant == b.isConstant && |
138 a.isEmpty == b.isEmpty; | 131 a.isEmpty == b.isEmpty; |
139 } | 132 } |
140 | 133 |
141 /// Strategy for testing equivalence. | 134 /// Strategy for testing equivalence. |
142 /// | 135 /// |
143 /// Use this strategy to determine equivalence without failing on inequivalence. | 136 /// Use this strategy to determine equivalence without failing on inequivalence. |
144 class TestStrategy { | 137 class TestStrategy { |
145 const TestStrategy(); | 138 const TestStrategy(); |
146 | 139 |
147 bool test(var object1, var object2, String property, var value1, var value2) { | 140 bool test(var object1, var object2, String property, var value1, var value2) { |
148 return value1 == value2; | 141 return value1 == value2; |
149 } | 142 } |
150 | 143 |
151 bool testLists( | 144 bool testLists( |
152 Object object1, Object object2, String property, | 145 Object object1, Object object2, String property, List list1, List list2, |
153 List list1, List list2, | |
154 [bool elementEquivalence(a, b) = equality]) { | 146 [bool elementEquivalence(a, b) = equality]) { |
155 return areListsEquivalent(list1, list2, elementEquivalence); | 147 return areListsEquivalent(list1, list2, elementEquivalence); |
156 } | 148 } |
157 | 149 |
158 bool testSets( | 150 bool testSets( |
159 var object1, var object2, String property, | 151 var object1, var object2, String property, Iterable set1, Iterable set2, |
160 Iterable set1, Iterable set2, | |
161 [bool elementEquivalence(a, b) = equality]) { | 152 [bool elementEquivalence(a, b) = equality]) { |
162 return areSetsEquivalent(set1, set2, elementEquivalence); | 153 return areSetsEquivalent(set1, set2, elementEquivalence); |
163 } | 154 } |
164 | 155 |
165 bool testElements( | 156 bool testElements(Object object1, Object object2, String property, |
166 Object object1, Object object2, String property, | |
167 Element element1, Element element2) { | 157 Element element1, Element element2) { |
168 return areElementsEquivalent(element1, element2); | 158 return areElementsEquivalent(element1, element2); |
169 } | 159 } |
170 | 160 |
171 bool testTypes( | 161 bool testTypes(Object object1, Object object2, String property, |
172 Object object1, Object object2, String property, | |
173 DartType type1, DartType type2) { | 162 DartType type1, DartType type2) { |
174 return areTypesEquivalent(type1, type2); | 163 return areTypesEquivalent(type1, type2); |
175 } | 164 } |
176 | 165 |
177 bool testConstants( | 166 bool testConstants(Object object1, Object object2, String property, |
178 Object object1, Object object2, String property, | |
179 ConstantExpression exp1, ConstantExpression exp2) { | 167 ConstantExpression exp1, ConstantExpression exp2) { |
180 return areConstantsEquivalent(exp1, exp2); | 168 return areConstantsEquivalent(exp1, exp2); |
181 } | 169 } |
182 | 170 |
183 bool testTypeLists( | 171 bool testTypeLists(Object object1, Object object2, String property, |
184 Object object1, Object object2, String property, | |
185 List<DartType> list1, List<DartType> list2) { | 172 List<DartType> list1, List<DartType> list2) { |
186 return areTypeListsEquivalent(list1, list2); | 173 return areTypeListsEquivalent(list1, list2); |
187 } | 174 } |
188 | 175 |
189 bool testConstantLists( | 176 bool testConstantLists(Object object1, Object object2, String property, |
190 Object object1, Object object2, String property, | 177 List<ConstantExpression> list1, List<ConstantExpression> list2) { |
191 List<ConstantExpression> list1, | |
192 List<ConstantExpression> list2) { | |
193 return areConstantListsEquivalent(list1, list2); | 178 return areConstantListsEquivalent(list1, list2); |
194 } | 179 } |
195 | |
196 } | 180 } |
197 | 181 |
198 /// Visitor that checks for equivalence of [Element]s. | 182 /// Visitor that checks for equivalence of [Element]s. |
199 class ElementIdentityEquivalence extends BaseElementVisitor<bool, Element> { | 183 class ElementIdentityEquivalence extends BaseElementVisitor<bool, Element> { |
200 final TestStrategy strategy; | 184 final TestStrategy strategy; |
201 | 185 |
202 const ElementIdentityEquivalence([this.strategy = const TestStrategy()]); | 186 const ElementIdentityEquivalence([this.strategy = const TestStrategy()]); |
203 | 187 |
204 bool visit(Element element1, Element element2) { | 188 bool visit(Element element1, Element element2) { |
205 if (element1 == null && element2 == null) { | 189 if (element1 == null && element2 == null) { |
206 return true; | 190 return true; |
207 } else if (element1 == null || element2 == null) { | 191 } else if (element1 == null || element2 == null) { |
208 return false; | 192 return false; |
209 } | 193 } |
210 element1 = element1.declaration; | 194 element1 = element1.declaration; |
211 element2 = element2.declaration; | 195 element2 = element2.declaration; |
212 if (element1 == element2) { | 196 if (element1 == element2) { |
213 return true; | 197 return true; |
214 } | 198 } |
215 return | 199 return strategy.test( |
216 strategy.test( | 200 element1, element2, 'kind', element1.kind, element2.kind) && |
217 element1, element2, 'kind', | |
218 element1.kind, element2.kind) && | |
219 element1.accept(this, element2); | 201 element1.accept(this, element2); |
220 } | 202 } |
221 | 203 |
222 @override | 204 @override |
223 bool visitElement(Element e, Element arg) { | 205 bool visitElement(Element e, Element arg) { |
224 throw new UnsupportedError("Unsupported element $e"); | 206 throw new UnsupportedError("Unsupported element $e"); |
225 } | 207 } |
226 | 208 |
227 @override | 209 @override |
228 bool visitLibraryElement(LibraryElement element1, LibraryElement element2) { | 210 bool visitLibraryElement(LibraryElement element1, LibraryElement element2) { |
229 return | 211 return strategy.test(element1, element2, 'canonicalUri', |
230 strategy.test(element1, element2, | 212 element1.canonicalUri, element2.canonicalUri); |
231 'canonicalUri', | |
232 element1.canonicalUri, element2.canonicalUri); | |
233 } | 213 } |
234 | 214 |
235 @override | 215 @override |
236 bool visitCompilationUnitElement(CompilationUnitElement element1, | 216 bool visitCompilationUnitElement( |
237 CompilationUnitElement element2) { | 217 CompilationUnitElement element1, CompilationUnitElement element2) { |
238 return | 218 return strategy.test( |
239 strategy.test(element1, element2, | 219 element1, element2, 'name', element1.name, element2.name) && |
240 'name', | |
241 element1.name, element2.name) && | |
242 visit(element1.library, element2.library); | 220 visit(element1.library, element2.library); |
243 } | 221 } |
244 | 222 |
245 @override | 223 @override |
246 bool visitClassElement(ClassElement element1, ClassElement element2) { | 224 bool visitClassElement(ClassElement element1, ClassElement element2) { |
247 return | 225 return strategy.test( |
248 strategy.test(element1, element2, | 226 element1, element2, 'name', element1.name, element2.name) && |
249 'name', | |
250 element1.name, element2.name) && | |
251 visit(element1.library, element2.library); | 227 visit(element1.library, element2.library); |
252 } | 228 } |
253 | 229 |
254 bool checkMembers(Element element1, Element element2) { | 230 bool checkMembers(Element element1, Element element2) { |
255 if (!strategy.test(element1, element2, 'name', | 231 if (!strategy.test( |
256 element1.name, element2.name)) { | 232 element1, element2, 'name', element1.name, element2.name)) { |
257 return false; | 233 return false; |
258 } | 234 } |
259 if (element1.enclosingClass != null || element2.enclosingClass != null) { | 235 if (element1.enclosingClass != null || element2.enclosingClass != null) { |
260 return visit(element1.enclosingClass, element2.enclosingClass); | 236 return visit(element1.enclosingClass, element2.enclosingClass); |
261 } else { | 237 } else { |
262 return visit(element1.library, element2.library); | 238 return visit(element1.library, element2.library); |
263 } | 239 } |
264 } | 240 } |
265 | 241 |
266 @override | 242 @override |
267 bool visitFieldElement(FieldElement element1, FieldElement element2) { | 243 bool visitFieldElement(FieldElement element1, FieldElement element2) { |
268 return checkMembers(element1, element2); | 244 return checkMembers(element1, element2); |
269 } | 245 } |
270 | 246 |
271 @override | 247 @override |
272 bool visitConstructorElement(ConstructorElement element1, | 248 bool visitConstructorElement( |
273 ConstructorElement element2) { | 249 ConstructorElement element1, ConstructorElement element2) { |
274 return checkMembers(element1, element2); | 250 return checkMembers(element1, element2); |
275 } | 251 } |
276 | 252 |
277 @override | 253 @override |
278 bool visitMethodElement(MethodElement element1, | 254 bool visitMethodElement(MethodElement element1, MethodElement element2) { |
279 MethodElement element2) { | |
280 return checkMembers(element1, element2); | 255 return checkMembers(element1, element2); |
281 } | 256 } |
282 | 257 |
283 @override | 258 @override |
284 bool visitGetterElement(GetterElement element1, | 259 bool visitGetterElement(GetterElement element1, GetterElement element2) { |
285 GetterElement element2) { | |
286 return checkMembers(element1, element2); | 260 return checkMembers(element1, element2); |
287 } | 261 } |
288 | 262 |
289 @override | 263 @override |
290 bool visitSetterElement(SetterElement element1, | 264 bool visitSetterElement(SetterElement element1, SetterElement element2) { |
291 SetterElement element2) { | |
292 return checkMembers(element1, element2); | 265 return checkMembers(element1, element2); |
293 } | 266 } |
294 | 267 |
295 @override | 268 @override |
296 bool visitLocalFunctionElement(LocalFunctionElement element1, | 269 bool visitLocalFunctionElement( |
297 LocalFunctionElement element2) { | 270 LocalFunctionElement element1, LocalFunctionElement element2) { |
298 // TODO(johnniwinther): Define an equivalence on locals. | 271 // TODO(johnniwinther): Define an equivalence on locals. |
299 return checkMembers(element1.memberContext, element2.memberContext); | 272 return checkMembers(element1.memberContext, element2.memberContext); |
300 } | 273 } |
301 | 274 |
302 bool visitAbstractFieldElement(AbstractFieldElement element1, | 275 bool visitAbstractFieldElement( |
303 AbstractFieldElement element2) { | 276 AbstractFieldElement element1, AbstractFieldElement element2) { |
304 return checkMembers(element1, element2); | 277 return checkMembers(element1, element2); |
305 } | 278 } |
306 | 279 |
307 @override | 280 @override |
308 bool visitTypeVariableElement(TypeVariableElement element1, | 281 bool visitTypeVariableElement( |
309 TypeVariableElement element2) { | 282 TypeVariableElement element1, TypeVariableElement element2) { |
310 return | 283 return strategy.test( |
311 strategy.test( | 284 element1, element2, 'name', element1.name, element2.name) && |
312 element1, element2, 'name', | |
313 element1.name, element2.name) && | |
314 visit(element1.typeDeclaration, element2.typeDeclaration); | 285 visit(element1.typeDeclaration, element2.typeDeclaration); |
315 } | 286 } |
316 | 287 |
317 @override | 288 @override |
318 bool visitTypedefElement(TypedefElement element1, TypedefElement element2) { | 289 bool visitTypedefElement(TypedefElement element1, TypedefElement element2) { |
319 return | 290 return strategy.test( |
320 strategy.test( | 291 element1, element2, 'name', element1.name, element2.name) && |
321 element1, element2, 'name', | |
322 element1.name, element2.name) && | |
323 visit(element1.library, element2.library); | 292 visit(element1.library, element2.library); |
324 } | 293 } |
325 | 294 |
326 @override | 295 @override |
327 bool visitParameterElement(ParameterElement element1, | 296 bool visitParameterElement( |
328 ParameterElement element2) { | 297 ParameterElement element1, ParameterElement element2) { |
329 return | 298 return strategy.test( |
330 strategy.test( | 299 element1, element2, 'name', element1.name, element2.name) && |
331 element1, element2, 'name', | |
332 element1.name, element2.name) && | |
333 visit(element1.functionDeclaration, element2.functionDeclaration); | 300 visit(element1.functionDeclaration, element2.functionDeclaration); |
334 } | 301 } |
335 | 302 |
336 @override | 303 @override |
337 bool visitImportElement(ImportElement element1, ImportElement element2) { | 304 bool visitImportElement(ImportElement element1, ImportElement element2) { |
338 return | 305 return visit(element1.importedLibrary, element2.importedLibrary) && |
339 visit(element1.importedLibrary, element2.importedLibrary) && | |
340 visit(element1.library, element2.library); | 306 visit(element1.library, element2.library); |
341 } | 307 } |
342 | 308 |
343 @override | 309 @override |
344 bool visitExportElement(ExportElement element1, ExportElement element2) { | 310 bool visitExportElement(ExportElement element1, ExportElement element2) { |
345 return | 311 return visit(element1.exportedLibrary, element2.exportedLibrary) && |
346 visit(element1.exportedLibrary, element2.exportedLibrary) && | |
347 visit(element1.library, element2.library); | 312 visit(element1.library, element2.library); |
348 } | 313 } |
349 | 314 |
350 @override | 315 @override |
351 bool visitPrefixElement(PrefixElement element1, PrefixElement element2) { | 316 bool visitPrefixElement(PrefixElement element1, PrefixElement element2) { |
352 return | 317 return strategy.test( |
353 strategy.test( | 318 element1, element2, 'name', element1.name, element2.name) && |
354 element1, element2, 'name', | |
355 element1.name, element2.name) && | |
356 visit(element1.library, element2.library); | 319 visit(element1.library, element2.library); |
357 } | 320 } |
358 } | 321 } |
359 | 322 |
360 | |
361 /// Visitor that checks for equivalence of [DartType]s. | 323 /// Visitor that checks for equivalence of [DartType]s. |
362 class TypeEquivalence implements DartTypeVisitor<bool, DartType> { | 324 class TypeEquivalence implements DartTypeVisitor<bool, DartType> { |
363 final TestStrategy strategy; | 325 final TestStrategy strategy; |
364 | 326 |
365 const TypeEquivalence([this.strategy = const TestStrategy()]); | 327 const TypeEquivalence([this.strategy = const TestStrategy()]); |
366 | 328 |
367 bool visit(DartType type1, DartType type2) { | 329 bool visit(DartType type1, DartType type2) { |
368 return | 330 return strategy.test(type1, type2, 'kind', type1.kind, type2.kind) && |
369 strategy.test(type1, type2, 'kind', type1.kind, type2.kind) && | |
370 type1.accept(this, type2); | 331 type1.accept(this, type2); |
371 } | 332 } |
372 | 333 |
373 @override | 334 @override |
374 bool visitDynamicType(DynamicType type, DynamicType other) => true; | 335 bool visitDynamicType(DynamicType type, DynamicType other) => true; |
375 | 336 |
376 @override | 337 @override |
377 bool visitFunctionType(FunctionType type, FunctionType other) { | 338 bool visitFunctionType(FunctionType type, FunctionType other) { |
378 return | 339 return strategy.testTypeLists(type, other, 'parameterTypes', |
379 strategy.testTypeLists( | |
380 type, other, 'parameterTypes', | |
381 type.parameterTypes, other.parameterTypes) && | 340 type.parameterTypes, other.parameterTypes) && |
382 strategy.testTypeLists( | 341 strategy.testTypeLists(type, other, 'optionalParameterTypes', |
383 type, other, 'optionalParameterTypes', | |
384 type.optionalParameterTypes, other.optionalParameterTypes) && | 342 type.optionalParameterTypes, other.optionalParameterTypes) && |
385 strategy.testTypeLists( | 343 strategy.testTypeLists(type, other, 'namedParameterTypes', |
386 type, other, 'namedParameterTypes', | |
387 type.namedParameterTypes, other.namedParameterTypes) && | 344 type.namedParameterTypes, other.namedParameterTypes) && |
388 strategy.testLists( | 345 strategy.testLists(type, other, 'namedParameters', type.namedParameters, |
389 type, other, 'namedParameters', | 346 other.namedParameters); |
390 type.namedParameters, other.namedParameters); | |
391 } | 347 } |
392 | 348 |
393 bool visitGenericType(GenericType type, GenericType other) { | 349 bool visitGenericType(GenericType type, GenericType other) { |
394 return | 350 return strategy.testElements( |
395 strategy.testElements( | 351 type, other, 'element', type.element, other.element) && |
396 type, other, 'element', | 352 strategy.testTypeLists(type, other, 'typeArguments', type.typeArguments, |
397 type.element, other.element) && | 353 other.typeArguments); |
398 strategy.testTypeLists( | |
399 type, other, 'typeArguments', | |
400 type.typeArguments, other.typeArguments); | |
401 } | 354 } |
402 | 355 |
403 @override | 356 @override |
404 bool visitMalformedType(MalformedType type, MalformedType other) => true; | 357 bool visitMalformedType(MalformedType type, MalformedType other) => true; |
405 | 358 |
406 @override | 359 @override |
407 bool visitStatementType(StatementType type, StatementType other) { | 360 bool visitStatementType(StatementType type, StatementType other) { |
408 throw new UnsupportedError("Unsupported type: $type"); | 361 throw new UnsupportedError("Unsupported type: $type"); |
409 } | 362 } |
410 | 363 |
411 @override | 364 @override |
412 bool visitTypeVariableType(TypeVariableType type, TypeVariableType other) { | 365 bool visitTypeVariableType(TypeVariableType type, TypeVariableType other) { |
413 return | 366 return strategy.testElements( |
414 strategy.testElements( | 367 type, other, 'element', type.element, other.element); |
415 type, other, 'element', | |
416 type.element, other.element); | |
417 } | 368 } |
418 | 369 |
419 @override | 370 @override |
420 bool visitVoidType(VoidType type, VoidType argument) => true; | 371 bool visitVoidType(VoidType type, VoidType argument) => true; |
421 | 372 |
422 @override | 373 @override |
423 bool visitInterfaceType(InterfaceType type, InterfaceType other) { | 374 bool visitInterfaceType(InterfaceType type, InterfaceType other) { |
424 return visitGenericType(type, other); | 375 return visitGenericType(type, other); |
425 } | 376 } |
426 | 377 |
427 @override | 378 @override |
428 bool visitTypedefType(TypedefType type, TypedefType other) { | 379 bool visitTypedefType(TypedefType type, TypedefType other) { |
429 return visitGenericType(type, other); | 380 return visitGenericType(type, other); |
430 } | 381 } |
431 } | 382 } |
432 | 383 |
433 /// Visitor that checks for structural equivalence of [ConstantExpression]s. | 384 /// Visitor that checks for structural equivalence of [ConstantExpression]s. |
434 class ConstantEquivalence | 385 class ConstantEquivalence |
435 implements ConstantExpressionVisitor<bool, ConstantExpression> { | 386 implements ConstantExpressionVisitor<bool, ConstantExpression> { |
436 final TestStrategy strategy; | 387 final TestStrategy strategy; |
437 | 388 |
438 const ConstantEquivalence([this.strategy = const TestStrategy()]); | 389 const ConstantEquivalence([this.strategy = const TestStrategy()]); |
439 | 390 |
440 @override | 391 @override |
441 bool visit(ConstantExpression exp1, ConstantExpression exp2) { | 392 bool visit(ConstantExpression exp1, ConstantExpression exp2) { |
442 if (identical(exp1, exp2)) return true; | 393 if (identical(exp1, exp2)) return true; |
443 return | 394 return strategy.test(exp1, exp2, 'kind', exp1.kind, exp2.kind) && |
444 strategy.test(exp1, exp2, 'kind', exp1.kind, exp2.kind) && | |
445 exp1.accept(this, exp2); | 395 exp1.accept(this, exp2); |
446 } | 396 } |
447 | 397 |
448 @override | 398 @override |
449 bool visitBinary(BinaryConstantExpression exp1, | 399 bool visitBinary( |
450 BinaryConstantExpression exp2) { | 400 BinaryConstantExpression exp1, BinaryConstantExpression exp2) { |
451 return | 401 return strategy.test( |
452 strategy.test(exp1, exp2, 'operator', exp1.operator, exp2.operator) && | 402 exp1, exp2, 'operator', exp1.operator, exp2.operator) && |
453 strategy.testConstants(exp1, exp2, 'left', exp1.left, exp2.left) && | 403 strategy.testConstants(exp1, exp2, 'left', exp1.left, exp2.left) && |
454 strategy.testConstants(exp1, exp2, 'right', exp1.right, exp2.right); | 404 strategy.testConstants(exp1, exp2, 'right', exp1.right, exp2.right); |
455 } | 405 } |
456 | 406 |
457 @override | 407 @override |
458 bool visitConcatenate(ConcatenateConstantExpression exp1, | 408 bool visitConcatenate( |
459 ConcatenateConstantExpression exp2) { | 409 ConcatenateConstantExpression exp1, ConcatenateConstantExpression exp2) { |
460 return | 410 return strategy.testConstantLists( |
461 strategy.testConstantLists( | 411 exp1, exp2, 'expressions', exp1.expressions, exp2.expressions); |
462 exp1, exp2, 'expressions', | |
463 exp1.expressions, exp2.expressions); | |
464 } | 412 } |
465 | 413 |
466 @override | 414 @override |
467 bool visitConditional(ConditionalConstantExpression exp1, | 415 bool visitConditional( |
468 ConditionalConstantExpression exp2) { | 416 ConditionalConstantExpression exp1, ConditionalConstantExpression exp2) { |
469 return | 417 return strategy.testConstants( |
470 strategy.testConstants( | |
471 exp1, exp2, 'condition', exp1.condition, exp2.condition) && | 418 exp1, exp2, 'condition', exp1.condition, exp2.condition) && |
472 strategy.testConstants( | 419 strategy.testConstants( |
473 exp1, exp2, 'trueExp', exp1.trueExp, exp2.trueExp) && | 420 exp1, exp2, 'trueExp', exp1.trueExp, exp2.trueExp) && |
474 strategy.testConstants( | 421 strategy.testConstants( |
475 exp1, exp2, 'falseExp', exp1.falseExp, exp2.falseExp); | 422 exp1, exp2, 'falseExp', exp1.falseExp, exp2.falseExp); |
476 } | 423 } |
477 | 424 |
478 @override | 425 @override |
479 bool visitConstructed(ConstructedConstantExpression exp1, | 426 bool visitConstructed( |
480 ConstructedConstantExpression exp2) { | 427 ConstructedConstantExpression exp1, ConstructedConstantExpression exp2) { |
481 return | 428 return strategy.testTypes(exp1, exp2, 'type', exp1.type, exp2.type) && |
482 strategy.testTypes( | 429 strategy.testElements(exp1, exp2, 'target', exp1.target, exp2.target) && |
483 exp1, exp2, 'type', | |
484 exp1.type, exp2.type) && | |
485 strategy.testElements( | |
486 exp1, exp2, 'target', | |
487 exp1.target, exp2.target) && | |
488 strategy.testConstantLists( | 430 strategy.testConstantLists( |
489 exp1, exp2, 'arguments', | 431 exp1, exp2, 'arguments', exp1.arguments, exp2.arguments) && |
490 exp1.arguments, exp2.arguments) && | 432 strategy.test(exp1, exp2, 'callStructure', exp1.callStructure, |
491 strategy.test(exp1, exp2, 'callStructure', | 433 exp2.callStructure); |
492 exp1.callStructure, exp2.callStructure); | |
493 } | 434 } |
494 | 435 |
495 @override | 436 @override |
496 bool visitFunction(FunctionConstantExpression exp1, | 437 bool visitFunction( |
497 FunctionConstantExpression exp2) { | 438 FunctionConstantExpression exp1, FunctionConstantExpression exp2) { |
498 return | 439 return strategy.testElements( |
499 strategy.testElements( | 440 exp1, exp2, 'element', exp1.element, exp2.element); |
500 exp1, exp2, 'element', | |
501 exp1.element, exp2.element); | |
502 } | 441 } |
503 | 442 |
504 @override | 443 @override |
505 bool visitIdentical(IdenticalConstantExpression exp1, | 444 bool visitIdentical( |
506 IdenticalConstantExpression exp2) { | 445 IdenticalConstantExpression exp1, IdenticalConstantExpression exp2) { |
507 return | 446 return strategy.testConstants(exp1, exp2, 'left', exp1.left, exp2.left) && |
508 strategy.testConstants(exp1, exp2, 'left', exp1.left, exp2.left) && | |
509 strategy.testConstants(exp1, exp2, 'right', exp1.right, exp2.right); | 447 strategy.testConstants(exp1, exp2, 'right', exp1.right, exp2.right); |
510 } | 448 } |
511 | 449 |
512 @override | 450 @override |
513 bool visitList(ListConstantExpression exp1, ListConstantExpression exp2) { | 451 bool visitList(ListConstantExpression exp1, ListConstantExpression exp2) { |
514 return | 452 return strategy.testTypes(exp1, exp2, 'type', exp1.type, exp2.type) && |
515 strategy.testTypes( | |
516 exp1, exp2, 'type', | |
517 exp1.type, exp2.type) && | |
518 strategy.testConstantLists( | 453 strategy.testConstantLists( |
519 exp1, exp2, 'values', | 454 exp1, exp2, 'values', exp1.values, exp2.values); |
520 exp1.values, exp2.values); | |
521 } | 455 } |
522 | 456 |
523 @override | 457 @override |
524 bool visitMap(MapConstantExpression exp1, MapConstantExpression exp2) { | 458 bool visitMap(MapConstantExpression exp1, MapConstantExpression exp2) { |
525 return | 459 return strategy.testTypes(exp1, exp2, 'type', exp1.type, exp2.type) && |
526 strategy.testTypes( | 460 strategy.testConstantLists(exp1, exp2, 'keys', exp1.keys, exp2.keys) && |
527 exp1, exp2, 'type', | |
528 exp1.type, exp2.type) && | |
529 strategy.testConstantLists( | 461 strategy.testConstantLists( |
530 exp1, exp2, 'keys', | 462 exp1, exp2, 'values', exp1.values, exp2.values); |
531 exp1.keys, exp2.keys) && | |
532 strategy.testConstantLists( | |
533 exp1, exp2, 'values', | |
534 exp1.values, exp2.values); | |
535 } | 463 } |
536 | 464 |
537 @override | 465 @override |
538 bool visitNamed(NamedArgumentReference exp1, NamedArgumentReference exp2) { | 466 bool visitNamed(NamedArgumentReference exp1, NamedArgumentReference exp2) { |
539 return strategy.test(exp1, exp2, 'name', exp1.name, exp2.name); | 467 return strategy.test(exp1, exp2, 'name', exp1.name, exp2.name); |
540 } | 468 } |
541 | 469 |
542 @override | 470 @override |
543 bool visitPositional(PositionalArgumentReference exp1, | 471 bool visitPositional( |
544 PositionalArgumentReference exp2) { | 472 PositionalArgumentReference exp1, PositionalArgumentReference exp2) { |
545 return strategy.test(exp1, exp2, 'index', exp1.index, exp2.index); | 473 return strategy.test(exp1, exp2, 'index', exp1.index, exp2.index); |
546 } | 474 } |
547 | 475 |
548 @override | 476 @override |
549 bool visitSymbol(SymbolConstantExpression exp1, | 477 bool visitSymbol( |
550 SymbolConstantExpression exp2) { | 478 SymbolConstantExpression exp1, SymbolConstantExpression exp2) { |
551 // TODO: implement visitSymbol | 479 // TODO: implement visitSymbol |
552 return true; | 480 return true; |
553 } | 481 } |
554 | 482 |
555 @override | 483 @override |
556 bool visitType(TypeConstantExpression exp1, TypeConstantExpression exp2) { | 484 bool visitType(TypeConstantExpression exp1, TypeConstantExpression exp2) { |
557 return strategy.testTypes(exp1, exp2, 'type', exp1.type, exp2.type); | 485 return strategy.testTypes(exp1, exp2, 'type', exp1.type, exp2.type); |
558 } | 486 } |
559 | 487 |
560 @override | 488 @override |
561 bool visitUnary(UnaryConstantExpression exp1, UnaryConstantExpression exp2) { | 489 bool visitUnary(UnaryConstantExpression exp1, UnaryConstantExpression exp2) { |
562 return | 490 return strategy.test( |
563 strategy.test(exp1, exp2, 'operator', exp1.operator, exp2.operator) && | 491 exp1, exp2, 'operator', exp1.operator, exp2.operator) && |
564 strategy.testConstants( | 492 strategy.testConstants( |
565 exp1, exp2, 'expression', exp1.expression, exp2.expression); | 493 exp1, exp2, 'expression', exp1.expression, exp2.expression); |
566 } | 494 } |
567 | 495 |
568 @override | 496 @override |
569 bool visitVariable(VariableConstantExpression exp1, | 497 bool visitVariable( |
570 VariableConstantExpression exp2) { | 498 VariableConstantExpression exp1, VariableConstantExpression exp2) { |
571 return | 499 return strategy.testElements( |
572 strategy.testElements( | 500 exp1, exp2, 'element', exp1.element, exp2.element); |
573 exp1, exp2, 'element', | |
574 exp1.element, exp2.element); | |
575 } | 501 } |
576 | 502 |
577 @override | 503 @override |
578 bool visitBool(BoolConstantExpression exp1, BoolConstantExpression exp2) { | 504 bool visitBool(BoolConstantExpression exp1, BoolConstantExpression exp2) { |
579 return | 505 return strategy.test( |
580 strategy.test( | 506 exp1, exp2, 'primitiveValue', exp1.primitiveValue, exp2.primitiveValue); |
581 exp1, exp2, 'primitiveValue', | |
582 exp1.primitiveValue, exp2.primitiveValue); | |
583 } | 507 } |
584 | 508 |
585 @override | 509 @override |
586 bool visitDouble(DoubleConstantExpression exp1, | 510 bool visitDouble( |
587 DoubleConstantExpression exp2) { | 511 DoubleConstantExpression exp1, DoubleConstantExpression exp2) { |
588 return | 512 return strategy.test( |
589 strategy.test( | 513 exp1, exp2, 'primitiveValue', exp1.primitiveValue, exp2.primitiveValue); |
590 exp1, exp2, 'primitiveValue', | |
591 exp1.primitiveValue, exp2.primitiveValue); | |
592 } | 514 } |
593 | 515 |
594 @override | 516 @override |
595 bool visitInt(IntConstantExpression exp1, IntConstantExpression exp2) { | 517 bool visitInt(IntConstantExpression exp1, IntConstantExpression exp2) { |
596 return | 518 return strategy.test( |
597 strategy.test( | 519 exp1, exp2, 'primitiveValue', exp1.primitiveValue, exp2.primitiveValue); |
598 exp1, exp2, 'primitiveValue', | |
599 exp1.primitiveValue, exp2.primitiveValue); | |
600 } | 520 } |
601 | 521 |
602 @override | 522 @override |
603 bool visitNull(NullConstantExpression exp1, NullConstantExpression exp2) { | 523 bool visitNull(NullConstantExpression exp1, NullConstantExpression exp2) { |
604 return true; | 524 return true; |
605 } | 525 } |
606 | 526 |
607 @override | 527 @override |
608 bool visitString(StringConstantExpression exp1, | 528 bool visitString( |
609 StringConstantExpression exp2) { | 529 StringConstantExpression exp1, StringConstantExpression exp2) { |
610 return | 530 return strategy.test( |
611 strategy.test( | 531 exp1, exp2, 'primitiveValue', exp1.primitiveValue, exp2.primitiveValue); |
612 exp1, exp2, 'primitiveValue', | |
613 exp1.primitiveValue, exp2.primitiveValue); | |
614 } | 532 } |
615 | 533 |
616 @override | 534 @override |
617 bool visitBoolFromEnvironment(BoolFromEnvironmentConstantExpression exp1, | 535 bool visitBoolFromEnvironment(BoolFromEnvironmentConstantExpression exp1, |
618 BoolFromEnvironmentConstantExpression exp2) { | 536 BoolFromEnvironmentConstantExpression exp2) { |
619 return | 537 return strategy.testConstants(exp1, exp2, 'name', exp1.name, exp2.name) && |
620 strategy.testConstants(exp1, exp2, 'name', exp1.name, exp2.name) && | |
621 strategy.testConstants( | 538 strategy.testConstants( |
622 exp1, exp2, 'defaultValue', | 539 exp1, exp2, 'defaultValue', exp1.defaultValue, exp2.defaultValue); |
623 exp1.defaultValue, exp2.defaultValue); | |
624 } | 540 } |
625 | 541 |
626 @override | 542 @override |
627 bool visitIntFromEnvironment(IntFromEnvironmentConstantExpression exp1, | 543 bool visitIntFromEnvironment(IntFromEnvironmentConstantExpression exp1, |
628 IntFromEnvironmentConstantExpression exp2) { | 544 IntFromEnvironmentConstantExpression exp2) { |
629 return | 545 return strategy.testConstants(exp1, exp2, 'name', exp1.name, exp2.name) && |
630 strategy.testConstants(exp1, exp2, 'name', exp1.name, exp2.name) && | |
631 strategy.testConstants( | 546 strategy.testConstants( |
632 exp1, exp2, 'defaultValue', | 547 exp1, exp2, 'defaultValue', exp1.defaultValue, exp2.defaultValue); |
633 exp1.defaultValue, exp2.defaultValue); | |
634 } | 548 } |
635 | 549 |
636 @override | 550 @override |
637 bool visitStringFromEnvironment( | 551 bool visitStringFromEnvironment(StringFromEnvironmentConstantExpression exp1, |
638 StringFromEnvironmentConstantExpression exp1, | |
639 StringFromEnvironmentConstantExpression exp2) { | 552 StringFromEnvironmentConstantExpression exp2) { |
640 return | 553 return strategy.testConstants(exp1, exp2, 'name', exp1.name, exp2.name) && |
641 strategy.testConstants(exp1, exp2, 'name', exp1.name, exp2.name) && | |
642 strategy.testConstants( | 554 strategy.testConstants( |
643 exp1, exp2, 'defaultValue', | 555 exp1, exp2, 'defaultValue', exp1.defaultValue, exp2.defaultValue); |
644 exp1.defaultValue, exp2.defaultValue); | |
645 } | 556 } |
646 | 557 |
647 @override | 558 @override |
648 bool visitStringLength(StringLengthConstantExpression exp1, | 559 bool visitStringLength(StringLengthConstantExpression exp1, |
649 StringLengthConstantExpression exp2) { | 560 StringLengthConstantExpression exp2) { |
650 return | 561 return strategy.testConstants( |
651 strategy.testConstants( | 562 exp1, exp2, 'expression', exp1.expression, exp2.expression); |
652 exp1, exp2, 'expression', | |
653 exp1.expression, exp2.expression); | |
654 } | 563 } |
655 | 564 |
656 @override | 565 @override |
657 bool visitDeferred(DeferredConstantExpression exp1, | 566 bool visitDeferred( |
658 DeferredConstantExpression exp2) { | 567 DeferredConstantExpression exp1, DeferredConstantExpression exp2) { |
659 // TODO: implement visitDeferred | 568 // TODO: implement visitDeferred |
660 return true; | 569 return true; |
661 } | 570 } |
662 } | 571 } |
663 | 572 |
664 /// Tests the equivalence of [impact1] and [impact2] using [strategy]. | 573 /// Tests the equivalence of [impact1] and [impact2] using [strategy]. |
665 bool testResolutionImpactEquivalence( | 574 bool testResolutionImpactEquivalence( |
666 ResolutionImpact impact1, | 575 ResolutionImpact impact1, ResolutionImpact impact2, |
667 ResolutionImpact impact2, | |
668 [TestStrategy strategy = const TestStrategy()]) { | 576 [TestStrategy strategy = const TestStrategy()]) { |
669 return | 577 return strategy.testSets(impact1, impact2, 'constSymbolNames', |
670 strategy.testSets( | |
671 impact1, impact2, 'constSymbolNames', | |
672 impact1.constSymbolNames, impact2.constSymbolNames) && | 578 impact1.constSymbolNames, impact2.constSymbolNames) && |
673 strategy.testSets( | 579 strategy.testSets( |
674 impact1, impact2, 'constantLiterals', | 580 impact1, |
675 impact1.constantLiterals, impact2.constantLiterals, | 581 impact2, |
| 582 'constantLiterals', |
| 583 impact1.constantLiterals, |
| 584 impact2.constantLiterals, |
676 areConstantsEquivalent) && | 585 areConstantsEquivalent) && |
| 586 strategy.testSets(impact1, impact2, 'dynamicUses', impact1.dynamicUses, |
| 587 impact2.dynamicUses, areDynamicUsesEquivalent) && |
677 strategy.testSets( | 588 strategy.testSets( |
678 impact1, impact2, 'dynamicUses', | 589 impact1, impact2, 'features', impact1.features, impact2.features) && |
679 impact1.dynamicUses, impact2.dynamicUses, | 590 strategy.testSets(impact1, impact2, 'listLiterals', impact1.listLiterals, |
680 areDynamicUsesEquivalent) && | 591 impact2.listLiterals, areListLiteralUsesEquivalent) && |
681 strategy.testSets( | 592 strategy.testSets(impact1, impact2, 'mapLiterals', impact1.mapLiterals, |
682 impact1, impact2, 'features', | 593 impact2.mapLiterals, areMapLiteralUsesEquivalent) && |
683 impact1.features, impact2.features) && | 594 strategy.testSets(impact1, impact2, 'staticUses', impact1.staticUses, |
684 strategy.testSets( | 595 impact2.staticUses, areStaticUsesEquivalent) && |
685 impact1, impact2, 'listLiterals', | 596 strategy.testSets(impact1, impact2, 'typeUses', impact1.typeUses, |
686 impact1.listLiterals, impact2.listLiterals, | 597 impact2.typeUses, areTypeUsesEquivalent); |
687 areListLiteralUsesEquivalent) && | |
688 strategy.testSets( | |
689 impact1, impact2, 'mapLiterals', | |
690 impact1.mapLiterals, impact2.mapLiterals, | |
691 areMapLiteralUsesEquivalent) && | |
692 strategy.testSets( | |
693 impact1, impact2, 'staticUses', | |
694 impact1.staticUses, impact2.staticUses, | |
695 areStaticUsesEquivalent) && | |
696 strategy.testSets( | |
697 impact1, impact2, 'typeUses', | |
698 impact1.typeUses, impact2.typeUses, | |
699 areTypeUsesEquivalent); | |
700 } | 598 } |
OLD | NEW |