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