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 |