| 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 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 * Extract the value of the field [fieldName] from the object reflected | 223 * Extract the value of the field [fieldName] from the object reflected |
| 224 * by [mirror]. | 224 * by [mirror]. |
| 225 */ | 225 */ |
| 226 // TODO(alanknight): The framework should be resilient if there are fields | 226 // TODO(alanknight): The framework should be resilient if there are fields |
| 227 // it expects that are missing, either for the case of de-serializing to a | 227 // it expects that are missing, either for the case of de-serializing to a |
| 228 // different definition, or for the case that tree-shaking has removed state. | 228 // different definition, or for the case that tree-shaking has removed state. |
| 229 // TODO(alanknight): This, and other places, rely on synchronous access to | 229 // TODO(alanknight): This, and other places, rely on synchronous access to |
| 230 // mirrors. Should be changed to use a synchronous API once one is available, | 230 // mirrors. Should be changed to use a synchronous API once one is available, |
| 231 // or to be async, but that would be extremely ugly. | 231 // or to be async, but that would be extremely ugly. |
| 232 _value(InstanceMirror mirror, _Field field) => field.valueIn(mirror); | 232 _value(InstanceMirror mirror, _Field field) => field.valueIn(mirror); |
| 233 | |
| 234 /** | |
| 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 | |
| 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. | |
| 239 * Or, in the special case of null, two nulls. | |
| 240 */ | |
| 241 pullStateFrom(Iterator stream) { | |
| 242 stream.moveNext(); | |
| 243 var dataLength = stream.current; | |
| 244 var ruleData = new List(); | |
| 245 for (var i = 0; i < dataLength; i++) { | |
| 246 var subList = new List(); | |
| 247 ruleData.add(subList); | |
| 248 for (var j = 0; j < fields.length; j++) { | |
| 249 stream.moveNext(); | |
| 250 var a = stream.current; | |
| 251 stream.moveNext(); | |
| 252 var b = stream.current; | |
| 253 if (!(a is int)) { | |
| 254 // This wasn't a reference, so just use the first object as a literal. | |
| 255 // particularly used for the case of null. | |
| 256 subList.add(a); | |
| 257 } else { | |
| 258 subList.add(new Reference(this, a, b)); | |
| 259 } | |
| 260 } | |
| 261 } | |
| 262 return ruleData; | |
| 263 } | |
| 264 } | 233 } |
| 265 | 234 |
| 266 /** | 235 /** |
| 267 * This represents a field in an object. It is intended to be used as part of | 236 * This represents a field in an object. It is intended to be used as part of |
| 268 * a [_FieldList]. | 237 * a [_FieldList]. |
| 269 */ | 238 */ |
| 270 abstract class _Field implements Comparable { | 239 abstract class _Field implements Comparable { |
| 271 | 240 |
| 272 /** The FieldList that contains us. */ | 241 /** The FieldList that contains us. */ |
| 273 final _FieldList fieldList; | 242 final _FieldList fieldList; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 * it is used in the constructor, or because it's been designated | 325 * it is used in the constructor, or because it's been designated |
| 357 * using [setFieldWith]. | 326 * using [setFieldWith]. |
| 358 */ | 327 */ |
| 359 bool get isEssential => super.isEssential || customSetter != null; | 328 bool get isEssential => super.isEssential || customSetter != null; |
| 360 | 329 |
| 361 /** Set the [value] of our field in the given mirrored [object]. */ | 330 /** Set the [value] of our field in the given mirrored [object]. */ |
| 362 void setValue(InstanceMirror object, value) { | 331 void setValue(InstanceMirror object, value) { |
| 363 setter(object, value); | 332 setter(object, value); |
| 364 } | 333 } |
| 365 | 334 |
| 366 valueIn(InstanceMirror mirror) { | 335 valueIn(InstanceMirror mirror) => |
| 367 var futureValue = deprecatedFutureValue(mirror.getField(name)); | 336 deprecatedFutureValue(mirror.getField(name)).reflectee; |
| 368 return futureValue.reflectee; | |
| 369 } | |
| 370 | 337 |
| 371 /** Return the function to use to set our value. */ | 338 /** Return the function to use to set our value. */ |
| 372 Function get setter => | 339 Function get setter => |
| 373 (customSetter != null) ? customSetter : defaultSetter; | 340 (customSetter != null) ? customSetter : defaultSetter; |
| 374 | 341 |
| 375 /** Return a default setter function. */ | 342 /** Return a default setter function. */ |
| 376 void defaultSetter(InstanceMirror object, value) { | 343 void defaultSetter(InstanceMirror object, value) { |
| 377 object.setField(name, reflect(value)); | 344 object.setField(name, reflect(value)); |
| 378 } | 345 } |
| 379 | 346 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 468 if (fields == null || fields.isEmpty) return; | 435 if (fields == null || fields.isEmpty) return; |
| 469 if (allFields.length > _constructorFields.length) { | 436 if (allFields.length > _constructorFields.length) { |
| 470 throw "You can't specify both excludeFields and regular fields"; | 437 throw "You can't specify both excludeFields and regular fields"; |
| 471 } | 438 } |
| 472 _excludeFields = fields; | 439 _excludeFields = fields; |
| 473 } | 440 } |
| 474 | 441 |
| 475 int get length => allFields.length; | 442 int get length => allFields.length; |
| 476 | 443 |
| 477 /** Add all the fields which aren't on the exclude list. */ | 444 /** Add all the fields which aren't on the exclude list. */ |
| 478 void addAllNotExplicitlyExcluded(List<String> aCollection) { | 445 void addAllNotExplicitlyExcluded(Iterable<String> aCollection) { |
| 479 if (aCollection == null) return; | 446 if (aCollection == null) return; |
| 480 var names = aCollection; | 447 var names = aCollection; |
| 481 names = names.where((x) => !_excludeFields.contains(x)); | 448 names = names.where((x) => !_excludeFields.contains(x)); |
| 482 addAllByName(names); | 449 addAllByName(names); |
| 483 } | 450 } |
| 484 | 451 |
| 485 /** Add all the fields with the given names without any special properties. */ | 452 /** Add all the fields with the given names without any special properties. */ |
| 486 void addAllByName(Iterable<String> names) { | 453 void addAllByName(Iterable<String> names) { |
| 487 for (var each in names) { | 454 for (var each in names) { |
| 488 allFields.putIfAbsent(each, () => new _Field(each, this)); | 455 allFields.putIfAbsent(each, () => new _Field(each, this)); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 527 f(each); | 494 f(each); |
| 528 } | 495 } |
| 529 } | 496 } |
| 530 } | 497 } |
| 531 | 498 |
| 532 List get constructorFields => _constructorFields; | 499 List get constructorFields => _constructorFields; |
| 533 List constructorFieldNames() => | 500 List constructorFieldNames() => |
| 534 constructorFields.mappedBy((x) => x.name).toList(); | 501 constructorFields.mappedBy((x) => x.name).toList(); |
| 535 List constructorFieldIndices() => | 502 List constructorFieldIndices() => |
| 536 constructorFields.mappedBy((x) => x.index).toList(); | 503 constructorFields.mappedBy((x) => x.index).toList(); |
| 537 List regularFields() => | 504 List regularFields() => contents.where((x) => !x.usedInConstructor).toList(); |
| 538 contents.where((x) => !x.usedInConstructor).toList(); | 505 List regularFieldNames() => regularFields().mappedBy((x) => x.name).toList(); |
| 539 List regularFieldNames() => | |
| 540 regularFields().mappedBy((x) => x.name).toList(); | |
| 541 List regularFieldIndices() => | 506 List regularFieldIndices() => |
| 542 regularFields().mappedBy((x) => x.index).toList(); | 507 regularFields().mappedBy((x) => x.index).toList(); |
| 543 | 508 |
| 544 | |
| 545 /** | 509 /** |
| 546 * If we weren't given any non-constructor fields to use, figure out what | 510 * If we weren't given any non-constructor fields to use, figure out what |
| 547 * we think they ought to be, based on the class definition. | 511 * we think they ought to be, based on the class definition. |
| 548 * We find public fields, getters that have corresponding setters, and getters | 512 * We find public fields, getters that have corresponding setters, and getters |
| 549 * that are listed in the constructor fields. | 513 * that are listed in the constructor fields. |
| 550 */ | 514 */ |
| 551 void figureOutFields() { | 515 void figureOutFields() { |
| 552 List names(Collection<DeclarationMirror> mirrors) => | 516 Iterable names(Iterable<DeclarationMirror> mirrors) => |
| 553 mirrors.mappedBy((each) => each.simpleName).toList(); | 517 mirrors.mappedBy((each) => each.simpleName); |
| 554 | 518 |
| 555 if (!_shouldFigureOutFields || !regularFields().isEmpty) return; | 519 if (!_shouldFigureOutFields || !regularFields().isEmpty) return; |
| 556 var fields = publicFields(mirror); | 520 var fields = publicFields(mirror); |
| 557 var getters = publicGetters(mirror); | 521 var getters = publicGetters(mirror); |
| 558 var gettersWithSetters = getters.where( (each) | 522 var gettersWithSetters = getters.where( (each) |
| 559 => mirror.setters["${each.simpleName}="] != null).toList(); | 523 => mirror.setters["${each.simpleName}="] != null); |
| 560 var gettersThatMatchConstructor = getters.where((each) | 524 var gettersThatMatchConstructor = getters.where((each) |
| 561 => (named(each.simpleName) != null) && | 525 => (named(each.simpleName) != null) && |
| 562 (named(each.simpleName).usedInConstructor)).toList(); | 526 (named(each.simpleName).usedInConstructor)).toList(); |
| 563 addAllNotExplicitlyExcluded(names(fields)); | 527 addAllNotExplicitlyExcluded(names(fields)); |
| 564 addAllNotExplicitlyExcluded(names(gettersWithSetters)); | 528 addAllNotExplicitlyExcluded(names(gettersWithSetters)); |
| 565 addAllNotExplicitlyExcluded(names(gettersThatMatchConstructor)); | 529 addAllNotExplicitlyExcluded(names(gettersThatMatchConstructor)); |
| 566 } | 530 } |
| 567 } | 531 } |
| 568 | 532 |
| 569 /** | 533 /** |
| (...skipping 30 matching lines...) Expand all Loading... |
| 600 } | 564 } |
| 601 | 565 |
| 602 /** | 566 /** |
| 603 * Find the field values in [state] and pass them to the constructor. | 567 * Find the field values in [state] and pass them to the constructor. |
| 604 * If any of [fieldNumbers] is not an int, then use it as a literal value. | 568 * If any of [fieldNumbers] is not an int, then use it as a literal value. |
| 605 */ | 569 */ |
| 606 constructFrom(state, Reader r) { | 570 constructFrom(state, Reader r) { |
| 607 // TODO(alanknight): Handle named parameters | 571 // TODO(alanknight): Handle named parameters |
| 608 Collection inflated = fieldNumbers.mappedBy( | 572 Collection inflated = fieldNumbers.mappedBy( |
| 609 (x) => (x is int) ? reflect(r.inflateReference(state[x])) : reflect(x)) | 573 (x) => (x is int) ? reflect(r.inflateReference(state[x])) : reflect(x)) |
| 610 .toList(); | 574 .toList(); |
| 611 var result = type.newInstance(name, inflated); | 575 var result = type.newInstance(name, inflated); |
| 612 return deprecatedFutureValue(result); | 576 return deprecatedFutureValue(result); |
| 613 } | 577 } |
| 614 } | 578 } |
| 615 | 579 |
| 616 /** | 580 /** |
| 617 * This wraps a map to make it indexable by integer field numbers. It translates | 581 * This wraps a map to make it indexable by integer field numbers. It translates |
| 618 * from the index into a field name and then looks it up in the map. | 582 * from the index into a field name and then looks it up in the map. |
| 619 */ | 583 */ |
| 620 class _MapWrapper { | 584 class _MapWrapper { |
| 621 Map<String, dynamic> _map = new Map<String, dynamic>(); | 585 Map<String, dynamic> _map = new Map<String, dynamic>(); |
| 622 List fieldList; | 586 List fieldList; |
| 623 _MapWrapper(this.fieldList); | 587 _MapWrapper(this.fieldList); |
| 624 _MapWrapper.fromMap(this._map, this.fieldList); | 588 _MapWrapper.fromMap(this._map, this.fieldList); |
| 625 | 589 |
| 626 operator [](key) => _map[fieldList[key].name]; | 590 operator [](key) => _map[fieldList[key].name]; |
| 627 operator []=(key, value) { _map[fieldList[key].name] = value; } | 591 operator []=(key, value) { _map[fieldList[key].name] = value; } |
| 628 get length => _map.length; | 592 get length => _map.length; |
| 629 | 593 |
| 630 asMap() => _map; | 594 asMap() => _map; |
| 631 } | 595 } |
| OLD | NEW |