Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // (c) 2015, the Dart Team. All rights reserved. Use of this | 1 // (c) 2015, the Dart Team. All rights reserved. Use of this |
| 2 // source code is governed by a BSD-style license that can be found in | 2 // source code is governed by a BSD-style license that can be found in |
| 3 // the LICENSE file. | 3 // the LICENSE file. |
| 4 | 4 |
| 5 library reflectable.src.transformer_implementation; | 5 library reflectable.src.transformer_implementation; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:convert'; | 8 import 'dart:convert'; |
| 9 import 'dart:io'; | 9 import 'dart:io'; |
| 10 import 'package:analyzer/src/generated/ast.dart'; | 10 import 'package:analyzer/src/generated/ast.dart'; |
| (...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 518 String _constConstructionCode(_ImportCollector importCollector) { | 518 String _constConstructionCode(_ImportCollector importCollector) { |
| 519 String prefix = importCollector._getPrefix(_reflector.library); | 519 String prefix = importCollector._getPrefix(_reflector.library); |
| 520 return "const $prefix.${_reflector.name}()"; | 520 return "const $prefix.${_reflector.name}()"; |
| 521 } | 521 } |
| 522 | 522 |
| 523 /// Generate the code which will create a `ReflectorData` instance | 523 /// Generate the code which will create a `ReflectorData` instance |
| 524 /// containing the mirrors and other reflection data which is needed for | 524 /// containing the mirrors and other reflection data which is needed for |
| 525 /// `_reflector` to behave correctly. | 525 /// `_reflector` to behave correctly. |
| 526 String _generateCode( | 526 String _generateCode( |
| 527 _ImportCollector importCollector, TransformLogger logger) { | 527 _ImportCollector importCollector, TransformLogger logger) { |
| 528 Enumerator<ExecutableElement> members = new Enumerator<ExecutableElement>(); | 528 // Library related collections. |
| 529 Enumerator<_LibraryDomain> libraries = new Enumerator<_LibraryDomain>(); | |
| 530 Map<LibraryElement, _LibraryDomain> libraryMap = | |
| 531 <LibraryElement, _LibraryDomain>{}; | |
| 532 Enumerator<TopLevelVariableElement> topLevelVariables = | |
| 533 new Enumerator<TopLevelVariableElement>(); | |
| 534 | |
| 535 // Class related collections. | |
| 529 Enumerator<FieldElement> fields = new Enumerator<FieldElement>(); | 536 Enumerator<FieldElement> fields = new Enumerator<FieldElement>(); |
| 530 Enumerator<ParameterElement> parameters = | 537 Enumerator<ParameterElement> parameters = |
| 531 new Enumerator<ParameterElement>(); | 538 new Enumerator<ParameterElement>(); |
| 532 Enumerator<LibraryElement> libraries = new Enumerator<LibraryElement>(); | |
| 533 Set<String> instanceGetterNames = new Set<String>(); | 539 Set<String> instanceGetterNames = new Set<String>(); |
| 534 Set<String> instanceSetterNames = new Set<String>(); | 540 Set<String> instanceSetterNames = new Set<String>(); |
| 535 | 541 |
| 542 // Library and class related collections. | |
| 543 Enumerator<ExecutableElement> members = new Enumerator<ExecutableElement>(); | |
| 544 | |
| 536 // Fill in [libraries], [members], [fields], [parameters], | 545 // Fill in [libraries], [members], [fields], [parameters], |
| 537 // [instanceGetterNames], and [instanceSetterNames]. | 546 // [instanceGetterNames], and [instanceSetterNames]. |
| 538 for (LibraryElement library in _libraries) { | 547 for (LibraryElement library in _libraries) { |
| 539 libraries.add(library); | 548 _LibraryDomain libraryDomain = _createLibraryDomain(library, this); |
| 549 libraries.add(libraryDomain); | |
| 550 libraryMap[library] = libraryDomain; | |
| 551 libraryDomain._declarations.forEach(members.add); | |
| 552 libraryDomain._declaredParameters.forEach(parameters.add); | |
| 553 libraryDomain._declaredVariables.forEach(topLevelVariables.add); | |
| 540 } | 554 } |
| 541 for (_ClassDomain classDomain in classes.domains) { | 555 for (_ClassDomain classDomain in classes.domains) { |
| 542 // Gather the behavioral interface into [members]. Note that | 556 // Gather the behavioral interface into [members]. Note that |
| 543 // this includes implicitly generated getters and setters, but | 557 // this includes implicitly generated getters and setters, but |
| 544 // omits fields. Also note that this does not match the | 558 // omits fields. Also note that this does not match the |
| 545 // semantics of the `declarations` method in a [ClassMirror]. | 559 // semantics of the `declarations` method in a [ClassMirror]. |
| 546 classDomain._declarations.forEach(members.add); | 560 classDomain._declarations.forEach(members.add); |
| 547 | 561 |
| 548 // Add the behavioral interface from this class (redundantly, for | 562 // Add the behavioral interface from this class (redundantly, for |
| 549 // non-static members) and all superclasses (which matters) to | 563 // non-static members) and all superclasses (which matters) to |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 581 instanceGetterNames.add(instanceMember.name); | 595 instanceGetterNames.add(instanceMember.name); |
| 582 } else { | 596 } else { |
| 583 // `instanceMember` is a ConstructorElement. | 597 // `instanceMember` is a ConstructorElement. |
| 584 // Even though a generative constructor has a false | 598 // Even though a generative constructor has a false |
| 585 // `isStatic`, we do not wish to include them among | 599 // `isStatic`, we do not wish to include them among |
| 586 // instanceGetterNames, so we do nothing here. | 600 // instanceGetterNames, so we do nothing here. |
| 587 } | 601 } |
| 588 }); | 602 }); |
| 589 } | 603 } |
| 590 | 604 |
| 605 // Find the offsets of fields and of methods and functions in members. | |
| 606 int fieldsOffset = topLevelVariables.length; | |
| 607 int methodsOffset = fieldsOffset + fields.length; | |
| 608 | |
| 591 // Generate code for creation of class mirrors. | 609 // Generate code for creation of class mirrors. |
| 592 String classMirrorsCode = _formatAsList( | 610 String classMirrorsCode = _formatAsList( |
| 593 "m.ClassMirror", | 611 "m.ClassMirror", |
| 594 _capabilities._impliesTypes | 612 _capabilities._impliesTypes |
| 595 ? classes.domains.map((_ClassDomain classDomain) => | 613 ? classes.domains.map((_ClassDomain classDomain) => |
| 596 _classMirrorCode(classDomain, fields, members, libraries, | 614 _classMirrorCode( |
| 597 importCollector, logger)) | 615 classDomain, |
| 616 fields, | |
| 617 fieldsOffset, | |
| 618 methodsOffset, | |
| 619 members, | |
| 620 libraries, | |
| 621 libraryMap, | |
| 622 importCollector, | |
| 623 logger)) | |
| 598 : <String>[]); | 624 : <String>[]); |
| 599 | 625 |
| 600 // Generate code for creation of getter and setter closures. | 626 // Generate code for creation of getter and setter closures. |
| 601 String gettersCode = _formatAsMap(instanceGetterNames.map(_gettingClosure)); | 627 String gettersCode = _formatAsMap(instanceGetterNames.map(_gettingClosure)); |
| 602 String settersCode = _formatAsMap(instanceSetterNames.map(_settingClosure)); | 628 String settersCode = _formatAsMap(instanceSetterNames.map(_settingClosure)); |
| 603 | 629 |
| 604 bool reflectedTypeRequested = _capabilities._impliesReflectedType; | 630 bool reflectedTypeRequested = _capabilities._impliesReflectedType; |
| 605 | 631 |
| 606 // Generate code for creation of member mirrors. | 632 // Generate code for creation of member mirrors. |
| 607 Iterable<String> methodsList = | 633 Iterable<String> methodsList = |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 623 _formatAsList("Type", classes.map((ClassElement classElement) { | 649 _formatAsList("Type", classes.map((ClassElement classElement) { |
| 624 return _typeCodeOfClass(classElement, importCollector); | 650 return _typeCodeOfClass(classElement, importCollector); |
| 625 })); | 651 })); |
| 626 | 652 |
| 627 // Generate code for creation of library mirrors. | 653 // Generate code for creation of library mirrors. |
| 628 String librariesCode; | 654 String librariesCode; |
| 629 if (!_capabilities.supportsLibraries) { | 655 if (!_capabilities.supportsLibraries) { |
| 630 librariesCode = "null"; | 656 librariesCode = "null"; |
| 631 } else { | 657 } else { |
| 632 librariesCode = _formatAsList("m.LibraryMirror", | 658 librariesCode = _formatAsList("m.LibraryMirror", |
| 633 libraries.items.map((LibraryElement library) { | 659 libraries.items.map((_LibraryDomain library) { |
| 634 return _libraryMirrorCode(library, importCollector, logger); | 660 return _libraryMirrorCode(library, members, topLevelVariables, |
| 661 fields.length, importCollector, logger); | |
| 635 })); | 662 })); |
| 636 } | 663 } |
| 637 | 664 |
| 638 // Generate code for creation of parameter mirrors. | 665 // Generate code for creation of parameter mirrors. |
| 639 Iterable<String> parametersList = | 666 Iterable<String> parametersList = |
| 640 parameters.items.map((ParameterElement element) { | 667 parameters.items.map((ParameterElement element) { |
| 641 return _parameterMirrorCode(element, fields, members, importCollector, | 668 return _parameterMirrorCode(element, fields, members, importCollector, |
| 642 logger, reflectedTypeRequested); | 669 logger, reflectedTypeRequested); |
| 643 }); | 670 }); |
| 644 String parameterMirrorsCode = | 671 String parameterMirrorsCode = |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 684 descriptor & constants.dynamicReturnTypeAttribute != 0, | 711 descriptor & constants.dynamicReturnTypeAttribute != 0, |
| 685 descriptor & constants.classReturnTypeAttribute != 0); | 712 descriptor & constants.classReturnTypeAttribute != 0); |
| 686 return result; | 713 return result; |
| 687 } | 714 } |
| 688 | 715 |
| 689 Iterable<PropertyAccessorElement> _gettersOfLibrary(LibraryElement library) { | 716 Iterable<PropertyAccessorElement> _gettersOfLibrary(LibraryElement library) { |
| 690 return library.units.map((CompilationUnitElement part) { | 717 return library.units.map((CompilationUnitElement part) { |
| 691 Iterable<Element> getters = <Iterable<Element>>[ | 718 Iterable<Element> getters = <Iterable<Element>>[ |
| 692 part.accessors | 719 part.accessors |
| 693 .where((PropertyAccessorElement accessor) => accessor.isGetter), | 720 .where((PropertyAccessorElement accessor) => accessor.isGetter), |
| 694 part.functions, | 721 part.functions |
| 695 part.topLevelVariables | |
| 696 ].expand((Iterable<Element> elements) => elements); | 722 ].expand((Iterable<Element> elements) => elements); |
| 697 return getters.where((Element getter) => | 723 return getters.where((Element getter) => |
| 698 _capabilities.supportsTopLevelInvoke(getter.name, getter.metadata)); | 724 _capabilities.supportsTopLevelInvoke(getter.name, getter.metadata)); |
| 699 }).expand((Iterable<Element> x) => x); | 725 }).expand((Iterable<Element> x) => x); |
| 700 } | 726 } |
| 701 | 727 |
| 702 Iterable<PropertyAccessorElement> _settersOfLibrary(LibraryElement library) { | 728 Iterable<PropertyAccessorElement> _settersOfLibrary(LibraryElement library) { |
| 703 return library.units.map((CompilationUnitElement part) { | 729 return library.units.map((CompilationUnitElement part) { |
| 704 Iterable setters = <Iterable<Element>>[ | 730 Iterable setters = <Iterable<Element>>[ |
| 705 part.accessors | 731 part.accessors |
| 706 .where((PropertyAccessorElement accessor) => accessor.isSetter), | 732 .where((PropertyAccessorElement accessor) => accessor.isSetter) |
| 707 part.topLevelVariables | |
| 708 .where((TopLevelVariableElement variable) => !variable.isFinal) | |
| 709 ].expand((Iterable<Element> elements) => elements); | 733 ].expand((Iterable<Element> elements) => elements); |
| 710 return setters.where((Element setter) => | 734 return setters.where((Element setter) => |
| 711 _capabilities.supportsTopLevelInvoke(setter.name, setter.metadata)); | 735 _capabilities.supportsTopLevelInvoke(setter.name, setter.metadata)); |
| 712 }).expand((Iterable<Element> x) => x); | 736 }).expand((Iterable<Element> x) => x); |
| 713 } | 737 } |
| 714 | 738 |
| 715 String _classMirrorCode( | 739 String _classMirrorCode( |
| 716 _ClassDomain classDomain, | 740 _ClassDomain classDomain, |
| 717 Enumerator<FieldElement> fields, | 741 Enumerator<FieldElement> fields, |
| 742 int fieldsOffset, | |
| 743 int methodsOffset, | |
| 718 Enumerator<ExecutableElement> members, | 744 Enumerator<ExecutableElement> members, |
| 719 Enumerator<LibraryElement> libraries, | 745 Enumerator<_LibraryDomain> libraries, |
| 746 Map<LibraryElement, _LibraryDomain> libraryMap, | |
| 720 _ImportCollector importCollector, | 747 _ImportCollector importCollector, |
| 721 TransformLogger logger) { | 748 TransformLogger logger) { |
| 749 int descriptor = _classDescriptor(classDomain._classElement); | |
| 750 | |
| 722 // Fields go first in [memberMirrors], so they will get the | 751 // Fields go first in [memberMirrors], so they will get the |
| 723 // same index as in [fields]. | 752 // same index as in [fields]. |
| 724 Iterable<int> fieldsIndices = | 753 Iterable<int> fieldsIndices = |
| 725 classDomain._declaredFields.map((FieldElement element) { | 754 classDomain._declaredFields.map((FieldElement element) { |
| 726 return fields.indexOf(element); | 755 return fields.indexOf(element) + fieldsOffset; |
| 727 }); | 756 }); |
| 728 | 757 |
| 729 // All the elements in the behavioral interface go after the | 758 // All the elements in the behavioral interface go after the |
| 730 // fields in [memberMirrors], so they must get an offset of | 759 // fields in [memberMirrors], so they must get an offset of |
| 731 // `fields.length` on the index. | 760 // `fields.length` on the index. |
| 732 Iterable<int> methodsIndices = classDomain._declarations | 761 Iterable<int> methodsIndices = classDomain._declarations |
| 733 .where(_executableIsntImplicitGetterOrSetter) | 762 .where(_executableIsntImplicitGetterOrSetter) |
| 734 .map((ExecutableElement element) { | 763 .map((ExecutableElement element) { |
| 735 // TODO(eernst) implement: The "magic" default constructor in `Object` | 764 // TODO(eernst) implement: The "magic" default constructor in `Object` |
| 736 // (the one that ultimately allocates the memory for _every_ new | 765 // (the one that ultimately allocates the memory for _every_ new |
| 737 // object) has no index, which creates the need to catch a `null` | 766 // object) has no index, which creates the need to catch a `null` |
| 738 // here. Search for "magic" to find other occurrences of the same | 767 // here. Search for "magic" to find other occurrences of the same |
| 739 // issue. For now, we use the index [constants.NO_CAPABILITY_INDEX] | 768 // issue. For now, we use the index [constants.NO_CAPABILITY_INDEX] |
| 740 // for this declaration, because it is not yet supported. | 769 // for this declaration, because it is not yet supported. |
| 741 // Need to find the correct solution, though! | 770 // Need to find the correct solution, though! |
| 742 int index = members.indexOf(element); | 771 int index = members.indexOf(element); |
| 743 return index == null | 772 return index == null |
| 744 ? constants.NO_CAPABILITY_INDEX | 773 ? constants.NO_CAPABILITY_INDEX |
| 745 : index + fields.length; | 774 : index + methodsOffset; |
| 746 }); | 775 }); |
| 747 | 776 |
| 748 String declarationsCode = "<int>[${constants | 777 String declarationsCode = _capabilities._impliesDeclarations |
| 749 .NO_CAPABILITY_INDEX}]"; | 778 ? _formatAsList( |
| 750 if (_capabilities._impliesDeclarations) { | 779 "int", |
| 751 List<int> declarationsIndices = <int>[] | 780 () sync* { |
| 752 ..addAll(fieldsIndices) | 781 yield* fieldsIndices; |
| 753 ..addAll(methodsIndices); | 782 yield* methodsIndices; |
| 754 declarationsCode = _formatAsList("int", declarationsIndices); | 783 }()) |
| 755 } | 784 : "<int>[${constants.NO_CAPABILITY_INDEX}]"; |
| 756 | 785 |
| 757 // All instance members belong to the behavioral interface, so they | 786 // All instance members belong to the behavioral interface, so they |
| 758 // also get an offset of `fields.length`. | 787 // also get an offset of `fields.length`. |
| 759 String instanceMembersCode = _formatAsList("int", | 788 String instanceMembersCode = _formatAsList("int", |
| 760 classDomain._instanceMembers.map((ExecutableElement element) { | 789 classDomain._instanceMembers.map((ExecutableElement element) { |
| 761 // TODO(eernst) implement: The "magic" default constructor has | 790 // TODO(eernst) implement: The "magic" default constructor has |
| 762 // index: NO_CAPABILITY_INDEX; adjust this when support for it has | 791 // index: NO_CAPABILITY_INDEX; adjust this when support for it has |
| 763 // been implemented. | 792 // been implemented. |
| 764 int index = members.indexOf(element); | 793 int index = members.indexOf(element); |
| 765 return index == null | 794 return index == null |
| 766 ? constants.NO_CAPABILITY_INDEX | 795 ? constants.NO_CAPABILITY_INDEX |
| 767 : index + fields.length; | 796 : index + methodsOffset; |
| 768 })); | 797 })); |
| 769 | 798 |
| 770 // All static members belong to the behavioral interface, so they | 799 // All static members belong to the behavioral interface, so they |
| 771 // also get an offset of `fields.length`. | 800 // also get an offset of `fields.length`. |
| 772 String staticMembersCode = _formatAsList("int", | 801 String staticMembersCode = _formatAsList("int", |
| 773 classDomain._staticMembers.map((ExecutableElement element) { | 802 classDomain._staticMembers.map((ExecutableElement element) { |
| 774 int index = members.indexOf(element); | 803 int index = members.indexOf(element); |
| 775 return index == null | 804 return index == null |
| 776 ? constants.NO_CAPABILITY_INDEX | 805 ? constants.NO_CAPABILITY_INDEX |
| 777 : index + fields.length; | 806 : index + methodsOffset; |
| 778 })); | 807 })); |
| 779 | 808 |
| 780 ClassElement classElement = classDomain._classElement; | 809 ClassElement classElement = classDomain._classElement; |
| 781 ClassElement superclass = classes.superclassOf(classElement); | 810 ClassElement superclass = classes.superclassOf(classElement); |
| 782 // [Object]'s superclass is reported as `null`: it does not exist and | 811 // [Object]'s superclass is reported as `null`: it does not exist and |
| 783 // hence we cannot decide whether it's supported or unsupported; by | 812 // hence we cannot decide whether it's supported or unsupported; by |
| 784 // convention we make it supported and report it in the same way as | 813 // convention we make it supported and report it in the same way as |
| 785 // 'dart:mirrors'. Other superclasses use `NO_CAPABILITY_INDEX` to | 814 // 'dart:mirrors'. Other superclasses use `NO_CAPABILITY_INDEX` to |
| 786 // indicate missing support. | 815 // indicate missing support. |
| 787 String superclassIndex = (classElement is! MixinApplication && | 816 String superclassIndex = (classElement is! MixinApplication && |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 825 // Named mixin application (using the syntax `class B = A with M;`). | 854 // Named mixin application (using the syntax `class B = A with M;`). |
| 826 mixinIndex = classes.indexOf(classElement.mixins.last.element); | 855 mixinIndex = classes.indexOf(classElement.mixins.last.element); |
| 827 } else { | 856 } else { |
| 828 mixinIndex = (classElement is MixinApplication) | 857 mixinIndex = (classElement is MixinApplication) |
| 829 ? classes.indexOf(classElement.mixin) | 858 ? classes.indexOf(classElement.mixin) |
| 830 : classes.indexOf(classElement); | 859 : classes.indexOf(classElement); |
| 831 } | 860 } |
| 832 if (mixinIndex == null) mixinIndex = constants.NO_CAPABILITY_INDEX; | 861 if (mixinIndex == null) mixinIndex = constants.NO_CAPABILITY_INDEX; |
| 833 | 862 |
| 834 int ownerIndex = _capabilities.supportsLibraries | 863 int ownerIndex = _capabilities.supportsLibraries |
| 835 ? libraries.indexOf(classElement.library) | 864 ? libraries.indexOf(libraryMap[classElement.library]) |
| 836 : constants.NO_CAPABILITY_INDEX; | 865 : constants.NO_CAPABILITY_INDEX; |
| 837 | 866 |
| 838 String superinterfaceIndices = _formatAsList( | 867 String superinterfaceIndices = _formatAsList( |
| 839 'int', | 868 'int', |
| 840 classElement.interfaces | 869 classElement.interfaces |
| 841 .map((InterfaceType type) => type.element) | 870 .map((InterfaceType type) => type.element) |
| 842 .where(classes.contains) | 871 .where(classes.contains) |
| 843 .map(classes.indexOf)); | 872 .map(classes.indexOf)); |
| 844 | 873 |
| 845 String classMetadataCode; | 874 String classMetadataCode; |
| 846 if (_capabilities._supportsMetadata) { | 875 if (_capabilities._supportsMetadata) { |
| 847 classMetadataCode = _extractMetadataCode(classElement, _resolver, | 876 classMetadataCode = _extractMetadataCode(classElement, _resolver, |
| 848 importCollector, logger, _generatedLibraryId); | 877 importCollector, logger, _generatedLibraryId); |
| 849 } else { | 878 } else { |
| 850 classMetadataCode = "null"; | 879 classMetadataCode = "null"; |
| 851 } | 880 } |
| 852 | 881 |
| 853 int classIndex = classes.indexOf(classElement); | 882 int classIndex = classes.indexOf(classElement); |
| 854 | 883 |
| 855 String result = 'new r.ClassMirrorImpl(r"${classDomain._simpleName}", ' | 884 String result = 'new r.ClassMirrorImpl(r"${classDomain._simpleName}", ' |
| 856 'r"${_qualifiedName(classElement)}", $classIndex, ' | 885 'r"${_qualifiedName(classElement)}", $descriptor, $classIndex, ' |
| 857 '${_constConstructionCode(importCollector)}, ' | 886 '${_constConstructionCode(importCollector)}, ' |
| 858 '$declarationsCode, $instanceMembersCode, $staticMembersCode, ' | 887 '$declarationsCode, $instanceMembersCode, $staticMembersCode, ' |
| 859 '$superclassIndex, $staticGettersCode, $staticSettersCode, ' | 888 '$superclassIndex, $staticGettersCode, $staticSettersCode, ' |
| 860 '$constructorsCode, $ownerIndex, $mixinIndex, ' | 889 '$constructorsCode, $ownerIndex, $mixinIndex, ' |
| 861 '$superinterfaceIndices, $classMetadataCode)'; | 890 '$superinterfaceIndices, $classMetadataCode)'; |
| 862 return result; | 891 return result; |
| 863 } | 892 } |
| 864 | 893 |
| 865 String _methodMirrorCode( | 894 String _methodMirrorCode( |
| 866 ExecutableElement element, | 895 ExecutableElement element, |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 943 '${dartType.element}")'; | 972 '${dartType.element}")'; |
| 944 } | 973 } |
| 945 return _typeCodeOfClass(dartType.element, importCollector); | 974 return _typeCodeOfClass(dartType.element, importCollector); |
| 946 } | 975 } |
| 947 | 976 |
| 948 String _typeCodeOfClass( | 977 String _typeCodeOfClass( |
| 949 ClassElement classElement, _ImportCollector importCollector) { | 978 ClassElement classElement, _ImportCollector importCollector) { |
| 950 if (classElement is MixinApplication && classElement.declaredName == null) { | 979 if (classElement is MixinApplication && classElement.declaredName == null) { |
| 951 return 'new r.FakeType(r"${_qualifiedName(classElement)}")'; | 980 return 'new r.FakeType(r"${_qualifiedName(classElement)}")'; |
| 952 } | 981 } |
| 953 if (classElement is! MixinApplication && classElement.type.isDynamic) { | 982 if (classElement.type.isDynamic) return "dynamic"; |
| 954 return "dynamic"; | |
| 955 } | |
| 956 String prefix = importCollector._getPrefix(classElement.library); | 983 String prefix = importCollector._getPrefix(classElement.library); |
| 957 return "$prefix.${classElement.name}"; | 984 return "$prefix.${classElement.name}"; |
| 958 } | 985 } |
| 959 | 986 |
| 960 String _libraryMirrorCode(LibraryElement library, | 987 String _libraryMirrorCode( |
| 961 _ImportCollector importCollector, TransformLogger logger) { | 988 _LibraryDomain libraryDomain, |
| 989 Enumerator<ExecutableElement> members, | |
| 990 Enumerator<TopLevelVariableElement> variables, | |
| 991 int fieldsLength, | |
| 992 _ImportCollector importCollector, | |
| 993 TransformLogger logger) { | |
| 994 LibraryElement library = libraryDomain._libraryElement; | |
| 962 String gettersCode = _formatAsMap( | 995 String gettersCode = _formatAsMap( |
| 963 _gettersOfLibrary(library).map((PropertyAccessorElement getter) { | 996 _gettersOfLibrary(library).map((PropertyAccessorElement getter) { |
| 964 return _topLevelGettingClosure(importCollector, library, getter.name); | 997 return _topLevelGettingClosure(importCollector, library, getter.name); |
| 965 })); | 998 })); |
|
sigurdm
2015/10/09 07:52:04
A newline here would look better.
eernst
2015/10/09 10:09:05
Not sure what you mean?
sigurdm
2015/10/09 10:47:20
Initialization of settersCode and variableIndices
eernst
2015/10/09 11:24:14
Done.
| |
| 966 String settersCode = _formatAsMap( | 999 String settersCode = _formatAsMap( |
| 967 _settersOfLibrary(library).map((PropertyAccessorElement setter) { | 1000 _settersOfLibrary(library).map((PropertyAccessorElement setter) { |
| 968 return topLevelSettingClosure(importCollector, library, setter.name); | 1001 return topLevelSettingClosure(importCollector, library, setter.name); |
| 969 })); | 1002 })); |
| 970 | 1003 |
| 1004 // Fields go first in [memberMirrors], so they will get the | |
| 1005 // same index as in [fields]. | |
| 1006 Iterable<int> variableIndices = | |
| 1007 libraryDomain._declaredVariables.map((TopLevelVariableElement element) { | |
| 1008 return variables.indexOf(element); | |
| 1009 }); | |
| 1010 | |
| 1011 // All the elements in the behavioral interface go after the | |
| 1012 // fields in [memberMirrors], so they must get an offset of | |
| 1013 // `fields.length` on the index. | |
| 1014 Iterable<int> methodsIndices = libraryDomain._declarations | |
| 1015 .where(_executableIsntImplicitGetterOrSetter) | |
| 1016 .map((ExecutableElement element) { | |
| 1017 int index = members.indexOf(element); | |
| 1018 return index + fieldsLength; | |
| 1019 }); | |
| 1020 | |
| 1021 String declarationsCode = "<int>[${constants.NO_CAPABILITY_INDEX}]"; | |
| 1022 if (_capabilities._impliesDeclarations) { | |
| 1023 List<int> declarationsIndices = <int>[] | |
| 1024 ..addAll(variableIndices) | |
| 1025 ..addAll(methodsIndices); | |
| 1026 declarationsCode = _formatAsList("int", declarationsIndices); | |
| 1027 } | |
| 1028 | |
| 971 // TODO(sigurdm) clarify: Find out how to get good uri's in a | 1029 // TODO(sigurdm) clarify: Find out how to get good uri's in a |
| 972 // transformer. | 1030 // transformer. |
| 973 // TODO(sigurdm) implement: Check for `uriCapability`. | 1031 // TODO(sigurdm) implement: Check for `uriCapability`. |
| 974 String uriCode = "null"; | 1032 String uriCode = "null"; |
| 975 | 1033 |
| 976 String metadataCode; | 1034 String metadataCode; |
| 977 if (_capabilities._supportsMetadata) { | 1035 if (_capabilities._supportsMetadata) { |
| 978 metadataCode = _extractMetadataCode( | 1036 metadataCode = _extractMetadataCode( |
| 979 library, _resolver, importCollector, logger, _generatedLibraryId); | 1037 library, _resolver, importCollector, logger, _generatedLibraryId); |
| 980 } else { | 1038 } else { |
| 981 metadataCode = "null"; | 1039 metadataCode = "null"; |
| 982 } | 1040 } |
| 983 | 1041 |
| 984 return 'new r.LibraryMirrorImpl(r"${library.name}", $uriCode, ' | 1042 return 'new r.LibraryMirrorImpl(r"${library.name}", $uriCode, ' |
| 985 '$gettersCode, $settersCode, $metadataCode)'; | 1043 '${_constConstructionCode(importCollector)}, ' |
| 1044 '$declarationsCode, $gettersCode, $settersCode, $metadataCode)'; | |
| 986 } | 1045 } |
| 987 | 1046 |
| 988 String _parameterMirrorCode( | 1047 String _parameterMirrorCode( |
| 989 ParameterElement element, | 1048 ParameterElement element, |
| 990 Enumerator<FieldElement> fields, | 1049 Enumerator<FieldElement> fields, |
| 991 Enumerator<ExecutableElement> members, | 1050 Enumerator<ExecutableElement> members, |
| 992 _ImportCollector importCollector, | 1051 _ImportCollector importCollector, |
| 993 TransformLogger logger, | 1052 TransformLogger logger, |
| 994 bool reflectedTypeRequested) { | 1053 bool reflectedTypeRequested) { |
| 995 int descriptor = _parameterDescriptor(element); | 1054 int descriptor = _parameterDescriptor(element); |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1297 } else if (getterName == "~") { | 1356 } else if (getterName == "~") { |
| 1298 closure = "(dynamic instance) => () => ~instance"; | 1357 closure = "(dynamic instance) => () => ~instance"; |
| 1299 } else { | 1358 } else { |
| 1300 closure = "(dynamic instance) => (x) => instance ${getterName} x"; | 1359 closure = "(dynamic instance) => (x) => instance ${getterName} x"; |
| 1301 } | 1360 } |
| 1302 return 'r"${getterName}": $closure'; | 1361 return 'r"${getterName}": $closure'; |
| 1303 } | 1362 } |
| 1304 | 1363 |
| 1305 // Auxiliary function used by `_generateCode`. | 1364 // Auxiliary function used by `_generateCode`. |
| 1306 String _settingClosure(String setterName) { | 1365 String _settingClosure(String setterName) { |
| 1307 assert(setterName.substring(setterName.length - 1) == "="); | 1366 String name = setterName.substring(setterName.length - 1) == "=" |
|
sigurdm
2015/10/09 07:52:04
Can we now get a setterName not ending in '='? Whe
eernst
2015/10/09 10:09:05
I found `someName = value` in the generated code a
sigurdm
2015/10/09 10:47:20
I think we should track down where that happens. M
eernst
2015/10/09 11:24:14
Did that, and it doesn't fail now. I think this ma
| |
| 1308 // The [setterName] includes the "=", remove it. | 1367 ? setterName.substring(0, setterName.length - 1) |
| 1309 String name = setterName.substring(0, setterName.length - 1); | 1368 : setterName; |
| 1310 | |
| 1311 return 'r"$setterName": (dynamic instance, value) => ' | 1369 return 'r"$setterName": (dynamic instance, value) => ' |
| 1312 'instance.$name = value'; | 1370 'instance.$name = value'; |
| 1313 } | 1371 } |
| 1314 | 1372 |
| 1315 // Auxiliary function used by `_generateCode`. | 1373 // Auxiliary function used by `_generateCode`. |
| 1316 String _staticGettingClosure(_ImportCollector importCollector, | 1374 String _staticGettingClosure(_ImportCollector importCollector, |
| 1317 ClassElement classElement, String getterName) { | 1375 ClassElement classElement, String getterName) { |
| 1318 String className = classElement.name; | 1376 String className = classElement.name; |
| 1319 String prefix = importCollector._getPrefix(classElement.library); | 1377 String prefix = importCollector._getPrefix(classElement.library); |
| 1320 // Operators cannot be static. | 1378 // Operators cannot be static. |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 1343 // Auxiliary function used by `_generateCode`. | 1401 // Auxiliary function used by `_generateCode`. |
| 1344 String topLevelSettingClosure(_ImportCollector importCollector, | 1402 String topLevelSettingClosure(_ImportCollector importCollector, |
| 1345 LibraryElement library, String setterName) { | 1403 LibraryElement library, String setterName) { |
| 1346 assert(setterName.substring(setterName.length - 1) == "="); | 1404 assert(setterName.substring(setterName.length - 1) == "="); |
| 1347 // The [setterName] includes the "=", remove it. | 1405 // The [setterName] includes the "=", remove it. |
| 1348 String name = setterName.substring(0, setterName.length - 1); | 1406 String name = setterName.substring(0, setterName.length - 1); |
| 1349 String prefix = importCollector._getPrefix(library); | 1407 String prefix = importCollector._getPrefix(library); |
| 1350 return 'r"$setterName": (value) => $prefix.$name = value'; | 1408 return 'r"$setterName": (value) => $prefix.$name = value'; |
| 1351 } | 1409 } |
| 1352 | 1410 |
| 1411 /// Information about reflectability for a given library. | |
| 1412 class _LibraryDomain { | |
| 1413 /// Element describing the target library. | |
| 1414 final LibraryElement _libraryElement; | |
| 1415 | |
| 1416 /// Fields declared by [_libraryElement] and included for reflection support, | |
| 1417 /// according to the reflector described by the [_reflectorDomain]; | |
| 1418 /// obtained by filtering `_libraryElement.fields`. | |
| 1419 final Iterable<TopLevelVariableElement> _declaredVariables; | |
| 1420 | |
| 1421 /// Methods which are declared by [_libraryElement] and included for | |
| 1422 /// reflection support, according to the reflector described by | |
| 1423 /// [_reflectorDomain]; obtained by filtering `_libraryElement.functions`. | |
| 1424 final Iterable<FunctionElement> _declaredFunctions; | |
| 1425 | |
| 1426 /// Formal parameters declared by one of the [_declaredFunctions]. | |
| 1427 final Iterable<ParameterElement> _declaredParameters; | |
| 1428 | |
| 1429 /// Getters and setters possessed by [_libraryElement] and included for | |
| 1430 /// reflection support, according to the reflector described by | |
| 1431 /// [_reflectorDomain]; obtained by filtering `_libraryElement.accessors`. | |
| 1432 /// Note that it includes declared as well as synthetic accessors, | |
| 1433 /// implicitly created as getters/setters for fields. | |
| 1434 final Iterable<PropertyAccessorElement> _declaredAndImplicitAccessors; | |
| 1435 | |
| 1436 /// The reflector domain that holds [this] object as one of its | |
| 1437 /// library domains. | |
| 1438 final _ReflectorDomain _reflectorDomain; | |
| 1439 | |
| 1440 _LibraryDomain( | |
| 1441 this._libraryElement, | |
| 1442 this._declaredVariables, | |
| 1443 this._declaredFunctions, | |
| 1444 this._declaredParameters, | |
| 1445 this._declaredAndImplicitAccessors, | |
| 1446 this._reflectorDomain); | |
| 1447 | |
| 1448 String get _simpleName { | |
| 1449 return _libraryElement.name; | |
| 1450 } | |
| 1451 | |
| 1452 /// Returns the declared methods, accessors and constructors in | |
| 1453 /// [_classElement]. Note that this includes synthetic getters and | |
| 1454 /// setters, and omits fields; in other words, it provides the | |
| 1455 /// behavioral point of view on the class. Also note that this is not | |
| 1456 /// the same semantics as that of `declarations` in [ClassMirror]. | |
| 1457 Iterable<ExecutableElement> get _declarations sync* { | |
| 1458 yield* _declaredFunctions; | |
| 1459 yield* _declaredAndImplicitAccessors; | |
| 1460 } | |
| 1461 | |
| 1462 String toString() { | |
| 1463 return "LibraryDomain($_libraryElement)"; | |
| 1464 } | |
| 1465 | |
| 1466 bool operator ==(Object other) { | |
| 1467 if (other is _LibraryDomain) { | |
| 1468 return _libraryElement == other._libraryElement && | |
| 1469 _reflectorDomain == other._reflectorDomain; | |
| 1470 } else { | |
| 1471 return false; | |
| 1472 } | |
| 1473 } | |
| 1474 | |
| 1475 int get hashCode => _libraryElement.hashCode ^ _reflectorDomain.hashCode; | |
| 1476 } | |
| 1477 | |
| 1353 /// Information about reflectability for a given class. | 1478 /// Information about reflectability for a given class. |
| 1354 class _ClassDomain { | 1479 class _ClassDomain { |
| 1355 /// Element describing the target class. | 1480 /// Element describing the target class. |
| 1356 final ClassElement _classElement; | 1481 final ClassElement _classElement; |
| 1357 | 1482 |
| 1358 /// Fields declared by [classElement] and included for reflection support, | 1483 /// Fields declared by [_classElement] and included for reflection support, |
| 1359 /// according to the reflector described by the [reflectorDomain]; | 1484 /// according to the reflector described by the [_reflectorDomain]; |
| 1360 /// obtained by filtering `classElement.fields`. | 1485 /// obtained by filtering `_classElement.fields`. |
| 1361 final Iterable<FieldElement> _declaredFields; | 1486 final Iterable<FieldElement> _declaredFields; |
| 1362 | 1487 |
| 1363 /// Methods which are declared by [classElement] and included for | 1488 /// Methods which are declared by [_classElement] and included for |
| 1364 /// reflection support, according to the reflector described by | 1489 /// reflection support, according to the reflector described by |
| 1365 /// [reflectorDomain]; obtained by filtering `classElement.methods`. | 1490 /// [reflectorDomain]; obtained by filtering `_classElement.methods`. |
| 1366 final Iterable<MethodElement> _declaredMethods; | 1491 final Iterable<MethodElement> _declaredMethods; |
| 1367 | 1492 |
| 1368 /// Formal parameters declared by one of the [_declaredMethods]. | 1493 /// Formal parameters declared by one of the [_declaredMethods]. |
| 1369 final Iterable<ParameterElement> _declaredParameters; | 1494 final Iterable<ParameterElement> _declaredParameters; |
| 1370 | 1495 |
| 1371 /// Getters and setters possessed by [classElement] and included for | 1496 /// Getters and setters possessed by [_classElement] and included for |
| 1372 /// reflection support, according to the reflector described by | 1497 /// reflection support, according to the reflector described by |
| 1373 /// [reflectorDomain]; obtained by filtering `classElement.accessors`. | 1498 /// [reflectorDomain]; obtained by filtering `_classElement.accessors`. |
| 1374 /// Note that it includes declared as well as synthetic accessors, | 1499 /// Note that it includes declared as well as synthetic accessors, |
| 1375 /// implicitly created as getters/setters for fields. | 1500 /// implicitly created as getters/setters for fields. |
| 1376 final Iterable<PropertyAccessorElement> _declaredAndImplicitAccessors; | 1501 final Iterable<PropertyAccessorElement> _declaredAndImplicitAccessors; |
| 1377 | 1502 |
| 1378 /// Constructors declared by [classElement] and included for reflection | 1503 /// Constructors declared by [_classElement] and included for reflection |
| 1379 /// support, according to the reflector described by [reflectorDomain]; | 1504 /// support, according to the reflector described by [_reflectorDomain]; |
| 1380 /// obtained by filtering `classElement.constructors`. | 1505 /// obtained by filtering `_classElement.constructors`. |
| 1381 final Iterable<ConstructorElement> _constructors; | 1506 final Iterable<ConstructorElement> _constructors; |
| 1382 | 1507 |
| 1383 /// The reflector domain that holds [this] object as one of its | 1508 /// The reflector domain that holds [this] object as one of its |
| 1384 /// class domains. | 1509 /// class domains. |
| 1385 final _ReflectorDomain _reflectorDomain; | 1510 final _ReflectorDomain _reflectorDomain; |
| 1386 | 1511 |
| 1387 _ClassDomain( | 1512 _ClassDomain( |
| 1388 this._classElement, | 1513 this._classElement, |
| 1389 this._declaredFields, | 1514 this._declaredFields, |
| 1390 this._declaredMethods, | 1515 this._declaredMethods, |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1634 // Handle API based capabilities. | 1759 // Handle API based capabilities. |
| 1635 if ((capability is ec.TopLevelInvokeCapability) && | 1760 if ((capability is ec.TopLevelInvokeCapability) && |
| 1636 _supportsName(capability, methodName)) { | 1761 _supportsName(capability, methodName)) { |
| 1637 return true; | 1762 return true; |
| 1638 } | 1763 } |
| 1639 if ((capability is ec.TopLevelInvokeMetaCapability) && | 1764 if ((capability is ec.TopLevelInvokeMetaCapability) && |
| 1640 _supportsMeta(capability, metadata)) { | 1765 _supportsMeta(capability, metadata)) { |
| 1641 return true; | 1766 return true; |
| 1642 } | 1767 } |
| 1643 // Quantifying capabilities do not influence the availability | 1768 // Quantifying capabilities do not influence the availability |
| 1644 // of reflection support for top level invocation. | 1769 // of reflection support for top-level invocation. |
| 1645 } | 1770 } |
| 1646 | 1771 |
| 1647 // All options exhausted, give up. | 1772 // All options exhausted, give up. |
| 1648 return false; | 1773 return false; |
| 1649 } | 1774 } |
| 1650 | 1775 |
| 1651 bool _supportsStaticInvoke(List<ec.ReflectCapability> capabilities, | 1776 bool _supportsStaticInvoke(List<ec.ReflectCapability> capabilities, |
| 1652 String methodName, Iterable<DartObject> metadata) { | 1777 String methodName, Iterable<DartObject> metadata) { |
| 1653 for (ec.ReflectCapability capability in capabilities) { | 1778 for (ec.ReflectCapability capability in capabilities) { |
| 1654 // Handle API based capabilities. | 1779 // Handle API based capabilities. |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1935 // types (types whose name does not end in `..Impl`) declare the getter | 2060 // types (types whose name does not end in `..Impl`) declare the getter |
| 1936 // `evaluationResult`. Another possible choice of type would be | 2061 // `evaluationResult`. Another possible choice of type would be |
| 1937 // [VariableElementImpl], but with that one we would have to test | 2062 // [VariableElementImpl], but with that one we would have to test |
| 1938 // `isConst` as well. | 2063 // `isConst` as well. |
| 1939 if (variable is ConstTopLevelVariableElementImpl) { | 2064 if (variable is ConstTopLevelVariableElementImpl) { |
| 1940 EvaluationResultImpl result = variable.evaluationResult; | 2065 EvaluationResultImpl result = variable.evaluationResult; |
| 1941 if (result.value == null) return null; // Errors during evaluation. | 2066 if (result.value == null) return null; // Errors during evaluation. |
| 1942 bool isOk = checkInheritance(result.value.type, focusClass.type); | 2067 bool isOk = checkInheritance(result.value.type, focusClass.type); |
| 1943 return isOk ? result.value.type.element : null; | 2068 return isOk ? result.value.type.element : null; |
| 1944 } else { | 2069 } else { |
| 1945 // Not a const top level variable, not relevant. | 2070 // Not a const top-level variable, not relevant. |
| 1946 return null; | 2071 return null; |
| 1947 } | 2072 } |
| 1948 } | 2073 } |
| 1949 // Otherwise [element] is some other construct which is not supported. | 2074 // Otherwise [element] is some other construct which is not supported. |
| 1950 // | 2075 // |
| 1951 // TODO(eernst) clarify: We need to consider whether there could be some | 2076 // TODO(eernst) clarify: We need to consider whether there could be some |
| 1952 // other syntactic constructs that are incorrectly assumed by programmers | 2077 // other syntactic constructs that are incorrectly assumed by programmers |
| 1953 // to be usable with Reflectable. Currently, such constructs will silently | 2078 // to be usable with Reflectable. Currently, such constructs will silently |
| 1954 // have no effect; it might be better to emit a diagnostic message (a | 2079 // have no effect; it might be better to emit a diagnostic message (a |
| 1955 // hint?) in order to notify the programmer that "it does not work". | 2080 // hint?) in order to notify the programmer that "it does not work". |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2126 } else { | 2251 } else { |
| 2127 _ReflectorDomain domain = getReflectorDomain(reflector); | 2252 _ReflectorDomain domain = getReflectorDomain(reflector); |
| 2128 if (!domain._classes.contains(type)) { | 2253 if (!domain._classes.contains(type)) { |
| 2129 if (type.isMixinApplication) { | 2254 if (type.isMixinApplication) { |
| 2130 // Iterate over all mixins in most-general-first order (so with | 2255 // Iterate over all mixins in most-general-first order (so with |
| 2131 // `class C extends B with M1, M2..` we visit `M1` then `M2`. | 2256 // `class C extends B with M1, M2..` we visit `M1` then `M2`. |
| 2132 ClassElement superclass = type.supertype.element; | 2257 ClassElement superclass = type.supertype.element; |
| 2133 for (InterfaceType mixin in type.mixins) { | 2258 for (InterfaceType mixin in type.mixins) { |
| 2134 ClassElement mixinElement = mixin.element; | 2259 ClassElement mixinElement = mixin.element; |
| 2135 ClassElement subClass = mixin == type.mixins.last ? type : null; | 2260 ClassElement subClass = mixin == type.mixins.last ? type : null; |
| 2136 String name = subClass == null ? null : type.name; | 2261 String name = subClass == null |
|
sigurdm
2015/10/09 07:52:04
Could be
```
String name = subClass ?? (type.isMix
eernst
2015/10/09 10:09:04
It's a bit more tricky than that: If `subClass ==
sigurdm
2015/10/09 10:47:20
Oops - you're right!
| |
| 2262 ? null | |
| 2263 : (type.isMixinApplication ? type.name : null); | |
| 2137 MixinApplication mixinApplication = new MixinApplication( | 2264 MixinApplication mixinApplication = new MixinApplication( |
| 2138 name, superclass, mixinElement, type.library, subClass); | 2265 name, superclass, mixinElement, type.library, subClass); |
| 2139 domain._classes.add(mixinApplication); | 2266 domain._classes.add(mixinApplication); |
| 2140 superclass = mixinApplication; | 2267 superclass = mixinApplication; |
| 2141 } | 2268 } |
| 2142 } else { | 2269 } else { |
| 2143 domain._classes.add(type); | 2270 domain._classes.add(type); |
| 2144 } | 2271 } |
| 2145 addLibrary(type.library, reflector); | 2272 addLibrary(type.library, reflector); |
| 2146 // We need to ensure that the [importCollector] has indeed added | 2273 // We need to ensure that the [importCollector] has indeed added |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2214 addLibrary(library, reflector); | 2341 addLibrary(library, reflector); |
| 2215 } | 2342 } |
| 2216 | 2343 |
| 2217 for (CompilationUnitElement unit in library.units) { | 2344 for (CompilationUnitElement unit in library.units) { |
| 2218 for (ClassElement type in unit.types) { | 2345 for (ClassElement type in unit.types) { |
| 2219 for (ClassElement reflector | 2346 for (ClassElement reflector |
| 2220 in getReflectors(_qualifiedName(type), type.metadata)) { | 2347 in getReflectors(_qualifiedName(type), type.metadata)) { |
| 2221 addClassDomain(type, reflector); | 2348 addClassDomain(type, reflector); |
| 2222 } | 2349 } |
| 2223 } | 2350 } |
| 2351 for (FunctionElement function in unit.functions) { | |
| 2352 for (ClassElement reflector in getReflectors( | |
| 2353 _qualifiedFunctionName(function), function.metadata)) { | |
| 2354 // We just add the library here, the function itself will be | |
| 2355 // supported using `invoke` and `declarations` of that library | |
| 2356 // mirror. | |
| 2357 addLibrary(library, reflector); | |
| 2358 } | |
| 2359 } | |
| 2224 } | 2360 } |
| 2225 } | 2361 } |
| 2226 | 2362 |
| 2227 return new ReflectionWorld(_resolver, dataId, domains.values.toList(), | 2363 return new ReflectionWorld(_resolver, dataId, domains.values.toList(), |
| 2228 reflectableLibrary, entryPoint, importCollector); | 2364 reflectableLibrary, entryPoint, importCollector); |
| 2229 } | 2365 } |
| 2230 | 2366 |
| 2231 /// Returns the [ReflectCapability] denoted by the given [initializer]. | 2367 /// Returns the [ReflectCapability] denoted by the given [initializer]. |
| 2232 ec.ReflectCapability _capabilityOfExpression(LibraryElement capabilityLibrary, | 2368 ec.ReflectCapability _capabilityOfExpression(LibraryElement capabilityLibrary, |
| 2233 Expression expression, LibraryElement containingLibrary) { | 2369 Expression expression, LibraryElement containingLibrary) { |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2581 bool _accessorIsntImplicitGetterOrSetter(PropertyAccessorElement accessor) { | 2717 bool _accessorIsntImplicitGetterOrSetter(PropertyAccessorElement accessor) { |
| 2582 return !accessor.isSynthetic || (!accessor.isGetter && !accessor.isSetter); | 2718 return !accessor.isSynthetic || (!accessor.isGetter && !accessor.isSetter); |
| 2583 } | 2719 } |
| 2584 | 2720 |
| 2585 bool _executableIsntImplicitGetterOrSetter(ExecutableElement executable) { | 2721 bool _executableIsntImplicitGetterOrSetter(ExecutableElement executable) { |
| 2586 return executable is! PropertyAccessorElement || | 2722 return executable is! PropertyAccessorElement || |
| 2587 _accessorIsntImplicitGetterOrSetter(executable); | 2723 _accessorIsntImplicitGetterOrSetter(executable); |
| 2588 } | 2724 } |
| 2589 | 2725 |
| 2590 /// Returns an integer encoding of the kind and attributes of the given | 2726 /// Returns an integer encoding of the kind and attributes of the given |
| 2727 /// class. | |
| 2728 int _classDescriptor(ClassElement element) { | |
| 2729 int result = constants.clazz; | |
| 2730 if (element.isPrivate) result |= constants.privateAttribute; | |
| 2731 if (element.isSynthetic) result |= constants.syntheticAttribute; | |
| 2732 if (element.isAbstract) result |= constants.abstractAttribute; | |
| 2733 if (element.isEnum) result |= constants.enumAttribute; | |
| 2734 return result; | |
| 2735 } | |
| 2736 | |
| 2737 /// Returns an integer encoding of the kind and attributes of the given | |
| 2591 /// field. | 2738 /// field. |
| 2592 int _fieldDescriptor(FieldElement element) { | 2739 int _fieldDescriptor(FieldElement element) { |
| 2593 int result = constants.field; | 2740 int result = constants.field; |
| 2594 if (element.isPrivate) result |= constants.privateAttribute; | 2741 if (element.isPrivate) result |= constants.privateAttribute; |
| 2595 if (element.isSynthetic) result |= constants.syntheticAttribute; | 2742 if (element.isSynthetic) result |= constants.syntheticAttribute; |
| 2596 if (element.isConst) { | 2743 if (element.isConst) { |
| 2597 result |= constants.constAttribute; | 2744 result |= constants.constAttribute; |
| 2598 // We will get `false` from `element.isFinal` in this case, but with | 2745 // We will get `false` from `element.isFinal` in this case, but with |
| 2599 // a mirror from 'dart:mirrors' it is considered to be "implicitly | 2746 // a mirror from 'dart:mirrors' it is considered to be "implicitly |
| 2600 // final", so we follow that and ignore `element.isFinal`. | 2747 // final", so we follow that and ignore `element.isFinal`. |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2933 metadataParts.add("const $prefix.$constructor($arguments)"); | 3080 metadataParts.add("const $prefix.$constructor($arguments)"); |
| 2934 } else { | 3081 } else { |
| 2935 // A field reference. | 3082 // A field reference. |
| 2936 metadataParts.add("$prefix.${annotationNode.name}"); | 3083 metadataParts.add("$prefix.${annotationNode.name}"); |
| 2937 } | 3084 } |
| 2938 } | 3085 } |
| 2939 | 3086 |
| 2940 return _formatAsList("Object", metadataParts); | 3087 return _formatAsList("Object", metadataParts); |
| 2941 } | 3088 } |
| 2942 | 3089 |
| 3090 Iterable<TopLevelVariableElement> _extractDeclaredVariables( | |
|
sigurdm
2015/10/09 07:52:04
Give these functions a (short) comment
eernst
2015/10/09 10:09:05
Done.
| |
| 3091 LibraryElement libraryElement, _Capabilities capabilities) sync* { | |
| 3092 for (CompilationUnitElement unit in libraryElement.units) { | |
| 3093 for (TopLevelVariableElement variable in unit.topLevelVariables) { | |
| 3094 if (variable.isPrivate || variable.isSynthetic) continue; | |
| 3095 // TODO(eernst) clarify: Do we want to subsume variables under invoke? | |
| 3096 if (capabilities.supportsTopLevelInvoke( | |
| 3097 variable.name, variable.metadata)) { | |
| 3098 yield variable; | |
| 3099 } | |
| 3100 } | |
| 3101 } | |
| 3102 } | |
| 3103 | |
| 3104 Iterable<FunctionElement> _extractDeclaredFunctions( | |
| 3105 LibraryElement libraryElement, _Capabilities capabilities) sync* { | |
| 3106 for (CompilationUnitElement unit in libraryElement.units) { | |
| 3107 for (FunctionElement function in unit.functions) { | |
| 3108 if (function.isPrivate) continue; | |
| 3109 if (capabilities.supportsTopLevelInvoke( | |
| 3110 function.name, function.metadata)) { | |
| 3111 yield function; | |
| 3112 } | |
| 3113 } | |
| 3114 } | |
| 3115 } | |
| 3116 | |
| 3117 Iterable<ParameterElement> _extractDeclaredFunctionParameters( | |
| 3118 Iterable<FunctionElement> declaredFunctions, | |
| 3119 Iterable<PropertyAccessorElement> accessors) { | |
| 3120 List<ParameterElement> result = <ParameterElement>[]; | |
| 3121 for (FunctionElement declaredFunction in declaredFunctions) { | |
| 3122 result.addAll(declaredFunction.parameters); | |
| 3123 } | |
| 3124 for (PropertyAccessorElement accessor in accessors) { | |
| 3125 if (accessor.isSetter) { | |
| 3126 result.addAll(accessor.parameters); | |
| 3127 } | |
| 3128 } | |
| 3129 return result; | |
| 3130 } | |
| 3131 | |
| 2943 Iterable<FieldElement> _extractDeclaredFields( | 3132 Iterable<FieldElement> _extractDeclaredFields( |
| 2944 ClassElement classElement, _Capabilities capabilities) { | 3133 ClassElement classElement, _Capabilities capabilities) { |
| 2945 return classElement.fields.where((FieldElement field) { | 3134 return classElement.fields.where((FieldElement field) { |
| 2946 if (field.isPrivate) return false; | 3135 if (field.isPrivate) return false; |
| 2947 Function capabilityChecker = field.isStatic | 3136 Function capabilityChecker = field.isStatic |
| 2948 ? capabilities.supportsStaticInvoke | 3137 ? capabilities.supportsStaticInvoke |
| 2949 : capabilities.supportsInstanceInvoke; | 3138 : capabilities.supportsInstanceInvoke; |
| 2950 return !field.isSynthetic && capabilityChecker(field.name, field.metadata); | 3139 return !field.isSynthetic && capabilityChecker(field.name, field.metadata); |
| 2951 }); | 3140 }); |
| 2952 } | 3141 } |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 2974 result.addAll(declaredConstructor.parameters); | 3163 result.addAll(declaredConstructor.parameters); |
| 2975 } | 3164 } |
| 2976 for (PropertyAccessorElement accessor in accessors) { | 3165 for (PropertyAccessorElement accessor in accessors) { |
| 2977 if (accessor.isSetter) { | 3166 if (accessor.isSetter) { |
| 2978 result.addAll(accessor.parameters); | 3167 result.addAll(accessor.parameters); |
| 2979 } | 3168 } |
| 2980 } | 3169 } |
| 2981 return result; | 3170 return result; |
| 2982 } | 3171 } |
| 2983 | 3172 |
| 3173 Iterable<PropertyAccessorElement> _declaredAndImplicitLibraryAccessors( | |
| 3174 LibraryElement libraryElement, _Capabilities capabilities) sync* { | |
| 3175 for (CompilationUnitElement unit in libraryElement.units) { | |
| 3176 for (PropertyAccessorElement accessor in unit.accessors) { | |
| 3177 if (accessor.isPrivate) continue; | |
| 3178 if (capabilities.supportsTopLevelInvoke( | |
| 3179 accessor.name, accessor.metadata)) { | |
| 3180 yield accessor; | |
| 3181 } | |
| 3182 } | |
| 3183 } | |
| 3184 } | |
| 3185 | |
| 2984 /// Returns the [PropertyAccessorElement]s which are the accessors | 3186 /// Returns the [PropertyAccessorElement]s which are the accessors |
| 2985 /// of the given [classElement], including both the declared ones | 3187 /// of the given [classElement], including both the declared ones |
| 2986 /// and the implicitly generated ones corresponding to fields. This | 3188 /// and the implicitly generated ones corresponding to fields. This |
| 2987 /// is the set of accessors that corresponds to the behavioral interface | 3189 /// is the set of accessors that corresponds to the behavioral interface |
| 2988 /// of the corresponding instances, as opposed to the source code oriented | 3190 /// of the corresponding instances, as opposed to the source code oriented |
| 2989 /// interface, e.g., `declarations`. But the latter can be computed from | 3191 /// interface, e.g., `declarations`. But the latter can be computed from |
| 2990 /// here, by filtering out the accessors whose `isSynthetic` is true | 3192 /// here, by filtering out the accessors whose `isSynthetic` is true |
| 2991 /// and adding the fields. | 3193 /// and adding the fields. |
| 2992 Iterable<PropertyAccessorElement> _declaredAndImplicitAccessors( | 3194 Iterable<PropertyAccessorElement> _declaredAndImplicitAccessors( |
| 2993 ClassElement classElement, _Capabilities capabilities) { | 3195 ClassElement classElement, _Capabilities capabilities) { |
| 2994 return classElement.accessors.where((PropertyAccessorElement accessor) { | 3196 return classElement.accessors.where((PropertyAccessorElement accessor) { |
| 2995 if (accessor.isPrivate) return false; | 3197 if (accessor.isPrivate) return false; |
| 2996 Function capabilityChecker = accessor.isStatic | 3198 Function capabilityChecker = accessor.isStatic |
| 2997 ? capabilities.supportsStaticInvoke | 3199 ? capabilities.supportsStaticInvoke |
| 2998 : capabilities.supportsInstanceInvoke; | 3200 : capabilities.supportsInstanceInvoke; |
| 2999 return capabilityChecker(accessor.name, accessor.metadata); | 3201 return capabilityChecker(accessor.name, accessor.metadata); |
| 3000 }); | 3202 }); |
| 3001 } | 3203 } |
| 3002 | 3204 |
| 3003 Iterable<ConstructorElement> _declaredConstructors( | 3205 Iterable<ConstructorElement> _declaredConstructors( |
| 3004 ClassElement classElement, _Capabilities capabilities) { | 3206 ClassElement classElement, _Capabilities capabilities) { |
| 3005 return classElement.constructors.where((ConstructorElement constructor) { | 3207 return classElement.constructors.where((ConstructorElement constructor) { |
| 3006 if (constructor.isPrivate) return false; | 3208 if (constructor.isPrivate) return false; |
| 3007 return capabilities.supportsNewInstance( | 3209 return capabilities.supportsNewInstance( |
| 3008 constructor.name, constructor.metadata); | 3210 constructor.name, constructor.metadata); |
| 3009 }); | 3211 }); |
| 3010 } | 3212 } |
| 3011 | 3213 |
| 3214 _LibraryDomain _createLibraryDomain( | |
| 3215 LibraryElement library, _ReflectorDomain domain) { | |
| 3216 List<TopLevelVariableElement> declaredVariablesOfLibrary = | |
| 3217 _extractDeclaredVariables(library, domain._capabilities).toList(); | |
| 3218 List<FunctionElement> declaredFunctionsOfLibrary = | |
| 3219 _extractDeclaredFunctions(library, domain._capabilities).toList(); | |
| 3220 List<PropertyAccessorElement> declaredAndImplicitAccessorsOfLibrary = | |
| 3221 _declaredAndImplicitLibraryAccessors(library, domain._capabilities); | |
| 3222 List<ParameterElement> declaredParametersOfLibrary = | |
| 3223 _extractDeclaredFunctionParameters( | |
| 3224 declaredFunctionsOfLibrary, declaredAndImplicitAccessorsOfLibrary); | |
| 3225 return new _LibraryDomain( | |
| 3226 library, | |
| 3227 declaredVariablesOfLibrary, | |
| 3228 declaredFunctionsOfLibrary, | |
| 3229 declaredParametersOfLibrary, | |
| 3230 declaredAndImplicitAccessorsOfLibrary, | |
| 3231 domain); | |
| 3232 } | |
| 3233 | |
| 3012 _ClassDomain _createClassDomain(ClassElement type, _ReflectorDomain domain) { | 3234 _ClassDomain _createClassDomain(ClassElement type, _ReflectorDomain domain) { |
| 3013 if (type is MixinApplication) { | 3235 if (type is MixinApplication) { |
| 3014 List<FieldElement> declaredFieldsOfClass = | 3236 List<FieldElement> declaredFieldsOfClass = |
| 3015 _extractDeclaredFields(type.mixin, domain._capabilities) | 3237 _extractDeclaredFields(type.mixin, domain._capabilities) |
| 3016 .where((FieldElement e) => !e.isStatic) | 3238 .where((FieldElement e) => !e.isStatic) |
| 3017 .toList(); | 3239 .toList(); |
| 3018 List<MethodElement> declaredMethodsOfClass = | 3240 List<MethodElement> declaredMethodsOfClass = |
| 3019 _extractDeclaredMethods(type.mixin, domain._capabilities) | 3241 _extractDeclaredMethods(type.mixin, domain._capabilities) |
| 3020 .where((MethodElement e) => !e.isStatic) | 3242 .where((MethodElement e) => !e.isStatic) |
| 3021 .toList(); | 3243 .toList(); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3109 String get name { | 3331 String get name { |
| 3110 if (declaredName != null) return declaredName; | 3332 if (declaredName != null) return declaredName; |
| 3111 if (superclass is MixinApplication) { | 3333 if (superclass is MixinApplication) { |
| 3112 return "${superclass.name}, ${_qualifiedName(mixin)}"; | 3334 return "${superclass.name}, ${_qualifiedName(mixin)}"; |
| 3113 } else { | 3335 } else { |
| 3114 return "${_qualifiedName(superclass)} with ${_qualifiedName(mixin)}"; | 3336 return "${_qualifiedName(superclass)} with ${_qualifiedName(mixin)}"; |
| 3115 } | 3337 } |
| 3116 } | 3338 } |
| 3117 | 3339 |
| 3118 @override | 3340 @override |
| 3341 String get displayName => name; | |
| 3342 | |
| 3343 @override | |
| 3119 List<InterfaceType> get interfaces => <InterfaceType>[]; | 3344 List<InterfaceType> get interfaces => <InterfaceType>[]; |
| 3120 | 3345 |
| 3121 @override | 3346 @override |
| 3122 List<ElementAnnotation> get metadata => <ElementAnnotation>[]; | 3347 List<ElementAnnotation> get metadata => <ElementAnnotation>[]; |
| 3123 | 3348 |
| 3124 @override | 3349 @override |
| 3125 bool get isSynthetic => declaredName != null; | 3350 bool get isSynthetic => declaredName == null; |
| 3126 | 3351 |
| 3127 // Note that the `InterfaceTypeImpl` may well call methods on this | 3352 // Note that the `InterfaceTypeImpl` may well call methods on this |
| 3128 // `MixinApplication` whose body is `_unImplemented()`, but it still provides | 3353 // `MixinApplication` whose body is `_unImplemented()`, but it still provides |
| 3129 // a slightly better service than leaving this method `_unImplemented()`: | 3354 // a slightly better service than leaving this method `_unImplemented()`: |
| 3130 // We are allowed to take one more step, which may be enough. | 3355 // We are allowed to take one more step, which may be enough. |
| 3131 @override | 3356 @override |
| 3132 InterfaceType get type => new InterfaceTypeImpl(this); | 3357 InterfaceType get type => new InterfaceTypeImpl(this); |
| 3133 | 3358 |
| 3134 @override | 3359 @override |
| 3135 InterfaceType get supertype { | 3360 InterfaceType get supertype { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 3148 } | 3373 } |
| 3149 | 3374 |
| 3150 /// Returns true iff this class was declared using the syntax | 3375 /// Returns true iff this class was declared using the syntax |
| 3151 /// `class B = A with M;`, i.e., if it is an explicitly named mixin | 3376 /// `class B = A with M;`, i.e., if it is an explicitly named mixin |
| 3152 /// application. We do not create instances of this class in that | 3377 /// application. We do not create instances of this class in that |
| 3153 /// case. | 3378 /// case. |
| 3154 @override | 3379 @override |
| 3155 bool get isMixinApplication => declaredName != null; | 3380 bool get isMixinApplication => declaredName != null; |
| 3156 | 3381 |
| 3157 @override | 3382 @override |
| 3383 bool get isAbstract => !isMixinApplication || mixin.isAbstract; | |
| 3384 | |
| 3385 @override | |
| 3386 // TODO(eernst) clarify: Is this test correct? Are all cases possible? | |
| 3387 bool get isEnum => mixin.isEnum || superclass.isEnum; | |
|
sigurdm
2015/10/09 07:52:04
As I understand it you cannot mix an enum in or su
eernst
2015/10/09 10:09:04
Yep, the spec confirms that. Removed the comment,
| |
| 3388 | |
| 3389 @override | |
| 3158 NamedCompilationUnitMember computeNode() => | 3390 NamedCompilationUnitMember computeNode() => |
| 3159 declaredName != null ? subclass.computeNode() : null; | 3391 declaredName != null ? subclass.computeNode() : null; |
| 3160 | 3392 |
| 3161 @override | 3393 @override |
| 3162 bool operator ==(Object object) { | 3394 bool operator ==(Object object) { |
| 3163 return object is MixinApplication && | 3395 return object is MixinApplication && |
| 3164 superclass == object.superclass && | 3396 superclass == object.superclass && |
| 3165 mixin == object.mixin && | 3397 mixin == object.mixin && |
| 3166 library == object.library && | 3398 library == object.library && |
| 3167 subclass == object.subclass; | 3399 subclass == object.subclass; |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 3189 @override | 3421 @override |
| 3190 bool get hasNonFinalField => _unImplemented(); | 3422 bool get hasNonFinalField => _unImplemented(); |
| 3191 | 3423 |
| 3192 @override | 3424 @override |
| 3193 bool get hasReferenceToSuper => _unImplemented(); | 3425 bool get hasReferenceToSuper => _unImplemented(); |
| 3194 | 3426 |
| 3195 @override | 3427 @override |
| 3196 bool get hasStaticMember => _unImplemented(); | 3428 bool get hasStaticMember => _unImplemented(); |
| 3197 | 3429 |
| 3198 @override | 3430 @override |
| 3199 bool get isAbstract => _unImplemented(); | |
| 3200 | |
| 3201 @override | |
| 3202 bool get isEnum => _unImplemented(); | |
| 3203 | |
| 3204 @override | |
| 3205 bool get isOrInheritsProxy => _unImplemented(); | 3431 bool get isOrInheritsProxy => _unImplemented(); |
| 3206 | 3432 |
| 3207 @override | 3433 @override |
| 3208 bool get isProxy => _unImplemented(); | 3434 bool get isProxy => _unImplemented(); |
| 3209 | 3435 |
| 3210 @override | 3436 @override |
| 3211 bool get isTypedef => _unImplemented(); | 3437 bool get isTypedef => _unImplemented(); |
| 3212 | 3438 |
| 3213 @override | 3439 @override |
| 3214 bool get isValidMixin => _unImplemented(); | 3440 bool get isValidMixin => _unImplemented(); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3290 } | 3516 } |
| 3291 | 3517 |
| 3292 // This seems to be the defined behaviour according to dart:mirrors. | 3518 // This seems to be the defined behaviour according to dart:mirrors. |
| 3293 @override | 3519 @override |
| 3294 bool get isPrivate => false; | 3520 bool get isPrivate => false; |
| 3295 | 3521 |
| 3296 @override | 3522 @override |
| 3297 get context => _unImplemented(); | 3523 get context => _unImplemented(); |
| 3298 | 3524 |
| 3299 @override | 3525 @override |
| 3300 String get displayName => _unImplemented(); | |
| 3301 | |
| 3302 @override | |
| 3303 Element get enclosingElement => _unImplemented(); | 3526 Element get enclosingElement => _unImplemented(); |
| 3304 | 3527 |
| 3305 @override | 3528 @override |
| 3306 int get id => _unImplemented(); | 3529 int get id => _unImplemented(); |
| 3307 | 3530 |
| 3308 @override | 3531 @override |
| 3309 bool get isDeprecated => _unImplemented(); | 3532 bool get isDeprecated => _unImplemented(); |
| 3310 | 3533 |
| 3311 @override | 3534 @override |
| 3312 bool get isOverride => _unImplemented(); | 3535 bool get isOverride => _unImplemented(); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3349 | 3572 |
| 3350 @override | 3573 @override |
| 3351 void visitChildren(ElementVisitor visitor) => _unImplemented(); | 3574 void visitChildren(ElementVisitor visitor) => _unImplemented(); |
| 3352 } | 3575 } |
| 3353 | 3576 |
| 3354 String _qualifiedName(ClassElement classElement) { | 3577 String _qualifiedName(ClassElement classElement) { |
| 3355 return classElement == null | 3578 return classElement == null |
| 3356 ? "null" | 3579 ? "null" |
| 3357 : "${classElement.library.name}.${classElement.name}"; | 3580 : "${classElement.library.name}.${classElement.name}"; |
| 3358 } | 3581 } |
| 3582 | |
| 3583 String _qualifiedFunctionName(FunctionElement functionElement) { | |
| 3584 return functionElement == null | |
| 3585 ? "null" | |
| 3586 : "${functionElement.library.name}.${functionElement.name}"; | |
| 3587 } | |
| OLD | NEW |