Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: tests/compiler/dart2js/serialization_test.dart

Issue 1192103002: Support serialization of the compiler backbone. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2015, 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 library dart2js.serialization_test;
6
7 import 'dart:io';
8 import 'memory_compiler.dart';
9 import 'package:async_helper/async_helper.dart';
10 import 'package:compiler/src/constants/expressions.dart';
11 import 'package:compiler/src/dart_types.dart';
12 import 'package:compiler/src/dart2jslib.dart';
13 import 'package:compiler/src/elements/elements.dart';
14 import 'package:compiler/src/elements/visitor.dart';
15 import 'package:compiler/src/ordered_typeset.dart';
16 import 'package:compiler/src/serialization/serialization.dart';
17 import 'package:compiler/src/serialization/json_serializer.dart';
18 import 'package:compiler/src/tree/tree.dart';
19
20 main(List<String> arguments) {
21 // Ensure that we can print out constant expressions.
22 DEBUG_MODE = true;
23
24 Uri entryPoint;
25 String outPath;
26 bool prettyPrint = false;
27 for (String arg in arguments) {
28 if (arg.startsWith('--')) {
29 if (arg.startsWith('--out=')) {
30 outPath = arg.substring('--out='.length);
31 } else if (arg == '--pretty-print') {
32 prettyPrint = true;
33 } else {
34 print("Unknown option $arg");
35 }
36 } else {
37 if (entryPoint != null) {
38 print("Multiple entrypoints is not supported.");
39 }
40 entryPoint = Uri.parse(arg);
41 }
42 }
43 if (entryPoint == null) {
44 entryPoint = Uri.parse('dart:core');
45 }
46 Compiler compiler = compilerFor({}, options: ['--analyze-all']);
47 asyncTest(() async {
48 await compiler.runCompiler(entryPoint);
49 testSerialization(compiler.libraryLoader.libraries,
50 outPath: outPath,
51 prettyPrint: prettyPrint);
52 });
53 }
54
55 void testSerialization(Iterable<LibraryElement> libraries1,
56 {String outPath,
57 bool prettyPrint}) {
58 Serializer serializer = new Serializer(const JsonSerializationEncoder());
59 for (LibraryElement library1 in libraries1) {
60 serializer.serialize(library1);
61 }
62 String text = serializer.toText();
63 String outText = text;
64 if (prettyPrint) {
65 outText = serializer.prettyPrint();
66 }
67 if (outPath != null) {
68 new File(outPath).writeAsStringSync(outText);
69 } else if (prettyPrint) {
70 print(outText);
71 }
72
73 Deserializer deserializer = new Deserializer.fromText(
74 text, const JsonSerializationDecoder());
75 List<LibraryElement> libraries2 = <LibraryElement>[];
76 for (LibraryElement library1 in libraries1) {
77 LibraryElement library2 =
78 deserializer.lookupLibrary(library1.canonicalUri);
79 if (library2 == null) {
80 throw new ArgumentError('No library ${library1.canonicalUri} found.');
81 }
82 checkLibraryContent('library1', 'library2', 'library', library1, library2);
83 libraries2.add(library2);
84 }
85
86 Serializer serializer2 = new Serializer(const JsonSerializationEncoder());
87 for (LibraryElement library2 in libraries2) {
88 serializer2.serialize(library2);
89 }
90 String text2 = serializer2.toText();
91
92 Deserializer deserializer3 = new Deserializer.fromText(
93 text2, const JsonSerializationDecoder());
94 for (LibraryElement library1 in libraries1) {
95 LibraryElement library2 =
96 deserializer.lookupLibrary(library1.canonicalUri);
97 if (library2 == null) {
98 throw new ArgumentError('No library ${library1.canonicalUri} found.');
99 }
100 LibraryElement library3 =
101 deserializer3.lookupLibrary(library1.canonicalUri);
102 if (library3 == null) {
103 throw new ArgumentError('No library ${library1.canonicalUri} found.');
104 }
105 checkLibraryContent('library1', 'library3', 'library', library1, library3);
106 checkLibraryContent('library2', 'library3', 'library', library2, library3);
107 }
108 }
109
110 /// Check the equivalence of [library1] and [library2] and their content.
111 ///
112 /// Uses [object1], [object2] and [property] to provide context for failures.
113 checkLibraryContent(
114 Object object1, object2, String property,
115 LibraryElement library1, LibraryElement library2) {
116 checkElementProperties(object1, object2, property, library1, library2);
117 }
118
119 /// Check the equivalence of [element1] and [element2] and their properties.
120 ///
121 /// Uses [object1], [object2] and [property] to provide context for failures.
122 checkElementProperties(
123 Object object1, object2, String property,
124 Element element1, Element element2) {
125 const ElementPropertyEquivalence().visit(element1, element2);
126 }
127
128 /// Check the equivalence of the two lists of elements, [list1] and [list2].
129 ///
130 /// Uses [object1], [object2] and [property] to provide context for failures.
131 checkElementLists(Object object1, Object object2, String property,
132 Iterable<Element> list1, Iterable<Element> list2) {
133 checkListEquivalence(object1, object2, property,
134 list1, list2, checkElementProperties);
135 }
136
137 /// Check equivalence of the two lists, [list1] and [list2], using
138 /// [checkEquivalence] to check the pair-wise equivalence.
139 ///
140 /// Uses [object1], [object2] and [property] to provide context for failures.
141 void checkListEquivalence(
142 Object object1, Object object2, String property,
143 Iterable list1, Iterable list2,
144 void checkEquivalence(o1, o2, property, a, b)) {
145 for (int i = 0; i < list1.length && i < list2.length; i++) {
146 checkEquivalence(
147 object1, object2, property,
148 list1.elementAt(i), list2.elementAt(i));
149 }
150 for (int i = list1.length; i < list2.length; i++) {
151 throw
152 'Missing equivalent for element '
153 '#$i ${list2.elementAt(i)} in `${property}` on $object2.\n'
154 '`${property}` on $object1:\n ${list1.join('\n ')}\n'
155 '`${property}` on $object2:\n ${list2.join('\n ')}';
156 }
157 for (int i = list2.length; i < list1.length; i++) {
158 throw
159 'Missing equivalent for element '
160 '#$i ${list1.elementAt(i)} in `${property}` on $object1.\n'
161 '`${property}` on $object1:\n ${list1.join('\n ')}\n'
162 '`${property}` on $object2:\n ${list2.join('\n ')}';
163 }
164 }
165
166 /// Checks the equivalence of the identity (but not properties) of [element1]
167 /// and [element2].
168 ///
169 /// Uses [object1], [object2] and [property] to provide context for failures.
170 void checkElementIdentities(
171 Object object1, Object object2, String property,
172 Element element1, Element element2) {
173 if (identical(element1, element2)) return;
174 if (element1 == null || element2 == null) {
175 check(object1, object2, property, element1, element2);
176 }
177 const ElementIdentityEquivalence().visit(element1, element2);
178 }
179
180 /// Checks the pair-wise equivalence of the identity (but not properties) of the
181 /// elements in [list] and [list2].
182 ///
183 /// Uses [object1], [object2] and [property] to provide context for failures.
184 void checkElementListIdentities(
185 Object object1, Object object2, String property,
186 Iterable<Element> list1, Iterable<Element> list2) {
187 checkListEquivalence(
188 object1, object2, property,
189 list1, list2, checkElementIdentities);
190 }
191
192 /// Checks the equivalence of [type1] and [type2].
193 ///
194 /// Uses [object1], [object2] and [property] to provide context for failures.
195 void checkTypes(
196 Object object1, Object object2, String property,
197 DartType type1, DartType type2) {
198 if (identical(type1, type2)) return;
199 if (type1 == null || type2 == null) {
200 check(object1, object2, property, type1, type2);
201 }
202 const TypeEquivalence().visit(type1, type2);
203 }
204
205 /// Checks the pair-wise equivalence of the types in [list1] and [list2].
206 ///
207 /// Uses [object1], [object2] and [property] to provide context for failures.
208 void checkTypeLists(
209 Object object1, Object object2, String property,
210 List<DartType> list1, List<DartType> list2) {
211 checkListEquivalence(object1, object2, property, list1, list2, checkTypes);
212 }
213
214 /// Checks the equivalence of [exp1] and [exp2].
215 ///
216 /// Uses [object1], [object2] and [property] to provide context for failures.
217 void checkConstants(
218 Object object1, Object object2, String property,
219 ConstantExpression exp1, ConstantExpression exp2) {
220 if (identical(exp1, exp2)) return;
221 if (exp1 == null || exp2 == null) {
222 check(object1, object2, property, exp1, exp2);
223 }
224 const ConstantEquivalence().visit(exp1, exp2);
225 }
226
227 /// Checks the pair-wise equivalence of the contants in [list1] and [list2].
228 ///
229 /// Uses [object1], [object2] and [property] to provide context for failures.
230 void checkConstantLists(
231 Object object1, Object object2, String property,
232 List<ConstantExpression> list1,
233 List<ConstantExpression> list2) {
234 checkListEquivalence(
235 object1, object2, property,
236 list1, list2, checkConstants);
237 }
238
239 /// Checks the equivalence of [constructor1] and [constructor2].
240 void constantConstructorEquivalence(ConstantConstructor constructor1,
241 ConstantConstructor constructor2) {
242 const ConstantConstructorEquivalence().visit(constructor1, constructor2);
243 }
244
245 /// Visitor that checks the equivalence of [ConstantConstructor]s.
246 class ConstantConstructorEquivalence
247 extends ConstantConstructorVisitor<dynamic, ConstantConstructor> {
248 const ConstantConstructorEquivalence();
249
250 @override
251 void visit(ConstantConstructor constructor1,
252 ConstantConstructor constructor2) {
253 if (identical(constructor1, constructor2)) return;
254 check(constructor1, constructor2, 'kind',
255 constructor1.kind, constructor2.kind);
256 constructor1.accept(this, constructor2);
257 }
258
259 @override
260 visitGenerative(
261 GenerativeConstantConstructor constructor1,
262 GenerativeConstantConstructor constructor2) {
263 checkTypes(
264 constructor1, constructor2, 'type',
265 constructor1.type, constructor2.type);
266 check(constructor1, constructor2, 'defaultValues.length',
267 constructor1.defaultValues.length,
268 constructor2.defaultValues.length);
269 constructor1.defaultValues.forEach((k, v) {
270 checkConstants(
271 constructor1, constructor2, 'defaultValue[$k]',
272 v, constructor2.defaultValues[k]);
273 });
274 check(constructor1, constructor2, 'fieldMap.length',
275 constructor1.fieldMap.length,
276 constructor2.fieldMap.length);
277 constructor1.fieldMap.forEach((k1, v1) {
278 bool matched = false;
279 constructor2.fieldMap.forEach((k2, v2) {
280 if (k1.name == k2.name &&
281 k1.library.canonicalUri == k2.library.canonicalUri) {
282 checkElementIdentities(
283 constructor1, constructor2, 'fieldMap[${k1.name}].key', k1, k2);
284 checkConstants(
285 constructor1, constructor2, 'fieldMap[${k1.name}].value', v1, v2);
286 matched = true;
287 }
288 });
289 if (!matched) {
290 throw 'Unmatched field $k1 = $v1';
291 }
292 });
293 checkConstants(
294 constructor1, constructor2, 'superConstructorInvocation',
295 constructor1.superConstructorInvocation,
296 constructor2.superConstructorInvocation);
297 }
298
299 @override
300 visitRedirectingFactory(
301 RedirectingFactoryConstantConstructor constructor1,
302 RedirectingFactoryConstantConstructor constructor2) {
303 checkConstants(
304 constructor1, constructor2, 'targetConstructorInvocation',
305 constructor1.targetConstructorInvocation,
306 constructor2.targetConstructorInvocation);
307 }
308
309 @override
310 visitRedirectingGenerative(
311 RedirectingGenerativeConstantConstructor constructor1,
312 RedirectingGenerativeConstantConstructor constructor2) {
313 check(constructor1, constructor2, 'defaultValues.length',
314 constructor1.defaultValues.length,
315 constructor2.defaultValues.length);
316 constructor1.defaultValues.forEach((k, v) {
317 checkConstants(
318 constructor1, constructor2, 'defaultValue[$k]',
319 v, constructor2.defaultValues[k]);
320 });
321 checkConstants(
322 constructor1, constructor2, 'thisConstructorInvocation',
323 constructor1.thisConstructorInvocation,
324 constructor2.thisConstructorInvocation);
325 }
326 }
327
328 /// Check that the values [property] of [object1] and [object2], [value1] and
329 /// [value2] respectively, are equal and throw otherwise.
330 void check(var object1, var object2, String property, var value1, value2) {
331 if (value1 != value2) {
332 throw "$object1.$property = '${value1}' <> "
333 "$object2.$property = '${value2}'";
334 }
335 }
336
337 /// Visitor that checks for equivalence of [Element] identities.
338 class ElementIdentityEquivalence extends BaseElementVisitor<dynamic, Element> {
339 const ElementIdentityEquivalence();
340
341 void visit(Element element1, Element element2) {
342 check(element1, element2, 'kind', element1.kind, element2.kind);
343 element1.accept(this, element2);
344 }
345
346 @override
347 void visitElement(Element e, Element arg) {
348 throw new UnsupportedError("Unsupported element $e");
349 }
350
351 @override
352 void visitLibraryElement(LibraryElement element1, LibraryElement element2) {
353 check(element1, element2,
354 'canonicalUri',
355 element1.canonicalUri, element2.canonicalUri);
356 }
357
358 @override
359 void visitCompilationUnitElement(CompilationUnitElement element1,
360 CompilationUnitElement element2) {
361 check(element1, element2,
362 'name',
363 element1.name, element2.name);
364 visit(element1.library, element2.library);
365 }
366
367 @override
368 void visitClassElement(ClassElement element1, ClassElement element2) {
369 check(element1, element2,
370 'name',
371 element1.name, element2.name);
372 visit(element1.library, element2.library);
373 }
374
375 void checkMembers(Element element1, Element element2) {
376 check(element1, element2,
377 'name',
378 element1.name, element2.name);
379 if (element1.enclosingClass != null || element2.enclosingClass != null) {
380 visit(element1.enclosingClass, element2.enclosingClass);
381 } else {
382 visit(element1.library, element2.library);
383 }
384 }
385
386 @override
387 void visitFieldElement(FieldElement element1, FieldElement element2) {
388 checkMembers(element1, element2);
389 }
390
391 @override
392 void visitFunctionElement(FunctionElement element1,
393 FunctionElement element2) {
394 checkMembers(element1, element2);
395 }
396
397 void visitAbstractFieldElement(AbstractFieldElement element1,
398 AbstractFieldElement element2) {
399 checkMembers(element1, element2);
400 }
401
402 @override
403 void visitTypeVariableElement(TypeVariableElement element1,
404 TypeVariableElement element2) {
405 check(element1, element2,
406 'name',
407 element1.name, element2.name);
408 visit(element1.typeDeclaration, element2.typeDeclaration);
409 }
410
411 @override
412 void visitTypedefElement(TypedefElement element1, TypedefElement element2) {
413 check(element1, element2,
414 'name',
415 element1.name, element2.name);
416 visit(element1.library, element2.library);
417 }
418
419 @override
420 void visitParameterElement(ParameterElement element1,
421 ParameterElement element2) {
422 check(element1, element2,
423 'name',
424 element1.name, element2.name);
425 visit(element1.functionDeclaration, element2.functionDeclaration);
426 }
427 }
428
429 /// Visitor that checks for equivalence of [Element] properties.
430 class ElementPropertyEquivalence extends BaseElementVisitor<dynamic, Element> {
431 const ElementPropertyEquivalence();
432
433 void visit(Element element1, Element element2) {
434 if (element1 == element2) return;
435 check(element1, element2, 'kind', element1.kind, element2.kind);
436 element1.accept(this, element2);
437 }
438
439 @override
440 void visitElement(Element e, Element arg) {
441 throw new UnsupportedError("Unsupported element $e");
442 }
443
444 @override
445 void visitLibraryElement(LibraryElement element1, LibraryElement element2) {
446 checkElementIdentities(null, null, null, element1, element2);
447 check(element1, element2, 'name', element1.name, element2.name);
448 check(element1, element2, 'getLibraryName',
449 element1.getLibraryName(), element2.getLibraryName());
450 visitMembers(element1, element2);
451 visit(element1.entryCompilationUnit, element2.entryCompilationUnit);
452 checkElementLists(
453 element1, element2, 'compilationUnits',
454 element1.compilationUnits.toList(),
455 element2.compilationUnits.toList());
456
457 bool filterTags(LibraryTag tag) => tag.asLibraryDependency() != null;
458
459 List<LibraryTag> tags1 = element1.tags.where(filterTags).toList();
460 List<LibraryTag> tags2 = element2.tags.where(filterTags).toList();
461 checkListEquivalence(element1, element2, 'tags', tags1, tags2,
462 (Object object1, Object object2, String property,
463 LibraryDependency tag1, LibraryDependency tag2) {
464 checkElementIdentities(
465 tag1, tag2, 'getLibraryFromTag',
466 element1.getLibraryFromTag(tag1),
467 element2.getLibraryFromTag(tag2));
468 });
469
470 List<Element> imports1 = <Element>[];
471 List<Element> imports2 = <Element>[];
472 element1.forEachImport((Element import) {
473 if (import.isAmbiguous) return;
474 imports1.add(import);
475 });
476 element2.forEachImport((Element import) {
477 if (import.isAmbiguous) return;
478 imports2.add(import);
479 });
480 checkElementListIdentities(
481 element1, element2, 'imports', imports1, imports2);
482
483 List<Element> exports1 = <Element>[];
484 List<Element> exports2 = <Element>[];
485 element1.forEachExport((Element export) {
486 if (export.isAmbiguous) return;
487 exports1.add(export);
488 });
489 element2.forEachExport((Element export) {
490 if (export.isAmbiguous) return;
491 exports2.add(export);
492 });
493 checkElementListIdentities(
494 element1, element2, 'exports', exports1, exports2);
495 }
496
497 @override
498 void visitCompilationUnitElement(CompilationUnitElement element1,
499 CompilationUnitElement element2) {
500 check(element1, element2,
501 'name',
502 element1.name, element2.name);
503 checkElementIdentities(
504 element1, element2, 'library',
505 element1.library, element2.library);
506 check(element1, element2,
507 'script.resourceUri',
508 element1.script.resourceUri, element2.script.resourceUri);
509 List<Element> members1 = <Element>[];
510 List<Element> members2 = <Element>[];
511 element1.forEachLocalMember((Element member) {
512 members1.add(member);
513 });
514 element2.forEachLocalMember((Element member) {
515 members2.add(member);
516 });
517 checkElementListIdentities(
518 element1, element2, 'localMembers', members1, members2);
519 }
520
521 void visitMembers(ScopeContainerElement element1,
522 ScopeContainerElement element2) {
523 Set<String> names = new Set<String>();
524 element1.forEachLocalMember((Element member) {
525 names.add(member.name);
526 });
527 element2.forEachLocalMember((Element member) {
528 names.add(member.name);
529 });
530 for (String name in names) {
531 Element member1 = element1.localLookup(name);
532 Element member2 = element2.localLookup(name);
533 if (member1 == null) {
534 print('Missing member for $member2');
535 continue;
536 }
537 if (member2 == null) {
538 print('Missing member for $member1');
539 continue;
540 }
541 visit(member1, member2);
542 }
543 }
544
545 @override
546 void visitClassElement(ClassElement element1, ClassElement element2) {
547 checkElementIdentities(null, null, null, element1, element2);
548 check(element1, element2, 'name',
549 element1.name, element2.name);
550 check(element1, element2, 'sourcePosition',
551 element1.sourcePosition, element2.sourcePosition);
552 checkElementIdentities(
553 element1, element2, 'library',
554 element1.library, element2.library);
555 checkElementIdentities(
556 element1, element2, 'compilationUnit',
557 element1.compilationUnit, element2.compilationUnit);
558 check(element1, element2, 'isObject',
559 element1.isObject, element2.isObject);
560 checkTypeLists(element1, element2, 'typeVariables',
561 element1.typeVariables, element2.typeVariables);
562 check(element1, element2, 'isAbstract',
563 element1.isAbstract, element2.isAbstract);
564 if (!element1.isObject) {
565 checkTypes(element1, element2, 'supertype',
566 element1.supertype, element2.supertype);
567 }
568 check(element1, element2, 'hierarchyDepth',
569 element1.hierarchyDepth, element2.hierarchyDepth);
570 checkTypeLists(
571 element1, element2, 'allSupertypes',
572 element1.allSupertypes.toList(),
573 element2.allSupertypes.toList());
574 OrderedTypeSet typeSet1 = element1.allSupertypesAndSelf;
575 OrderedTypeSet typeSet2 = element1.allSupertypesAndSelf;
576 checkListEquivalence(
577 element1, element2, 'allSupertypes',
578 typeSet1.levelOffsets,
579 typeSet2.levelOffsets,
580 check);
581 check(element1, element2, 'allSupertypesAndSelf.levels',
582 typeSet1.levels, typeSet2.levels);
583 checkTypeLists(
584 element1, element2, 'supertypes',
585 typeSet1.supertypes.toList(),
586 typeSet2.supertypes.toList());
587 checkTypeLists(
588 element1, element2, 'types',
589 typeSet1.types.toList(),
590 typeSet2.types.toList());
591
592 checkTypeLists(
593 element1, element2, 'interfaces',
594 element1.interfaces.toList(),
595 element2.interfaces.toList());
596
597 visitMembers(element1, element2);
598 }
599
600 @override
601 void visitFieldElement(FieldElement element1, FieldElement element2) {
602 checkElementIdentities(null, null, null, element1, element2);
603 check(element1, element2, 'name',
604 element1.name, element2.name);
605 check(element1, element2, 'sourcePosition',
606 element1.sourcePosition, element2.sourcePosition);
607 checkTypes(
608 element1, element2, 'type',
609 element1.type, element2.type);
610 check(element1, element2, 'isConst',
611 element1.isConst, element2.isConst);
612 check(element1, element2, 'isFinal',
613 element1.isFinal, element2.isFinal);
614 if (element1.isConst) {
615 checkConstants(
616 element1, element2, 'constant',
617 element1.constant, element2.constant);
618 }
619 check(element1, element2, 'isTopLevel',
620 element1.isTopLevel, element2.isTopLevel);
621 check(element1, element2, 'isStatic',
622 element1.isStatic, element2.isStatic);
623 check(element1, element2, 'isInstanceMember',
624 element1.isInstanceMember, element2.isInstanceMember);
625
626 checkElementIdentities(
627 element1, element2, 'library',
628 element1.library, element2.library);
629 checkElementIdentities(
630 element1, element2, 'compilationUnit',
631 element1.compilationUnit, element2.compilationUnit);
632 checkElementIdentities(
633 element1, element2, 'enclosingClass',
634 element1.enclosingClass, element2.enclosingClass);
635 }
636
637 @override
638 void visitFunctionElement(FunctionElement element1,
639 FunctionElement element2) {
640 checkElementIdentities(null, null, null, element1, element2);
641 check(element1, element2, 'name',
642 element1.name, element2.name);
643 check(element1, element2, 'sourcePosition',
644 element1.sourcePosition, element2.sourcePosition);
645 checkTypes(
646 element1, element2, 'type',
647 element1.type, element2.type);
648 checkListEquivalence(
649 element1, element2, 'parameters',
650 element1.parameters, element2.parameters,
651 checkElementProperties);
652 check(element1, element2, 'isOperator',
653 element1.isOperator, element2.isOperator);
654
655 checkElementIdentities(
656 element1, element2, 'library',
657 element1.library, element2.library);
658 checkElementIdentities(
659 element1, element2, 'compilationUnit',
660 element1.compilationUnit, element2.compilationUnit);
661 checkElementIdentities(
662 element1, element2, 'enclosingClass',
663 element1.enclosingClass, element2.enclosingClass);
664 }
665
666 @override
667 void visitConstructorElement(ConstructorElement element1,
668 ConstructorElement element2) {
669 checkElementIdentities(null, null, null, element1, element2);
670 checkElementIdentities(
671 element1, element2, 'enclosingClass',
672 element1.enclosingClass, element2.enclosingClass);
673 check(
674 element1, element2, 'name',
675 element1.name, element2.name);
676 check(element1, element2, 'sourcePosition',
677 element1.sourcePosition, element2.sourcePosition);
678 checkListEquivalence(
679 element1, element2, 'parameters',
680 element1.parameters, element2.parameters,
681 checkElementProperties);
682 checkTypes(
683 element1, element2, 'type',
684 element1.type, element2.type);
685 check(element1, element2, 'isConst',
686 element1.isConst, element2.isConst);
687 if (element1.isConst) {
688 constantConstructorEquivalence(
689 element1.constantConstructor,
690 element2.constantConstructor);
691 }
692 }
693
694 @override
695 void visitAbstractFieldElement(AbstractFieldElement element1,
696 AbstractFieldElement element2) {
697 visit(element1.getter, element2.getter);
698 visit(element1.setter, element2.setter);
699 }
700
701 @override
702 void visitTypeVariableElement(TypeVariableElement element1,
703 TypeVariableElement element2) {
704 checkElementIdentities(null, null, null, element1, element2);
705 check(element1, element2, 'name', element1.name, element2.name);
706 check(element1, element2, 'sourcePosition',
707 element1.sourcePosition, element2.sourcePosition);
708 check(element1, element2, 'index', element1.index, element2.index);
709 checkTypes(
710 element1, element2, 'type',
711 element1.type, element2.type);
712 checkTypes(
713 element1, element2, 'bound',
714 element1.bound, element2.bound);
715 }
716
717 @override
718 void visitTypedefElement(TypedefElement element1,
719 TypedefElement element2) {
720 checkElementIdentities(null, null, null, element1, element2);
721 check(element1, element2, 'name', element1.name, element2.name);
722 check(element1, element2, 'sourcePosition',
723 element1.sourcePosition, element2.sourcePosition);
724 checkTypes(
725 element1, element2, 'alias',
726 element1.alias, element2.alias);
727 checkTypeLists(
728 element1, element2, 'typeVariables',
729 element1.typeVariables, element2.typeVariables);
730 checkElementIdentities(
731 element1, element2, 'library',
732 element1.library, element2.library);
733 checkElementIdentities(
734 element1, element2, 'compilationUnit',
735 element1.compilationUnit, element2.compilationUnit);
736 // TODO(johnniwinther): Check the equivalence of typedef parameters.
737 }
738
739 @override
740 void visitParameterElement(ParameterElement element1,
741 ParameterElement element2) {
742 checkElementIdentities(null, null, null, element1, element2);
743 checkElementIdentities(
744 element1, element2, 'functionDeclaration',
745 element1.functionDeclaration, element2.functionDeclaration);
746 check(element1, element2, 'name', element1.name, element2.name);
747 check(element1, element2, 'sourcePosition',
748 element1.sourcePosition, element2.sourcePosition);
749 checkTypes(
750 element1, element2, 'type',
751 element1.type, element2.type);
752 check(
753 element1, element2, 'isOptional',
754 element1.isOptional, element2.isOptional);
755 check(
756 element1, element2, 'isNamed',
757 element1.isNamed, element2.isNamed);
758 check(element1, element2, 'name', element1.name, element2.name);
759 if (element1.isOptional) {
760 checkConstants(
761 element1, element2, 'constant',
762 element1.constant, element2.constant);
763 }
764 checkElementIdentities(
765 element1, element2, 'compilationUnit',
766 element1.compilationUnit, element2.compilationUnit);
767 }
768
769 @override
770 void visitFieldParameterElement(InitializingFormalElement element1,
771 InitializingFormalElement element2) {
772 visitParameterElement(element1, element2);
773 checkElementIdentities(
774 element1, element2, 'fieldElement',
775 element1.fieldElement, element2.fieldElement);
776 }
777 }
778
779 /// Visitor that checks for equivalence of [DartType]s.
780 class TypeEquivalence implements DartTypeVisitor<dynamic, DartType> {
781 const TypeEquivalence();
782
783 void visit(DartType type1, DartType type2) {
784 check(type1, type2, 'kind', type1.kind, type2.kind);
785 type1.accept(this, type2);
786 }
787
788 @override
789 void visitDynamicType(DynamicType type, DynamicType other) {
790 }
791
792 @override
793 void visitFunctionType(FunctionType type, FunctionType other) {
794 checkTypeLists(
795 type, other, 'parameterTypes',
796 type.parameterTypes, other.parameterTypes);
797 checkTypeLists(
798 type, other, 'optionalParameterTypes',
799 type.optionalParameterTypes, other.optionalParameterTypes);
800 checkTypeLists(
801 type, other, 'namedParameterTypes',
802 type.namedParameterTypes, other.namedParameterTypes);
803 for (int i = 0; i < type.namedParameters.length; i++) {
804 if (type.namedParameters[i] != other.namedParameters[i]) {
805 throw "Named parameter '$type.namedParameters[i]' <> "
806 "'${other.namedParameters[i]}'";
807 }
808 }
809 }
810
811 void visitGenericType(GenericType type, GenericType other) {
812 checkElementIdentities(
813 type, other, 'element',
814 type.element, other.element);
815 checkTypeLists(
816 type, other, 'typeArguments',
817 type.typeArguments, other.typeArguments);
818 }
819
820 @override
821 void visitMalformedType(MalformedType type, MalformedType other) {
822 }
823
824 @override
825 void visitStatementType(StatementType type, StatementType other) {
826 throw new UnsupportedError("Unsupported type: $type");
827 }
828
829 @override
830 void visitTypeVariableType(TypeVariableType type, TypeVariableType other) {
831 checkElementIdentities(
832 type, other, 'element',
833 type.element, other.element);
834 }
835
836 @override
837 void visitVoidType(VoidType type, VoidType argument) {
838 }
839
840 @override
841 void visitInterfaceType(InterfaceType type, InterfaceType other) {
842 visitGenericType(type, other);
843 }
844
845 @override
846 void visitTypedefType(TypedefType type, TypedefType other) {
847 visitGenericType(type, other);
848 }
849 }
850
851 /// Visitor that checks for structural equivalence of [ConstantExpression]s.
852 class ConstantEquivalence
853 implements ConstantExpressionVisitor<dynamic, ConstantExpression> {
854 const ConstantEquivalence();
855
856 @override
857 visit(ConstantExpression exp1, ConstantExpression exp2) {
858 if (identical(exp1, exp2)) return;
859 check(exp1, exp2, 'kind', exp1.kind, exp2.kind);
860 exp1.accept(this, exp2);
861 }
862
863 @override
864 visitBinary(BinaryConstantExpression exp1, BinaryConstantExpression exp2) {
865 check(exp1, exp2, 'operator', exp1.operator, exp2.operator);
866 checkConstants(exp1, exp2, 'left', exp1.left, exp2.left);
867 checkConstants(exp1, exp2, 'right', exp1.right, exp2.right);
868 }
869
870 @override
871 visitConcatenate(ConcatenateConstantExpression exp1,
872 ConcatenateConstantExpression exp2) {
873 checkConstantLists(
874 exp1, exp2, 'expressions',
875 exp1.expressions, exp2.expressions);
876 }
877
878 @override
879 visitConditional(ConditionalConstantExpression exp1,
880 ConditionalConstantExpression exp2) {
881 checkConstants(
882 exp1, exp2, 'condition', exp1.condition, exp2.condition);
883 checkConstants(exp1, exp2, 'trueExp', exp1.trueExp, exp2.trueExp);
884 checkConstants(exp1, exp2, 'falseExp', exp1.falseExp, exp2.falseExp);
885 }
886
887 @override
888 visitConstructed(ConstructedConstantExpression exp1,
889 ConstructedConstantExpression exp2) {
890 checkTypes(
891 exp1, exp2, 'type',
892 exp1.type, exp2.type);
893 checkElementIdentities(
894 exp1, exp2, 'target',
895 exp1.target, exp2.target);
896 checkConstantLists(
897 exp1, exp2, 'arguments',
898 exp1.arguments, exp2.arguments);
899 check(exp1, exp2, 'callStructure', exp1.callStructure, exp2.callStructure);
900 }
901
902 @override
903 visitFunction(FunctionConstantExpression exp1,
904 FunctionConstantExpression exp2) {
905 checkElementIdentities(
906 exp1, exp2, 'element',
907 exp1.element, exp2.element);
908 }
909
910 @override
911 visitIdentical(IdenticalConstantExpression exp1,
912 IdenticalConstantExpression exp2) {
913 checkConstants(exp1, exp2, 'left', exp1.left, exp2.left);
914 checkConstants(exp1, exp2, 'right', exp1.right, exp2.right);
915 }
916
917 @override
918 visitList(ListConstantExpression exp1, ListConstantExpression exp2) {
919 checkTypes(
920 exp1, exp2, 'type',
921 exp1.type, exp2.type);
922 checkConstantLists(
923 exp1, exp2, 'values',
924 exp1.values, exp2.values);
925 }
926
927 @override
928 visitMap(MapConstantExpression exp1, MapConstantExpression exp2) {
929 checkTypes(
930 exp1, exp2, 'type',
931 exp1.type, exp2.type);
932 checkConstantLists(
933 exp1, exp2, 'keys',
934 exp1.keys, exp2.keys);
935 checkConstantLists(
936 exp1, exp2, 'values',
937 exp1.values, exp2.values);
938 }
939
940 @override
941 visitNamed(NamedArgumentReference exp1, NamedArgumentReference exp2) {
942 check(exp1, exp2, 'name', exp1.name, exp2.name);
943 }
944
945 @override
946 visitPositional(PositionalArgumentReference exp1,
947 PositionalArgumentReference exp2) {
948 check(exp1, exp2, 'index', exp1.index, exp2.index);
949 }
950
951 @override
952 visitSymbol(SymbolConstantExpression exp1, SymbolConstantExpression exp2) {
953 // TODO: implement visitSymbol
954 }
955
956 @override
957 visitType(TypeConstantExpression exp1, TypeConstantExpression exp2) {
958 checkTypes(
959 exp1, exp2, 'type',
960 exp1.type, exp2.type);
961 }
962
963 @override
964 visitUnary(UnaryConstantExpression exp1, UnaryConstantExpression exp2) {
965 check(exp1, exp2, 'operator', exp1.operator, exp2.operator);
966 checkConstants(
967 exp1, exp2, 'expression', exp1.expression, exp2.expression);
968 }
969
970 @override
971 visitVariable(VariableConstantExpression exp1,
972 VariableConstantExpression exp2) {
973 checkElementIdentities(
974 exp1, exp2, 'element',
975 exp1.element, exp2.element);
976 }
977
978 @override
979 visitBool(BoolConstantExpression exp1, BoolConstantExpression exp2) {
980 check(exp1, exp2, 'primitiveValue',
981 exp1.primitiveValue, exp2.primitiveValue);
982 }
983
984 @override
985 visitDouble(DoubleConstantExpression exp1, DoubleConstantExpression exp2) {
986 check(exp1, exp2, 'primitiveValue',
987 exp1.primitiveValue, exp2.primitiveValue);
988 }
989
990 @override
991 visitInt(IntConstantExpression exp1, IntConstantExpression exp2) {
992 check(exp1, exp2, 'primitiveValue',
993 exp1.primitiveValue, exp2.primitiveValue);
994 }
995
996 @override
997 visitNull(NullConstantExpression exp1, NullConstantExpression exp2) {
998 // Do nothing.
999 }
1000
1001 @override
1002 visitString(StringConstantExpression exp1, StringConstantExpression exp2) {
1003 check(exp1, exp2, 'primitiveValue',
1004 exp1.primitiveValue, exp2.primitiveValue);
1005 }
1006
1007 @override
1008 visitBoolFromEnvironment(BoolFromEnvironmentConstantExpression exp1,
1009 BoolFromEnvironmentConstantExpression exp2) {
1010 checkConstants(exp1, exp2, 'name', exp1.name, exp2.name);
1011 checkConstants(
1012 exp1, exp2, 'defaultValue',
1013 exp1.defaultValue, exp2.defaultValue);
1014 }
1015
1016 @override
1017 visitIntFromEnvironment(IntFromEnvironmentConstantExpression exp1,
1018 IntFromEnvironmentConstantExpression exp2) {
1019 checkConstants(exp1, exp2, 'name', exp1.name, exp2.name);
1020 checkConstants(
1021 exp1, exp2, 'defaultValue',
1022 exp1.defaultValue, exp2.defaultValue);
1023 }
1024
1025 @override
1026 visitStringFromEnvironment(StringFromEnvironmentConstantExpression exp1,
1027 StringFromEnvironmentConstantExpression exp2) {
1028 checkConstants(exp1, exp2, 'name', exp1.name, exp2.name);
1029 checkConstants(
1030 exp1, exp2, 'defaultValue',
1031 exp1.defaultValue, exp2.defaultValue);
1032 }
1033
1034 @override
1035 visitStringLength(StringLengthConstantExpression exp1,
1036 StringLengthConstantExpression exp2) {
1037 checkConstants(
1038 exp1, exp2, 'expression',
1039 exp1.expression, exp2.expression);
1040 }
1041
1042 @override
1043 visitDeferred(DeferredConstantExpression exp1,
1044 DeferredConstantExpression exp2) {
1045 // TODO: implement visitDeferred
1046 }
1047 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698