OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 part of serialization; | 5 part of serialization; |
6 | 6 |
7 // TODO(alanknight): Figure out how to reasonably separate out the things | 7 // TODO(alanknight): Figure out how to reasonably separate out the things |
8 // that require reflection without making the API more awkward. Or if that is | 8 // that require reflection without making the API more awkward. Or if that is |
9 // in fact necessary. Maybe the tree-shaking will just remove it if unused. | 9 // in fact necessary. Maybe the tree-shaking will just remove it if unused. |
10 | 10 |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 _value(InstanceMirror mirror, _Field field) => field.valueIn(mirror); | 232 _value(InstanceMirror mirror, _Field field) => field.valueIn(mirror); |
233 | 233 |
234 /** | 234 /** |
235 * When reading from a flat format we are given [stream] and need to pull as | 235 * When reading from a flat format we are given [stream] and need to pull as |
236 * much data from it as we need. Our format is that we have an integer N | 236 * much data from it as we need. Our format is that we have an integer N |
237 * indicating the number of objects and then for each object N fields, which | 237 * indicating the number of objects and then for each object N fields, which |
238 * are references, where a reference is stored in the stream as two integers. | 238 * are references, where a reference is stored in the stream as two integers. |
239 * Or, in the special case of null, two nulls. | 239 * Or, in the special case of null, two nulls. |
240 */ | 240 */ |
241 pullStateFrom(Iterator stream) { | 241 pullStateFrom(Iterator stream) { |
242 var dataLength = stream.next(); | 242 stream.moveNext(); |
| 243 var dataLength = stream.current; |
243 var ruleData = new List(); | 244 var ruleData = new List(); |
244 for (var i = 0; i < dataLength; i++) { | 245 for (var i = 0; i < dataLength; i++) { |
245 var subList = new List(); | 246 var subList = new List(); |
246 ruleData.add(subList); | 247 ruleData.add(subList); |
247 for (var j = 0; j < fields.length; j++) { | 248 for (var j = 0; j < fields.length; j++) { |
248 var a = stream.next(); | 249 stream.moveNext(); |
249 var b = stream.next(); | 250 var a = stream.current; |
| 251 stream.moveNext(); |
| 252 var b = stream.current; |
250 if (!(a is int)) { | 253 if (!(a is int)) { |
251 // This wasn't a reference, so just use the first object as a literal. | 254 // This wasn't a reference, so just use the first object as a literal. |
252 // particularly used for the case of null. | 255 // particularly used for the case of null. |
253 subList.add(a); | 256 subList.add(a); |
254 } else { | 257 } else { |
255 subList.add(new Reference(this, a, b)); | 258 subList.add(new Reference(this, a, b)); |
256 } | 259 } |
257 } | 260 } |
258 } | 261 } |
259 return ruleData; | 262 return ruleData; |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
353 * it is used in the constructor, or because it's been designated | 356 * it is used in the constructor, or because it's been designated |
354 * using [setFieldWith]. | 357 * using [setFieldWith]. |
355 */ | 358 */ |
356 bool get isEssential => super.isEssential || customSetter != null; | 359 bool get isEssential => super.isEssential || customSetter != null; |
357 | 360 |
358 /** Set the [value] of our field in the given mirrored [object]. */ | 361 /** Set the [value] of our field in the given mirrored [object]. */ |
359 void setValue(InstanceMirror object, value) { | 362 void setValue(InstanceMirror object, value) { |
360 setter(object, value); | 363 setter(object, value); |
361 } | 364 } |
362 | 365 |
363 valueIn(InstanceMirror mirror) => mirror.getField(name).value.reflectee; | 366 valueIn(InstanceMirror mirror) { |
| 367 var futureValue = deprecatedFutureValue(mirror.getField(name)); |
| 368 return futureValue.reflectee; |
| 369 } |
364 | 370 |
365 /** Return the function to use to set our value. */ | 371 /** Return the function to use to set our value. */ |
366 Function get setter => | 372 Function get setter => |
367 (customSetter != null) ? customSetter : defaultSetter; | 373 (customSetter != null) ? customSetter : defaultSetter; |
368 | 374 |
369 /** Return a default setter function. */ | 375 /** Return a default setter function. */ |
370 void defaultSetter(InstanceMirror object, value) { | 376 void defaultSetter(InstanceMirror object, value) { |
371 object.setField(name, reflect(value)); | 377 object.setField(name, reflect(value)); |
372 } | 378 } |
373 | 379 |
(...skipping 23 matching lines...) Expand all Loading... |
397 * use the value for that. | 403 * use the value for that. |
398 */ | 404 */ |
399 get name => value; | 405 get name => value; |
400 } | 406 } |
401 | 407 |
402 /** | 408 /** |
403 * The organization of fields in an object can be reasonably complex, so they | 409 * The organization of fields in an object can be reasonably complex, so they |
404 * are kept in a separate object, which also has the ability to compute the | 410 * are kept in a separate object, which also has the ability to compute the |
405 * default fields to use reflectively. | 411 * default fields to use reflectively. |
406 */ | 412 */ |
407 class _FieldList implements Iterable { | 413 class _FieldList extends Iterable { |
408 /** | 414 /** |
409 * All of our fields, indexed by name. Note that the names are not | 415 * All of our fields, indexed by name. Note that the names are not |
410 * necessarily strings. | 416 * necessarily strings. |
411 */ | 417 */ |
412 Map<dynamic, _Field> allFields = new Map<dynamic, _Field>(); | 418 Map<dynamic, _Field> allFields = new Map<dynamic, _Field>(); |
413 | 419 |
414 /** | 420 /** |
415 * The fields which are used in the constructor. The fields themselves also | 421 * The fields which are used in the constructor. The fields themselves also |
416 * know if they are constructor fields or not, but we need to keep this | 422 * know if they are constructor fields or not, but we need to keep this |
417 * information here because the order matters. | 423 * information here because the order matters. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
465 } | 471 } |
466 _excludeFields = fields; | 472 _excludeFields = fields; |
467 } | 473 } |
468 | 474 |
469 int get length => allFields.length; | 475 int get length => allFields.length; |
470 | 476 |
471 /** Add all the fields which aren't on the exclude list. */ | 477 /** Add all the fields which aren't on the exclude list. */ |
472 void addAllNotExplicitlyExcluded(List<String> aCollection) { | 478 void addAllNotExplicitlyExcluded(List<String> aCollection) { |
473 if (aCollection == null) return; | 479 if (aCollection == null) return; |
474 var names = aCollection; | 480 var names = aCollection; |
475 names = names.filter((x) => !_excludeFields.contains(x)); | 481 names = names.where((x) => !_excludeFields.contains(x)); |
476 addAllByName(names); | 482 addAllByName(names); |
477 } | 483 } |
478 | 484 |
479 /** Add all the fields with the given names without any special properties. */ | 485 /** Add all the fields with the given names without any special properties. */ |
480 void addAllByName(List<String> names) { | 486 void addAllByName(Iterable<String> names) { |
481 for (var each in names) { | 487 for (var each in names) { |
482 allFields.putIfAbsent(each, () => new _Field(each, this)); | 488 allFields.putIfAbsent(each, () => new _Field(each, this)); |
483 } | 489 } |
484 invalidate(); | 490 invalidate(); |
485 } | 491 } |
486 | 492 |
487 /** | 493 /** |
488 * Fields have been added. In case we had already forced calculation of the | 494 * Fields have been added. In case we had already forced calculation of the |
489 * list of contents, re-set it. | 495 * list of contents, re-set it. |
490 */ | 496 */ |
491 void invalidate() { | 497 void invalidate() { |
492 _contents = null; | 498 _contents = null; |
493 contents; | 499 contents; |
494 } | 500 } |
495 | 501 |
496 Iterator iterator() => contents.iterator(); | 502 Iterator get iterator => contents.iterator; |
497 | 503 |
498 /** Return a cached, sorted list of all the fields. */ | 504 /** Return a cached, sorted list of all the fields. */ |
499 List<_Field> get contents { | 505 List<_Field> get contents { |
500 if (_contents == null) { | 506 if (_contents == null) { |
501 _contents = sorted(allFields.values); | 507 _contents = sorted(allFields.values); |
502 for (var i = 0; i < _contents.length; i++) | 508 for (var i = 0; i < _contents.length; i++) |
503 _contents[i].index = i; | 509 _contents[i].index = i; |
504 } | 510 } |
505 return _contents; | 511 return _contents; |
506 } | 512 } |
(...skipping 10 matching lines...) Expand all Loading... |
517 /** Iterate over the fields used in the constructor. */ | 523 /** Iterate over the fields used in the constructor. */ |
518 void forEachConstructorField(Function f) { | 524 void forEachConstructorField(Function f) { |
519 for (var each in contents) { | 525 for (var each in contents) { |
520 if (each.usedInConstructor) { | 526 if (each.usedInConstructor) { |
521 f(each); | 527 f(each); |
522 } | 528 } |
523 } | 529 } |
524 } | 530 } |
525 | 531 |
526 List get constructorFields => _constructorFields; | 532 List get constructorFields => _constructorFields; |
527 List constructorFieldNames() => constructorFields.map((x) => x.name); | 533 List constructorFieldNames() => |
528 List constructorFieldIndices() => constructorFields.map((x) => x.index); | 534 constructorFields.mappedBy((x) => x.name).toList(); |
529 List regularFields() => contents.filter((x) => !x.usedInConstructor); | 535 List constructorFieldIndices() => |
530 List regularFieldNames() => regularFields().map((x) => x.name); | 536 constructorFields.mappedBy((x) => x.index).toList(); |
531 List regularFieldIndices() => regularFields().map((x) => x.index); | 537 List regularFields() => |
| 538 contents.where((x) => !x.usedInConstructor).toList(); |
| 539 List regularFieldNames() => |
| 540 regularFields().mappedBy((x) => x.name).toList(); |
| 541 List regularFieldIndices() => |
| 542 regularFields().mappedBy((x) => x.index).toList(); |
532 | 543 |
533 | 544 |
534 /** | 545 /** |
535 * If we weren't given any non-constructor fields to use, figure out what | 546 * If we weren't given any non-constructor fields to use, figure out what |
536 * we think they ought to be, based on the class definition. | 547 * we think they ought to be, based on the class definition. |
537 * We find public fields, getters that have corresponding setters, and getters | 548 * We find public fields, getters that have corresponding setters, and getters |
538 * that are listed in the constructor fields. | 549 * that are listed in the constructor fields. |
539 */ | 550 */ |
540 void figureOutFields() { | 551 void figureOutFields() { |
541 List names(Collection<DeclarationMirror> mirrors) => | 552 List names(Collection<DeclarationMirror> mirrors) => |
542 mirrors.map((each) => each.simpleName); | 553 mirrors.mappedBy((each) => each.simpleName).toList(); |
543 | 554 |
544 if (!_shouldFigureOutFields || !regularFields().isEmpty) return; | 555 if (!_shouldFigureOutFields || !regularFields().isEmpty) return; |
545 var fields = publicFields(mirror); | 556 var fields = publicFields(mirror); |
546 var getters = publicGetters(mirror); | 557 var getters = publicGetters(mirror); |
547 var gettersWithSetters = getters.filter( (each) | 558 var gettersWithSetters = getters.where( (each) |
548 => mirror.setters["${each.simpleName}="] != null); | 559 => mirror.setters["${each.simpleName}="] != null).toList(); |
549 var gettersThatMatchConstructor = getters.filter((each) | 560 var gettersThatMatchConstructor = getters.where((each) |
550 => (named(each.simpleName) != null) && | 561 => (named(each.simpleName) != null) && |
551 (named(each.simpleName).usedInConstructor)); | 562 (named(each.simpleName).usedInConstructor)).toList(); |
552 addAllNotExplicitlyExcluded(names(fields)); | 563 addAllNotExplicitlyExcluded(names(fields)); |
553 addAllNotExplicitlyExcluded(names(gettersWithSetters)); | 564 addAllNotExplicitlyExcluded(names(gettersWithSetters)); |
554 addAllNotExplicitlyExcluded(names(gettersThatMatchConstructor)); | 565 addAllNotExplicitlyExcluded(names(gettersThatMatchConstructor)); |
555 } | 566 } |
556 } | 567 } |
557 | 568 |
558 /** | 569 /** |
559 * Provide a typedef for the setWith argument to setFieldWith. It would | 570 * Provide a typedef for the setWith argument to setFieldWith. It would |
560 * be nice if we could put this closer to the definition. | 571 * be nice if we could put this closer to the definition. |
561 */ | 572 */ |
(...skipping 25 matching lines...) Expand all Loading... |
587 if (name == null) name = ''; | 598 if (name == null) name = ''; |
588 if (fieldNumbers == null) fieldNumbers = const []; | 599 if (fieldNumbers == null) fieldNumbers = const []; |
589 } | 600 } |
590 | 601 |
591 /** | 602 /** |
592 * Find the field values in [state] and pass them to the constructor. | 603 * Find the field values in [state] and pass them to the constructor. |
593 * If any of [fieldNumbers] is not an int, then use it as a literal value. | 604 * If any of [fieldNumbers] is not an int, then use it as a literal value. |
594 */ | 605 */ |
595 constructFrom(state, Reader r) { | 606 constructFrom(state, Reader r) { |
596 // TODO(alanknight): Handle named parameters | 607 // TODO(alanknight): Handle named parameters |
597 Collection inflated = fieldNumbers.map( | 608 Collection inflated = fieldNumbers.mappedBy( |
598 (x) => (x is int) ? reflect(r.inflateReference(state[x])) : reflect(x)); | 609 (x) => (x is int) ? reflect(r.inflateReference(state[x])) : reflect(x)) |
| 610 .toList(); |
599 var result = type.newInstance(name, inflated); | 611 var result = type.newInstance(name, inflated); |
600 return result.value; | 612 return deprecatedFutureValue(result); |
601 } | 613 } |
602 } | 614 } |
603 | 615 |
604 /** | 616 /** |
605 * This wraps a map to make it indexable by integer field numbers. It translates | 617 * This wraps a map to make it indexable by integer field numbers. It translates |
606 * from the index into a field name and then looks it up in the map. | 618 * from the index into a field name and then looks it up in the map. |
607 */ | 619 */ |
608 class _MapWrapper { | 620 class _MapWrapper { |
609 Map<String, dynamic> _map = new Map<String, dynamic>(); | 621 Map<String, dynamic> _map = new Map<String, dynamic>(); |
610 List fieldList; | 622 List fieldList; |
611 _MapWrapper(this.fieldList); | 623 _MapWrapper(this.fieldList); |
612 _MapWrapper.fromMap(this._map, this.fieldList); | 624 _MapWrapper.fromMap(this._map, this.fieldList); |
613 | 625 |
614 operator [](key) => _map[fieldList[key].name]; | 626 operator [](key) => _map[fieldList[key].name]; |
615 operator []=(key, value) { _map[fieldList[key].name] = value; } | 627 operator []=(key, value) { _map[fieldList[key].name] = value; } |
616 get length => _map.length; | 628 get length => _map.length; |
617 | 629 |
618 asMap() => _map; | 630 asMap() => _map; |
619 } | 631 } |
OLD | NEW |