| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 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 | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library dart2js.serialization_test; | 5 library dart2js.serialization_test; |
| 6 | 6 |
| 7 import 'dart:io'; | 7 import 'dart:io'; |
| 8 import 'memory_compiler.dart'; | 8 import 'memory_compiler.dart'; |
| 9 import 'package:async_helper/async_helper.dart'; | 9 import 'package:async_helper/async_helper.dart'; |
| 10 import 'package:compiler/src/commandline_options.dart'; | 10 import 'package:compiler/src/commandline_options.dart'; |
| 11 import 'package:compiler/src/constants/constructors.dart'; | 11 import 'package:compiler/src/constants/constructors.dart'; |
| 12 import 'package:compiler/src/constants/expressions.dart'; | 12 import 'package:compiler/src/constants/expressions.dart'; |
| 13 import 'package:compiler/src/dart_types.dart'; | 13 import 'package:compiler/src/dart_types.dart'; |
| 14 import 'package:compiler/src/compiler.dart'; | 14 import 'package:compiler/src/compiler.dart'; |
| 15 import 'package:compiler/src/diagnostics/invariant.dart'; | 15 import 'package:compiler/src/diagnostics/invariant.dart'; |
| 16 import 'package:compiler/src/elements/elements.dart'; | 16 import 'package:compiler/src/elements/elements.dart'; |
| 17 import 'package:compiler/src/elements/visitor.dart'; | 17 import 'package:compiler/src/elements/visitor.dart'; |
| 18 import 'package:compiler/src/ordered_typeset.dart'; | 18 import 'package:compiler/src/ordered_typeset.dart'; |
| 19 import 'package:compiler/src/serialization/element_serialization.dart'; | 19 import 'package:compiler/src/serialization/element_serialization.dart'; |
| 20 import 'package:compiler/src/serialization/equivalence.dart'; |
| 20 import 'package:compiler/src/serialization/json_serializer.dart'; | 21 import 'package:compiler/src/serialization/json_serializer.dart'; |
| 21 import 'package:compiler/src/serialization/serialization.dart'; | 22 import 'package:compiler/src/serialization/serialization.dart'; |
| 22 | 23 |
| 23 main(List<String> arguments) { | 24 main(List<String> arguments) { |
| 24 // Ensure that we can print out constant expressions. | 25 // Ensure that we can print out constant expressions. |
| 25 DEBUG_MODE = true; | 26 DEBUG_MODE = true; |
| 26 | 27 |
| 27 Uri entryPoint; | 28 Uri entryPoint; |
| 28 String outPath; | 29 String outPath; |
| 29 bool prettyPrint = false; | 30 bool prettyPrint = false; |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 checkElementLists(Object object1, Object object2, String property, | 138 checkElementLists(Object object1, Object object2, String property, |
| 138 Iterable<Element> list1, Iterable<Element> list2) { | 139 Iterable<Element> list1, Iterable<Element> list2) { |
| 139 checkListEquivalence(object1, object2, property, | 140 checkListEquivalence(object1, object2, property, |
| 140 list1, list2, checkElementProperties); | 141 list1, list2, checkElementProperties); |
| 141 } | 142 } |
| 142 | 143 |
| 143 /// Check equivalence of the two lists, [list1] and [list2], using | 144 /// Check equivalence of the two lists, [list1] and [list2], using |
| 144 /// [checkEquivalence] to check the pair-wise equivalence. | 145 /// [checkEquivalence] to check the pair-wise equivalence. |
| 145 /// | 146 /// |
| 146 /// Uses [object1], [object2] and [property] to provide context for failures. | 147 /// Uses [object1], [object2] and [property] to provide context for failures. |
| 147 void checkListEquivalence( | 148 bool checkListEquivalence( |
| 148 Object object1, Object object2, String property, | 149 Object object1, Object object2, String property, |
| 149 Iterable list1, Iterable list2, | 150 Iterable list1, Iterable list2, |
| 150 void checkEquivalence(o1, o2, property, a, b)) { | 151 void checkEquivalence(o1, o2, property, a, b)) { |
| 151 for (int i = 0; i < list1.length && i < list2.length; i++) { | 152 for (int i = 0; i < list1.length && i < list2.length; i++) { |
| 152 checkEquivalence( | 153 checkEquivalence( |
| 153 object1, object2, property, | 154 object1, object2, property, |
| 154 list1.elementAt(i), list2.elementAt(i)); | 155 list1.elementAt(i), list2.elementAt(i)); |
| 155 } | 156 } |
| 156 for (int i = list1.length; i < list2.length; i++) { | 157 for (int i = list1.length; i < list2.length; i++) { |
| 157 throw | 158 throw |
| 158 'Missing equivalent for element ' | 159 'Missing equivalent for element ' |
| 159 '#$i ${list2.elementAt(i)} in `${property}` on $object2.\n' | 160 '#$i ${list2.elementAt(i)} in `${property}` on $object2.\n' |
| 160 '`${property}` on $object1:\n ${list1.join('\n ')}\n' | 161 '`${property}` on $object1:\n ${list1.join('\n ')}\n' |
| 161 '`${property}` on $object2:\n ${list2.join('\n ')}'; | 162 '`${property}` on $object2:\n ${list2.join('\n ')}'; |
| 162 } | 163 } |
| 163 for (int i = list2.length; i < list1.length; i++) { | 164 for (int i = list2.length; i < list1.length; i++) { |
| 164 throw | 165 throw |
| 165 'Missing equivalent for element ' | 166 'Missing equivalent for element ' |
| 166 '#$i ${list1.elementAt(i)} in `${property}` on $object1.\n' | 167 '#$i ${list1.elementAt(i)} in `${property}` on $object1.\n' |
| 167 '`${property}` on $object1:\n ${list1.join('\n ')}\n' | 168 '`${property}` on $object1:\n ${list1.join('\n ')}\n' |
| 168 '`${property}` on $object2:\n ${list2.join('\n ')}'; | 169 '`${property}` on $object2:\n ${list2.join('\n ')}'; |
| 169 } | 170 } |
| 171 return true; |
| 172 } |
| 173 |
| 174 /// Check equivalence of the two iterables, [set1] and [set1], as sets using |
| 175 /// [elementEquivalence] to compute the pair-wise equivalence. |
| 176 /// |
| 177 /// Uses [object1], [object2] and [property] to provide context for failures. |
| 178 bool checkSetEquivalence( |
| 179 var object1, |
| 180 var object2, |
| 181 String property, |
| 182 Iterable set1, |
| 183 Iterable set2, |
| 184 bool sameElement(a, b)) { |
| 185 List common = []; |
| 186 List unfound = []; |
| 187 Set remaining = set2.toSet(); |
| 188 for (var element1 in set1) { |
| 189 bool found = false; |
| 190 for (var element2 in remaining) { |
| 191 if (sameElement(element1, element2)) { |
| 192 found = true; |
| 193 remaining.remove(element2); |
| 194 break; |
| 195 } |
| 196 } |
| 197 if (found) { |
| 198 common.add(element1); |
| 199 } else { |
| 200 unfound.add(element1); |
| 201 } |
| 202 } |
| 203 if (unfound.isNotEmpty || remaining.isNotEmpty) { |
| 204 String message = |
| 205 "Set mismatch for `$property` on $object1 vs $object2: \n" |
| 206 "Common:\n ${common.join('\n ')}\n" |
| 207 "Unfound:\n ${unfound.join('\n ')}\n" |
| 208 "Extra: \n ${remaining.join('\n ')}"; |
| 209 throw message; |
| 210 } |
| 211 return true; |
| 170 } | 212 } |
| 171 | 213 |
| 172 /// Checks the equivalence of the identity (but not properties) of [element1] | 214 /// Checks the equivalence of the identity (but not properties) of [element1] |
| 173 /// and [element2]. | 215 /// and [element2]. |
| 174 /// | 216 /// |
| 175 /// Uses [object1], [object2] and [property] to provide context for failures. | 217 /// Uses [object1], [object2] and [property] to provide context for failures. |
| 176 void checkElementIdentities( | 218 bool checkElementIdentities( |
| 177 Object object1, Object object2, String property, | 219 Object object1, Object object2, String property, |
| 178 Element element1, Element element2) { | 220 Element element1, Element element2) { |
| 179 if (identical(element1, element2)) return; | 221 if (identical(element1, element2)) return true; |
| 180 if (element1 == null || element2 == null) { | 222 if (element1 == null || element2 == null) { |
| 181 check(object1, object2, property, element1, element2); | 223 return check(object1, object2, property, element1, element2); |
| 224 } else { |
| 225 return const ElementIdentityEquivalence(const CheckStrategy()) |
| 226 .visit(element1, element2); |
| 182 } | 227 } |
| 183 const ElementIdentityEquivalence().visit(element1, element2); | |
| 184 } | 228 } |
| 185 | 229 |
| 186 /// Checks the pair-wise equivalence of the identity (but not properties) of the | 230 /// Checks the pair-wise equivalence of the identity (but not properties) of the |
| 187 /// elements in [list] and [list2]. | 231 /// elements in [list] and [list2]. |
| 188 /// | 232 /// |
| 189 /// Uses [object1], [object2] and [property] to provide context for failures. | 233 /// Uses [object1], [object2] and [property] to provide context for failures. |
| 190 void checkElementListIdentities( | 234 bool checkElementListIdentities( |
| 191 Object object1, Object object2, String property, | 235 Object object1, Object object2, String property, |
| 192 Iterable<Element> list1, Iterable<Element> list2) { | 236 Iterable<Element> list1, Iterable<Element> list2) { |
| 193 checkListEquivalence( | 237 return checkListEquivalence( |
| 194 object1, object2, property, | 238 object1, object2, property, |
| 195 list1, list2, checkElementIdentities); | 239 list1, list2, checkElementIdentities); |
| 196 } | 240 } |
| 197 | 241 |
| 198 /// Checks the equivalence of [type1] and [type2]. | 242 /// Checks the equivalence of [type1] and [type2]. |
| 199 /// | 243 /// |
| 200 /// Uses [object1], [object2] and [property] to provide context for failures. | 244 /// Uses [object1], [object2] and [property] to provide context for failures. |
| 201 void checkTypes( | 245 bool checkTypes( |
| 202 Object object1, Object object2, String property, | 246 Object object1, Object object2, String property, |
| 203 DartType type1, DartType type2) { | 247 DartType type1, DartType type2) { |
| 204 if (identical(type1, type2)) return; | 248 if (identical(type1, type2)) return true; |
| 205 if (type1 == null || type2 == null) { | 249 if (type1 == null || type2 == null) { |
| 206 check(object1, object2, property, type1, type2); | 250 return check(object1, object2, property, type1, type2); |
| 251 } else { |
| 252 return const TypeEquivalence(const CheckStrategy()).visit(type1, type2); |
| 207 } | 253 } |
| 208 const TypeEquivalence().visit(type1, type2); | |
| 209 } | 254 } |
| 210 | 255 |
| 211 /// Checks the pair-wise equivalence of the types in [list1] and [list2]. | 256 /// Checks the pair-wise equivalence of the types in [list1] and [list2]. |
| 212 /// | 257 /// |
| 213 /// Uses [object1], [object2] and [property] to provide context for failures. | 258 /// Uses [object1], [object2] and [property] to provide context for failures. |
| 214 void checkTypeLists( | 259 bool checkTypeLists( |
| 215 Object object1, Object object2, String property, | 260 Object object1, Object object2, String property, |
| 216 List<DartType> list1, List<DartType> list2) { | 261 List<DartType> list1, List<DartType> list2) { |
| 217 checkListEquivalence(object1, object2, property, list1, list2, checkTypes); | 262 return checkListEquivalence( |
| 263 object1, object2, property, list1, list2, checkTypes); |
| 218 } | 264 } |
| 219 | 265 |
| 220 /// Checks the equivalence of [exp1] and [exp2]. | 266 /// Checks the equivalence of [exp1] and [exp2]. |
| 221 /// | 267 /// |
| 222 /// Uses [object1], [object2] and [property] to provide context for failures. | 268 /// Uses [object1], [object2] and [property] to provide context for failures. |
| 223 void checkConstants( | 269 bool checkConstants( |
| 224 Object object1, Object object2, String property, | 270 Object object1, Object object2, String property, |
| 225 ConstantExpression exp1, ConstantExpression exp2) { | 271 ConstantExpression exp1, ConstantExpression exp2) { |
| 226 if (identical(exp1, exp2)) return; | 272 if (identical(exp1, exp2)) return true; |
| 227 if (exp1 == null || exp2 == null) { | 273 if (exp1 == null || exp2 == null) { |
| 228 check(object1, object2, property, exp1, exp2); | 274 return check(object1, object2, property, exp1, exp2); |
| 275 } else { |
| 276 return const ConstantEquivalence(const CheckStrategy()).visit(exp1, exp2); |
| 229 } | 277 } |
| 230 const ConstantEquivalence().visit(exp1, exp2); | |
| 231 } | 278 } |
| 232 | 279 |
| 233 /// Checks the pair-wise equivalence of the contants in [list1] and [list2]. | 280 /// Checks the pair-wise equivalence of the contants in [list1] and [list2]. |
| 234 /// | 281 /// |
| 235 /// Uses [object1], [object2] and [property] to provide context for failures. | 282 /// Uses [object1], [object2] and [property] to provide context for failures. |
| 236 void checkConstantLists( | 283 bool checkConstantLists( |
| 237 Object object1, Object object2, String property, | 284 Object object1, Object object2, String property, |
| 238 List<ConstantExpression> list1, | 285 List<ConstantExpression> list1, |
| 239 List<ConstantExpression> list2) { | 286 List<ConstantExpression> list2) { |
| 240 checkListEquivalence( | 287 return checkListEquivalence( |
| 241 object1, object2, property, | 288 object1, object2, property, |
| 242 list1, list2, checkConstants); | 289 list1, list2, checkConstants); |
| 243 } | 290 } |
| 244 | 291 |
| 292 |
| 293 /// Strategy for checking equivalence. |
| 294 /// |
| 295 /// Use this strategy to fail early with contextual information in the event of |
| 296 /// inequivalence. |
| 297 class CheckStrategy implements TestStrategy { |
| 298 const CheckStrategy(); |
| 299 |
| 300 @override |
| 301 bool test(var object1, var object2, String property, var value1, var value2) { |
| 302 return check(object1, object2, property, value1, value2); |
| 303 } |
| 304 |
| 305 @override |
| 306 bool testLists( |
| 307 Object object1, Object object2, String property, |
| 308 List list1, List list2, |
| 309 [bool elementEquivalence(a, b) = equality]) { |
| 310 return checkListEquivalence( |
| 311 object1, object2, property, list1, list2, |
| 312 (o1, o2, p, v1, v2) { |
| 313 if (!elementEquivalence(v1, v2)) { |
| 314 throw "$o1.$p = '${v1}' <> " |
| 315 "$o2.$p = '${v2}'"; |
| 316 } |
| 317 return true; |
| 318 }); |
| 319 } |
| 320 |
| 321 @override |
| 322 bool testSets( |
| 323 var object1, var object2, String property, |
| 324 Iterable set1, Iterable set2, |
| 325 [bool elementEquivalence(a, b) = equality]) { |
| 326 return checkSetEquivalence( |
| 327 object1, object2,property, set1, set2, elementEquivalence); |
| 328 } |
| 329 |
| 330 @override |
| 331 bool testElements( |
| 332 Object object1, Object object2, String property, |
| 333 Element element1, Element element2) { |
| 334 return checkElementIdentities( |
| 335 object1, object2, property, element1, element2); |
| 336 } |
| 337 |
| 338 @override |
| 339 bool testTypes( |
| 340 Object object1, Object object2, String property, |
| 341 DartType type1, DartType type2) { |
| 342 return checkTypes(object1, object2, property, type1, type2); |
| 343 } |
| 344 |
| 345 @override |
| 346 bool testConstants( |
| 347 Object object1, Object object2, String property, |
| 348 ConstantExpression exp1, ConstantExpression exp2) { |
| 349 return checkConstants(object1, object2, property, exp1, exp2); |
| 350 } |
| 351 |
| 352 @override |
| 353 bool testTypeLists( |
| 354 Object object1, Object object2, String property, |
| 355 List<DartType> list1, List<DartType> list2) { |
| 356 return checkTypeLists(object1, object2, property, list1, list2); |
| 357 } |
| 358 |
| 359 @override |
| 360 bool testConstantLists( |
| 361 Object object1, Object object2, String property, |
| 362 List<ConstantExpression> list1, |
| 363 List<ConstantExpression> list2) { |
| 364 return checkConstantLists(object1, object2, property, list1, list2); |
| 365 } |
| 366 } |
| 367 |
| 245 /// Checks the equivalence of [constructor1] and [constructor2]. | 368 /// Checks the equivalence of [constructor1] and [constructor2]. |
| 246 void constantConstructorEquivalence(ConstantConstructor constructor1, | 369 void constantConstructorEquivalence(ConstantConstructor constructor1, |
| 247 ConstantConstructor constructor2) { | 370 ConstantConstructor constructor2) { |
| 248 const ConstantConstructorEquivalence().visit(constructor1, constructor2); | 371 const ConstantConstructorEquivalence().visit(constructor1, constructor2); |
| 249 } | 372 } |
| 250 | 373 |
| 251 /// Visitor that checks the equivalence of [ConstantConstructor]s. | 374 /// Visitor that checks the equivalence of [ConstantConstructor]s. |
| 252 class ConstantConstructorEquivalence | 375 class ConstantConstructorEquivalence |
| 253 extends ConstantConstructorVisitor<dynamic, ConstantConstructor> { | 376 extends ConstantConstructorVisitor<dynamic, ConstantConstructor> { |
| 254 const ConstantConstructorEquivalence(); | 377 const ConstantConstructorEquivalence(); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 326 }); | 449 }); |
| 327 checkConstants( | 450 checkConstants( |
| 328 constructor1, constructor2, 'thisConstructorInvocation', | 451 constructor1, constructor2, 'thisConstructorInvocation', |
| 329 constructor1.thisConstructorInvocation, | 452 constructor1.thisConstructorInvocation, |
| 330 constructor2.thisConstructorInvocation); | 453 constructor2.thisConstructorInvocation); |
| 331 } | 454 } |
| 332 } | 455 } |
| 333 | 456 |
| 334 /// Check that the values [property] of [object1] and [object2], [value1] and | 457 /// Check that the values [property] of [object1] and [object2], [value1] and |
| 335 /// [value2] respectively, are equal and throw otherwise. | 458 /// [value2] respectively, are equal and throw otherwise. |
| 336 void check(var object1, var object2, String property, var value1, value2) { | 459 bool check(var object1, var object2, String property, var value1, value2) { |
| 337 if (value1 != value2) { | 460 if (value1 != value2) { |
| 338 throw "$object1.$property = '${value1}' <> " | 461 throw "$object1.$property = '${value1}' <> " |
| 339 "$object2.$property = '${value2}'"; | 462 "$object2.$property = '${value2}'"; |
| 340 } | 463 } |
| 341 } | 464 return true; |
| 342 | |
| 343 /// Visitor that checks for equivalence of [Element] identities. | |
| 344 class ElementIdentityEquivalence extends BaseElementVisitor<dynamic, Element> { | |
| 345 const ElementIdentityEquivalence(); | |
| 346 | |
| 347 void visit(Element element1, Element element2) { | |
| 348 if (element1 == null && element2 == null) return; | |
| 349 element1 = element1.declaration; | |
| 350 element2 = element2.declaration; | |
| 351 if (element1 == element2) return; | |
| 352 check(element1, element2, 'kind', element1.kind, element2.kind); | |
| 353 element1.accept(this, element2); | |
| 354 } | |
| 355 | |
| 356 @override | |
| 357 void visitElement(Element e, Element arg) { | |
| 358 throw new UnsupportedError("Unsupported element $e"); | |
| 359 } | |
| 360 | |
| 361 @override | |
| 362 void visitLibraryElement(LibraryElement element1, LibraryElement element2) { | |
| 363 check(element1, element2, | |
| 364 'canonicalUri', | |
| 365 element1.canonicalUri, element2.canonicalUri); | |
| 366 } | |
| 367 | |
| 368 @override | |
| 369 void visitCompilationUnitElement(CompilationUnitElement element1, | |
| 370 CompilationUnitElement element2) { | |
| 371 check(element1, element2, | |
| 372 'name', | |
| 373 element1.name, element2.name); | |
| 374 visit(element1.library, element2.library); | |
| 375 } | |
| 376 | |
| 377 @override | |
| 378 void visitClassElement(ClassElement element1, ClassElement element2) { | |
| 379 check(element1, element2, | |
| 380 'name', | |
| 381 element1.name, element2.name); | |
| 382 visit(element1.library, element2.library); | |
| 383 } | |
| 384 | |
| 385 void checkMembers(Element element1, Element element2) { | |
| 386 check(element1, element2, | |
| 387 'name', | |
| 388 element1.name, element2.name); | |
| 389 if (element1.enclosingClass != null || element2.enclosingClass != null) { | |
| 390 visit(element1.enclosingClass, element2.enclosingClass); | |
| 391 } else { | |
| 392 visit(element1.library, element2.library); | |
| 393 } | |
| 394 } | |
| 395 | |
| 396 @override | |
| 397 void visitFieldElement(FieldElement element1, FieldElement element2) { | |
| 398 checkMembers(element1, element2); | |
| 399 } | |
| 400 | |
| 401 @override | |
| 402 void visitFunctionElement(FunctionElement element1, | |
| 403 FunctionElement element2) { | |
| 404 checkMembers(element1, element2); | |
| 405 } | |
| 406 | |
| 407 void visitAbstractFieldElement(AbstractFieldElement element1, | |
| 408 AbstractFieldElement element2) { | |
| 409 checkMembers(element1, element2); | |
| 410 } | |
| 411 | |
| 412 @override | |
| 413 void visitTypeVariableElement(TypeVariableElement element1, | |
| 414 TypeVariableElement element2) { | |
| 415 check(element1, element2, | |
| 416 'name', | |
| 417 element1.name, element2.name); | |
| 418 visit(element1.typeDeclaration, element2.typeDeclaration); | |
| 419 } | |
| 420 | |
| 421 @override | |
| 422 void visitTypedefElement(TypedefElement element1, TypedefElement element2) { | |
| 423 check(element1, element2, | |
| 424 'name', | |
| 425 element1.name, element2.name); | |
| 426 visit(element1.library, element2.library); | |
| 427 } | |
| 428 | |
| 429 @override | |
| 430 void visitParameterElement(ParameterElement element1, | |
| 431 ParameterElement element2) { | |
| 432 check(element1, element2, | |
| 433 'name', | |
| 434 element1.name, element2.name); | |
| 435 visit(element1.functionDeclaration, element2.functionDeclaration); | |
| 436 } | |
| 437 | |
| 438 @override | |
| 439 void visitImportElement(ImportElement element1, ImportElement element2) { | |
| 440 visit(element1.importedLibrary, element2.importedLibrary); | |
| 441 visit(element1.library, element2.library); | |
| 442 } | |
| 443 | |
| 444 @override | |
| 445 void visitExportElement(ExportElement element1, ExportElement element2) { | |
| 446 visit(element1.exportedLibrary, element2.exportedLibrary); | |
| 447 visit(element1.library, element2.library); | |
| 448 } | |
| 449 | |
| 450 @override | |
| 451 void visitPrefixElement(PrefixElement element1, PrefixElement element2) { | |
| 452 check(element1, element2, | |
| 453 'name', | |
| 454 element1.name, element2.name); | |
| 455 visit(element1.library, element2.library); | |
| 456 } | |
| 457 } | 465 } |
| 458 | 466 |
| 459 /// Visitor that checks for equivalence of [Element] properties. | 467 /// Visitor that checks for equivalence of [Element] properties. |
| 460 class ElementPropertyEquivalence extends BaseElementVisitor<dynamic, Element> { | 468 class ElementPropertyEquivalence extends BaseElementVisitor<dynamic, Element> { |
| 461 const ElementPropertyEquivalence(); | 469 const ElementPropertyEquivalence(); |
| 462 | 470 |
| 463 void visit(Element element1, Element element2) { | 471 void visit(Element element1, Element element2) { |
| 464 if (element1 == null && element2 == null) return; | 472 if (element1 == null && element2 == null) return; |
| 465 element1 = element1.declaration; | 473 element1 = element1.declaration; |
| 466 element2 = element2.declaration; | 474 element2 = element2.declaration; |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 548 element1 = element1.implementation; | 556 element1 = element1.implementation; |
| 549 element2 = element2.implementation; | 557 element2 = element2.implementation; |
| 550 for (String name in names) { | 558 for (String name in names) { |
| 551 Element member1 = element1.localLookup(name); | 559 Element member1 = element1.localLookup(name); |
| 552 Element member2 = element2.localLookup(name); | 560 Element member2 = element2.localLookup(name); |
| 553 if (member1 == null) { | 561 if (member1 == null) { |
| 554 String message = | 562 String message = |
| 555 'Missing member for $member2 in\n ${members1.join('\n ')}'; | 563 'Missing member for $member2 in\n ${members1.join('\n ')}'; |
| 556 if (member2.isAbstractField) { | 564 if (member2.isAbstractField) { |
| 557 // TODO(johnniwinther): Ensure abstract fields are handled correctly. | 565 // TODO(johnniwinther): Ensure abstract fields are handled correctly. |
| 558 print(message); | 566 //print(message); |
| 559 continue; | 567 continue; |
| 560 } else { | 568 } else { |
| 561 throw message; | 569 throw message; |
| 562 } | 570 } |
| 563 } | 571 } |
| 564 if (member2 == null) { | 572 if (member2 == null) { |
| 565 String message = | 573 String message = |
| 566 'Missing member for $member1 in\n ${members2.join('\n ')}'; | 574 'Missing member for $member1 in\n ${members2.join('\n ')}'; |
| 567 if (member1.isAbstractField) { | 575 if (member1.isAbstractField) { |
| 568 // TODO(johnniwinther): Ensure abstract fields are handled correctly. | 576 // TODO(johnniwinther): Ensure abstract fields are handled correctly. |
| 569 print(message); | 577 //print(message); |
| 570 continue; | 578 continue; |
| 571 } else { | 579 } else { |
| 572 throw message; | 580 throw message; |
| 573 } | 581 } |
| 574 } | 582 } |
| 575 //print('Checking member ${member1} against ${member2}'); | 583 //print('Checking member ${member1} against ${member2}'); |
| 576 visit(member1, member2); | 584 visit(member1, member2); |
| 577 } | 585 } |
| 578 } | 586 } |
| 579 | 587 |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 857 void visitPrefixElement(PrefixElement element1, PrefixElement element2) { | 865 void visitPrefixElement(PrefixElement element1, PrefixElement element2) { |
| 858 check( | 866 check( |
| 859 element1, element2, 'isDeferred', | 867 element1, element2, 'isDeferred', |
| 860 element1.isDeferred, element2.isDeferred); | 868 element1.isDeferred, element2.isDeferred); |
| 861 checkElementIdentities( | 869 checkElementIdentities( |
| 862 element1, element2, 'importedLibrary', | 870 element1, element2, 'importedLibrary', |
| 863 element1.deferredImport, element2.deferredImport); | 871 element1.deferredImport, element2.deferredImport); |
| 864 // TODO(johnniwinther): Check members. | 872 // TODO(johnniwinther): Check members. |
| 865 } | 873 } |
| 866 } | 874 } |
| 867 | |
| 868 /// Visitor that checks for equivalence of [DartType]s. | |
| 869 class TypeEquivalence implements DartTypeVisitor<dynamic, DartType> { | |
| 870 const TypeEquivalence(); | |
| 871 | |
| 872 void visit(DartType type1, DartType type2) { | |
| 873 check(type1, type2, 'kind', type1.kind, type2.kind); | |
| 874 type1.accept(this, type2); | |
| 875 } | |
| 876 | |
| 877 @override | |
| 878 void visitDynamicType(DynamicType type, DynamicType other) { | |
| 879 } | |
| 880 | |
| 881 @override | |
| 882 void visitFunctionType(FunctionType type, FunctionType other) { | |
| 883 checkTypeLists( | |
| 884 type, other, 'parameterTypes', | |
| 885 type.parameterTypes, other.parameterTypes); | |
| 886 checkTypeLists( | |
| 887 type, other, 'optionalParameterTypes', | |
| 888 type.optionalParameterTypes, other.optionalParameterTypes); | |
| 889 checkTypeLists( | |
| 890 type, other, 'namedParameterTypes', | |
| 891 type.namedParameterTypes, other.namedParameterTypes); | |
| 892 for (int i = 0; i < type.namedParameters.length; i++) { | |
| 893 if (type.namedParameters[i] != other.namedParameters[i]) { | |
| 894 throw "Named parameter '$type.namedParameters[i]' <> " | |
| 895 "'${other.namedParameters[i]}'"; | |
| 896 } | |
| 897 } | |
| 898 } | |
| 899 | |
| 900 void visitGenericType(GenericType type, GenericType other) { | |
| 901 checkElementIdentities( | |
| 902 type, other, 'element', | |
| 903 type.element, other.element); | |
| 904 checkTypeLists( | |
| 905 type, other, 'typeArguments', | |
| 906 type.typeArguments, other.typeArguments); | |
| 907 } | |
| 908 | |
| 909 @override | |
| 910 void visitMalformedType(MalformedType type, MalformedType other) { | |
| 911 } | |
| 912 | |
| 913 @override | |
| 914 void visitStatementType(StatementType type, StatementType other) { | |
| 915 throw new UnsupportedError("Unsupported type: $type"); | |
| 916 } | |
| 917 | |
| 918 @override | |
| 919 void visitTypeVariableType(TypeVariableType type, TypeVariableType other) { | |
| 920 checkElementIdentities( | |
| 921 type, other, 'element', | |
| 922 type.element, other.element); | |
| 923 } | |
| 924 | |
| 925 @override | |
| 926 void visitVoidType(VoidType type, VoidType argument) { | |
| 927 } | |
| 928 | |
| 929 @override | |
| 930 void visitInterfaceType(InterfaceType type, InterfaceType other) { | |
| 931 visitGenericType(type, other); | |
| 932 } | |
| 933 | |
| 934 @override | |
| 935 void visitTypedefType(TypedefType type, TypedefType other) { | |
| 936 visitGenericType(type, other); | |
| 937 } | |
| 938 } | |
| 939 | |
| 940 /// Visitor that checks for structural equivalence of [ConstantExpression]s. | |
| 941 class ConstantEquivalence | |
| 942 implements ConstantExpressionVisitor<dynamic, ConstantExpression> { | |
| 943 const ConstantEquivalence(); | |
| 944 | |
| 945 @override | |
| 946 visit(ConstantExpression exp1, ConstantExpression exp2) { | |
| 947 if (identical(exp1, exp2)) return; | |
| 948 check(exp1, exp2, 'kind', exp1.kind, exp2.kind); | |
| 949 exp1.accept(this, exp2); | |
| 950 } | |
| 951 | |
| 952 @override | |
| 953 visitBinary(BinaryConstantExpression exp1, BinaryConstantExpression exp2) { | |
| 954 check(exp1, exp2, 'operator', exp1.operator, exp2.operator); | |
| 955 checkConstants(exp1, exp2, 'left', exp1.left, exp2.left); | |
| 956 checkConstants(exp1, exp2, 'right', exp1.right, exp2.right); | |
| 957 } | |
| 958 | |
| 959 @override | |
| 960 visitConcatenate(ConcatenateConstantExpression exp1, | |
| 961 ConcatenateConstantExpression exp2) { | |
| 962 checkConstantLists( | |
| 963 exp1, exp2, 'expressions', | |
| 964 exp1.expressions, exp2.expressions); | |
| 965 } | |
| 966 | |
| 967 @override | |
| 968 visitConditional(ConditionalConstantExpression exp1, | |
| 969 ConditionalConstantExpression exp2) { | |
| 970 checkConstants( | |
| 971 exp1, exp2, 'condition', exp1.condition, exp2.condition); | |
| 972 checkConstants(exp1, exp2, 'trueExp', exp1.trueExp, exp2.trueExp); | |
| 973 checkConstants(exp1, exp2, 'falseExp', exp1.falseExp, exp2.falseExp); | |
| 974 } | |
| 975 | |
| 976 @override | |
| 977 visitConstructed(ConstructedConstantExpression exp1, | |
| 978 ConstructedConstantExpression exp2) { | |
| 979 checkTypes( | |
| 980 exp1, exp2, 'type', | |
| 981 exp1.type, exp2.type); | |
| 982 checkElementIdentities( | |
| 983 exp1, exp2, 'target', | |
| 984 exp1.target, exp2.target); | |
| 985 checkConstantLists( | |
| 986 exp1, exp2, 'arguments', | |
| 987 exp1.arguments, exp2.arguments); | |
| 988 check(exp1, exp2, 'callStructure', exp1.callStructure, exp2.callStructure); | |
| 989 } | |
| 990 | |
| 991 @override | |
| 992 visitFunction(FunctionConstantExpression exp1, | |
| 993 FunctionConstantExpression exp2) { | |
| 994 checkElementIdentities( | |
| 995 exp1, exp2, 'element', | |
| 996 exp1.element, exp2.element); | |
| 997 } | |
| 998 | |
| 999 @override | |
| 1000 visitIdentical(IdenticalConstantExpression exp1, | |
| 1001 IdenticalConstantExpression exp2) { | |
| 1002 checkConstants(exp1, exp2, 'left', exp1.left, exp2.left); | |
| 1003 checkConstants(exp1, exp2, 'right', exp1.right, exp2.right); | |
| 1004 } | |
| 1005 | |
| 1006 @override | |
| 1007 visitList(ListConstantExpression exp1, ListConstantExpression exp2) { | |
| 1008 checkTypes( | |
| 1009 exp1, exp2, 'type', | |
| 1010 exp1.type, exp2.type); | |
| 1011 checkConstantLists( | |
| 1012 exp1, exp2, 'values', | |
| 1013 exp1.values, exp2.values); | |
| 1014 } | |
| 1015 | |
| 1016 @override | |
| 1017 visitMap(MapConstantExpression exp1, MapConstantExpression exp2) { | |
| 1018 checkTypes( | |
| 1019 exp1, exp2, 'type', | |
| 1020 exp1.type, exp2.type); | |
| 1021 checkConstantLists( | |
| 1022 exp1, exp2, 'keys', | |
| 1023 exp1.keys, exp2.keys); | |
| 1024 checkConstantLists( | |
| 1025 exp1, exp2, 'values', | |
| 1026 exp1.values, exp2.values); | |
| 1027 } | |
| 1028 | |
| 1029 @override | |
| 1030 visitNamed(NamedArgumentReference exp1, NamedArgumentReference exp2) { | |
| 1031 check(exp1, exp2, 'name', exp1.name, exp2.name); | |
| 1032 } | |
| 1033 | |
| 1034 @override | |
| 1035 visitPositional(PositionalArgumentReference exp1, | |
| 1036 PositionalArgumentReference exp2) { | |
| 1037 check(exp1, exp2, 'index', exp1.index, exp2.index); | |
| 1038 } | |
| 1039 | |
| 1040 @override | |
| 1041 visitSymbol(SymbolConstantExpression exp1, SymbolConstantExpression exp2) { | |
| 1042 // TODO: implement visitSymbol | |
| 1043 } | |
| 1044 | |
| 1045 @override | |
| 1046 visitType(TypeConstantExpression exp1, TypeConstantExpression exp2) { | |
| 1047 checkTypes( | |
| 1048 exp1, exp2, 'type', | |
| 1049 exp1.type, exp2.type); | |
| 1050 } | |
| 1051 | |
| 1052 @override | |
| 1053 visitUnary(UnaryConstantExpression exp1, UnaryConstantExpression exp2) { | |
| 1054 check(exp1, exp2, 'operator', exp1.operator, exp2.operator); | |
| 1055 checkConstants( | |
| 1056 exp1, exp2, 'expression', exp1.expression, exp2.expression); | |
| 1057 } | |
| 1058 | |
| 1059 @override | |
| 1060 visitVariable(VariableConstantExpression exp1, | |
| 1061 VariableConstantExpression exp2) { | |
| 1062 checkElementIdentities( | |
| 1063 exp1, exp2, 'element', | |
| 1064 exp1.element, exp2.element); | |
| 1065 } | |
| 1066 | |
| 1067 @override | |
| 1068 visitBool(BoolConstantExpression exp1, BoolConstantExpression exp2) { | |
| 1069 check(exp1, exp2, 'primitiveValue', | |
| 1070 exp1.primitiveValue, exp2.primitiveValue); | |
| 1071 } | |
| 1072 | |
| 1073 @override | |
| 1074 visitDouble(DoubleConstantExpression exp1, DoubleConstantExpression exp2) { | |
| 1075 check(exp1, exp2, 'primitiveValue', | |
| 1076 exp1.primitiveValue, exp2.primitiveValue); | |
| 1077 } | |
| 1078 | |
| 1079 @override | |
| 1080 visitInt(IntConstantExpression exp1, IntConstantExpression exp2) { | |
| 1081 check(exp1, exp2, 'primitiveValue', | |
| 1082 exp1.primitiveValue, exp2.primitiveValue); | |
| 1083 } | |
| 1084 | |
| 1085 @override | |
| 1086 visitNull(NullConstantExpression exp1, NullConstantExpression exp2) { | |
| 1087 // Do nothing. | |
| 1088 } | |
| 1089 | |
| 1090 @override | |
| 1091 visitString(StringConstantExpression exp1, StringConstantExpression exp2) { | |
| 1092 check(exp1, exp2, 'primitiveValue', | |
| 1093 exp1.primitiveValue, exp2.primitiveValue); | |
| 1094 } | |
| 1095 | |
| 1096 @override | |
| 1097 visitBoolFromEnvironment(BoolFromEnvironmentConstantExpression exp1, | |
| 1098 BoolFromEnvironmentConstantExpression exp2) { | |
| 1099 checkConstants(exp1, exp2, 'name', exp1.name, exp2.name); | |
| 1100 checkConstants( | |
| 1101 exp1, exp2, 'defaultValue', | |
| 1102 exp1.defaultValue, exp2.defaultValue); | |
| 1103 } | |
| 1104 | |
| 1105 @override | |
| 1106 visitIntFromEnvironment(IntFromEnvironmentConstantExpression exp1, | |
| 1107 IntFromEnvironmentConstantExpression exp2) { | |
| 1108 checkConstants(exp1, exp2, 'name', exp1.name, exp2.name); | |
| 1109 checkConstants( | |
| 1110 exp1, exp2, 'defaultValue', | |
| 1111 exp1.defaultValue, exp2.defaultValue); | |
| 1112 } | |
| 1113 | |
| 1114 @override | |
| 1115 visitStringFromEnvironment(StringFromEnvironmentConstantExpression exp1, | |
| 1116 StringFromEnvironmentConstantExpression exp2) { | |
| 1117 checkConstants(exp1, exp2, 'name', exp1.name, exp2.name); | |
| 1118 checkConstants( | |
| 1119 exp1, exp2, 'defaultValue', | |
| 1120 exp1.defaultValue, exp2.defaultValue); | |
| 1121 } | |
| 1122 | |
| 1123 @override | |
| 1124 visitStringLength(StringLengthConstantExpression exp1, | |
| 1125 StringLengthConstantExpression exp2) { | |
| 1126 checkConstants( | |
| 1127 exp1, exp2, 'expression', | |
| 1128 exp1.expression, exp2.expression); | |
| 1129 } | |
| 1130 | |
| 1131 @override | |
| 1132 visitDeferred(DeferredConstantExpression exp1, | |
| 1133 DeferredConstantExpression exp2) { | |
| 1134 // TODO: implement visitDeferred | |
| 1135 } | |
| 1136 } | |
| OLD | NEW |