| OLD | NEW |
| (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 } |
| OLD | NEW |