| 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 |