Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: reflectable/lib/src/transformer_implementation.dart

Issue 1391543003: Creates `reflectors`, as a meta-meta feature that enables dynamic selection of a "mirror system". (Closed) Base URL: https://github.com/dart-lang/reflectable.git@master
Patch Set: Added lots of LibraryMirror support in order to make reflectors work in transformed code Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698