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 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 Iterable<_ClassDomain> get domains => elementToDomain.values; | 357 Iterable<_ClassDomain> get domains => elementToDomain.values; |
358 } | 358 } |
359 | 359 |
360 /// Information about the program parts that can be reflected by a given | 360 /// Information about the program parts that can be reflected by a given |
361 /// Reflector. | 361 /// Reflector. |
362 class _ReflectorDomain { | 362 class _ReflectorDomain { |
363 final Resolver _resolver; | 363 final Resolver _resolver; |
364 final AssetId _generatedLibraryId; | 364 final AssetId _generatedLibraryId; |
365 final ClassElement _reflector; | 365 final ClassElement _reflector; |
366 | 366 |
367 /// Do not use this, use [classes] which ensures that closures operations | 367 /// Do not use this, use [classes] which ensures that closure operations |
368 /// have been performed as requested in [_capabilities]. Exception: In | 368 /// have been performed as requested in [_capabilities]. Exception: In |
369 /// `_computeWorld`, [_classes] is filled in with the set of directly | 369 /// `_computeWorld`, [_classes] is filled in with the set of directly |
370 /// covered classes during creation of this [_ReflectorDomain]. | 370 /// covered classes during creation of this [_ReflectorDomain]. |
371 /// NB: [_classes] should be final, but it is not possible because this | 371 /// NB: [_classes] should be final, but it is not possible because this |
372 /// would create a cycle of final fields, which cannot be initialized. | 372 /// would create a cycle of final fields, which cannot be initialized. |
373 ClassElementEnhancedSet _classes; | 373 ClassElementEnhancedSet _classes; |
374 | 374 |
375 /// Used by [classes], only, to keep track of whether [_classes] has been | 375 /// Used by [classes], only, to keep track of whether [_classes] has been |
376 /// properly initialized by means of closure operations. | 376 /// properly initialized by means of closure operations. |
377 bool _classesInitialized = false; | 377 bool _classesInitialized = false; |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
535 // Class related collections. | 535 // Class related collections. |
536 Enumerator<FieldElement> fields = new Enumerator<FieldElement>(); | 536 Enumerator<FieldElement> fields = new Enumerator<FieldElement>(); |
537 Enumerator<ParameterElement> parameters = | 537 Enumerator<ParameterElement> parameters = |
538 new Enumerator<ParameterElement>(); | 538 new Enumerator<ParameterElement>(); |
539 Set<String> instanceGetterNames = new Set<String>(); | 539 Set<String> instanceGetterNames = new Set<String>(); |
540 Set<String> instanceSetterNames = new Set<String>(); | 540 Set<String> instanceSetterNames = new Set<String>(); |
541 | 541 |
542 // Library and class related collections. | 542 // Library and class related collections. |
543 Enumerator<ExecutableElement> members = new Enumerator<ExecutableElement>(); | 543 Enumerator<ExecutableElement> members = new Enumerator<ExecutableElement>(); |
544 | 544 |
545 // Fill in [libraries], [members], [fields], [parameters], | 545 /// Adds a library domain for [library] to [libraries], relying on checks |
546 // [instanceGetterNames], and [instanceSetterNames]. | 546 /// for importability and insertion into [importCollector] to have taken |
547 for (LibraryElement library in _libraries) { | 547 /// place already. |
| 548 void uncheckedAddLibrary(LibraryElement library) { |
548 _LibraryDomain libraryDomain = _createLibraryDomain(library, this); | 549 _LibraryDomain libraryDomain = _createLibraryDomain(library, this); |
549 libraries.add(libraryDomain); | 550 libraries.add(libraryDomain); |
550 libraryMap[library] = libraryDomain; | 551 libraryMap[library] = libraryDomain; |
551 libraryDomain._declarations.forEach(members.add); | 552 libraryDomain._declarations.forEach(members.add); |
552 libraryDomain._declaredParameters.forEach(parameters.add); | 553 libraryDomain._declaredParameters.forEach(parameters.add); |
553 libraryDomain._declaredVariables.forEach(topLevelVariables.add); | 554 libraryDomain._declaredVariables.forEach(topLevelVariables.add); |
554 } | 555 } |
| 556 |
| 557 /// Used to add a library domain for [library] to [libraries], checking |
| 558 /// that it is importable and registering it with [importCollector]. |
| 559 void addLibrary(LibraryElement library) { |
| 560 if (!_isImportableLibrary( |
| 561 library, _generatedLibraryId, _resolver)) return; |
| 562 importCollector._addLibrary(library); |
| 563 uncheckedAddLibrary(library); |
| 564 } |
| 565 |
| 566 // Fill in [libraries], [members], [fields], [parameters], |
| 567 // [instanceGetterNames], and [instanceSetterNames]. |
| 568 _libraries.forEach(uncheckedAddLibrary); |
| 569 classes.forEach((ClassElement classElement) { |
| 570 if (!libraries.items.any((_LibraryDomain libraryDomain) => |
| 571 libraryDomain._libraryElement == classElement.library)) { |
| 572 addLibrary(classElement.library); |
| 573 } |
| 574 }); |
555 for (_ClassDomain classDomain in classes.domains) { | 575 for (_ClassDomain classDomain in classes.domains) { |
556 // Gather the behavioral interface into [members]. Note that | 576 // Gather the behavioral interface into [members]. Note that |
557 // this includes implicitly generated getters and setters, but | 577 // this includes implicitly generated getters and setters, but |
558 // omits fields. Also note that this does not match the | 578 // omits fields. Also note that this does not match the |
559 // semantics of the `declarations` method in a [ClassMirror]. | 579 // semantics of the `declarations` method in a [ClassMirror]. |
560 classDomain._declarations.forEach(members.add); | 580 classDomain._declarations.forEach(members.add); |
561 | 581 |
562 // Add the behavioral interface from this class (redundantly, for | 582 // Add the behavioral interface from this class (redundantly, for |
563 // non-static members) and all superclasses (which matters) to | 583 // non-static members) and all superclasses (which matters) to |
564 // [members], such that it contains both the behavioral parts for | 584 // [members], such that it contains both the behavioral parts for |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
650 return _typeCodeOfClass(classElement, importCollector); | 670 return _typeCodeOfClass(classElement, importCollector); |
651 })); | 671 })); |
652 | 672 |
653 // Generate code for creation of library mirrors. | 673 // Generate code for creation of library mirrors. |
654 String librariesCode; | 674 String librariesCode; |
655 if (!_capabilities.supportsLibraries) { | 675 if (!_capabilities.supportsLibraries) { |
656 librariesCode = "null"; | 676 librariesCode = "null"; |
657 } else { | 677 } else { |
658 librariesCode = _formatAsList("m.LibraryMirror", | 678 librariesCode = _formatAsList("m.LibraryMirror", |
659 libraries.items.map((_LibraryDomain library) { | 679 libraries.items.map((_LibraryDomain library) { |
660 return _libraryMirrorCode(library, members, topLevelVariables, | 680 return _libraryMirrorCode(library, libraries.indexOf(library), members, |
661 fields.length, importCollector, logger); | 681 topLevelVariables, fields.length, importCollector, logger); |
662 })); | 682 })); |
663 } | 683 } |
664 | 684 |
665 // Generate code for creation of parameter mirrors. | 685 // Generate code for creation of parameter mirrors. |
666 Iterable<String> parametersList = | 686 Iterable<String> parametersList = |
667 parameters.items.map((ParameterElement element) { | 687 parameters.items.map((ParameterElement element) { |
668 return _parameterMirrorCode(element, fields, members, importCollector, | 688 return _parameterMirrorCode(element, fields, members, importCollector, |
669 logger, reflectedTypeRequested); | 689 logger, reflectedTypeRequested); |
670 }); | 690 }); |
671 String parameterMirrorsCode = | 691 String parameterMirrorsCode = |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
861 String classMetadataCode; | 881 String classMetadataCode; |
862 if (_capabilities._supportsMetadata) { | 882 if (_capabilities._supportsMetadata) { |
863 classMetadataCode = _extractMetadataCode(classElement, _resolver, | 883 classMetadataCode = _extractMetadataCode(classElement, _resolver, |
864 importCollector, logger, _generatedLibraryId); | 884 importCollector, logger, _generatedLibraryId); |
865 } else { | 885 } else { |
866 classMetadataCode = "null"; | 886 classMetadataCode = "null"; |
867 } | 887 } |
868 | 888 |
869 int classIndex = classes.indexOf(classElement); | 889 int classIndex = classes.indexOf(classElement); |
870 | 890 |
871 String result = 'new r.ClassMirrorImpl(r"${classDomain._simpleName}", ' | 891 return 'new r.ClassMirrorImpl(r"${classDomain._simpleName}", ' |
872 'r"${_qualifiedName(classElement)}", $descriptor, $classIndex, ' | 892 'r"${_qualifiedName(classElement)}", $descriptor, $classIndex, ' |
873 '${_constConstructionCode(importCollector)}, ' | 893 '${_constConstructionCode(importCollector)}, ' |
874 '$declarationsCode, $instanceMembersCode, $staticMembersCode, ' | 894 '$declarationsCode, $instanceMembersCode, $staticMembersCode, ' |
875 '$superclassIndex, $staticGettersCode, $staticSettersCode, ' | 895 '$superclassIndex, $staticGettersCode, $staticSettersCode, ' |
876 '$constructorsCode, $ownerIndex, $mixinIndex, ' | 896 '$constructorsCode, $ownerIndex, $mixinIndex, ' |
877 '$superinterfaceIndices, $classMetadataCode)'; | 897 '$superinterfaceIndices, $classMetadataCode)'; |
878 return result; | |
879 } | 898 } |
880 | 899 |
881 String _methodMirrorCode( | 900 String _methodMirrorCode( |
882 ExecutableElement element, | 901 ExecutableElement element, |
883 Enumerator<FieldElement> fields, | 902 Enumerator<FieldElement> fields, |
884 Enumerator<ExecutableElement> members, | 903 Enumerator<ExecutableElement> members, |
885 Enumerator<ParameterElement> parameters, | 904 Enumerator<ParameterElement> parameters, |
886 _ImportCollector importCollector, | 905 _ImportCollector importCollector, |
887 TransformLogger logger, | 906 TransformLogger logger, |
888 bool reflectedTypeRequested) { | 907 bool reflectedTypeRequested) { |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
956 if (dartType is TypeParameterType) { | 975 if (dartType is TypeParameterType) { |
957 ClassElement owningClassElement = dartType.element.enclosingElement; | 976 ClassElement owningClassElement = dartType.element.enclosingElement; |
958 return 'const r.FakeType(r"${_qualifiedName(owningClassElement)}.' | 977 return 'const r.FakeType(r"${_qualifiedName(owningClassElement)}.' |
959 '${dartType.element}")'; | 978 '${dartType.element}")'; |
960 } | 979 } |
961 return _typeCodeOfClass(dartType.element, importCollector); | 980 return _typeCodeOfClass(dartType.element, importCollector); |
962 } | 981 } |
963 | 982 |
964 String _typeCodeOfClass( | 983 String _typeCodeOfClass( |
965 ClassElement classElement, _ImportCollector importCollector) { | 984 ClassElement classElement, _ImportCollector importCollector) { |
966 if (classElement is MixinApplication && classElement.declaredName == null) { | 985 if ((classElement is MixinApplication && |
| 986 classElement.declaredName == null) || |
| 987 classElement.isPrivate) { |
967 return 'const r.FakeType(r"${_qualifiedName(classElement)}")'; | 988 return 'const r.FakeType(r"${_qualifiedName(classElement)}")'; |
968 } | 989 } |
969 if (classElement.type.isDynamic) return "dynamic"; | 990 if (classElement.type.isDynamic) return "dynamic"; |
970 String prefix = importCollector._getPrefix(classElement.library); | 991 String prefix = importCollector._getPrefix(classElement.library); |
971 return "$prefix.${classElement.name}"; | 992 return "$prefix.${classElement.name}"; |
972 } | 993 } |
973 | 994 |
974 String _libraryMirrorCode( | 995 String _libraryMirrorCode( |
975 _LibraryDomain libraryDomain, | 996 _LibraryDomain libraryDomain, |
| 997 int libraryIndex, |
976 Enumerator<ExecutableElement> members, | 998 Enumerator<ExecutableElement> members, |
977 Enumerator<TopLevelVariableElement> variables, | 999 Enumerator<TopLevelVariableElement> variables, |
978 int fieldsLength, | 1000 int fieldsLength, |
979 _ImportCollector importCollector, | 1001 _ImportCollector importCollector, |
980 TransformLogger logger) { | 1002 TransformLogger logger) { |
981 LibraryElement library = libraryDomain._libraryElement; | 1003 LibraryElement library = libraryDomain._libraryElement; |
982 | 1004 |
983 String gettersCode = _formatAsMap( | 1005 String gettersCode = _formatAsMap( |
984 _gettersOfLibrary(libraryDomain).map((PropertyAccessorElement getter) { | 1006 _gettersOfLibrary(libraryDomain).map((PropertyAccessorElement getter) { |
985 return _topLevelGettingClosure(importCollector, library, getter.name); | 1007 return _topLevelGettingClosure(importCollector, library, getter.name); |
(...skipping 24 matching lines...) Expand all Loading... |
1010 String declarationsCode = "const <int>[${constants.NO_CAPABILITY_INDEX}]"; | 1032 String declarationsCode = "const <int>[${constants.NO_CAPABILITY_INDEX}]"; |
1011 if (_capabilities._impliesDeclarations) { | 1033 if (_capabilities._impliesDeclarations) { |
1012 List<int> declarationsIndices = <int>[] | 1034 List<int> declarationsIndices = <int>[] |
1013 ..addAll(variableIndices) | 1035 ..addAll(variableIndices) |
1014 ..addAll(methodsIndices); | 1036 ..addAll(methodsIndices); |
1015 declarationsCode = _formatAsConstList("int", declarationsIndices); | 1037 declarationsCode = _formatAsConstList("int", declarationsIndices); |
1016 } | 1038 } |
1017 | 1039 |
1018 // TODO(sigurdm) clarify: Find out how to get good uri's in a | 1040 // TODO(sigurdm) clarify: Find out how to get good uri's in a |
1019 // transformer. | 1041 // transformer. |
1020 // TODO(sigurdm) implement: Check for `uriCapability`. | 1042 String uriCode = (_capabilities._supportsUri || |
1021 String uriCode = "null"; | 1043 _capabilities.supportsLibraries) |
| 1044 ? 'Uri.parse(r"reflectable://$libraryIndex/$library")' |
| 1045 : 'null'; |
1022 | 1046 |
1023 String metadataCode; | 1047 String metadataCode; |
1024 if (_capabilities._supportsMetadata) { | 1048 if (_capabilities._supportsMetadata) { |
1025 metadataCode = _extractMetadataCode( | 1049 metadataCode = _extractMetadataCode( |
1026 library, _resolver, importCollector, logger, _generatedLibraryId); | 1050 library, _resolver, importCollector, logger, _generatedLibraryId); |
1027 } else { | 1051 } else { |
1028 metadataCode = "null"; | 1052 metadataCode = "null"; |
1029 } | 1053 } |
1030 | 1054 |
1031 return 'new r.LibraryMirrorImpl(r"${library.name}", $uriCode, ' | 1055 return 'new r.LibraryMirrorImpl(r"${library.name}", $uriCode, ' |
(...skipping 817 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1849 methodName, | 1873 methodName, |
1850 _getEvaluatedMetadata(metadata), | 1874 _getEvaluatedMetadata(metadata), |
1851 getterMetadata == null ? null : _getEvaluatedMetadata(getterMetadata)); | 1875 getterMetadata == null ? null : _getEvaluatedMetadata(getterMetadata)); |
1852 } | 1876 } |
1853 | 1877 |
1854 bool get _supportsMetadata { | 1878 bool get _supportsMetadata { |
1855 return _capabilities.any((ec.ReflectCapability capability) => | 1879 return _capabilities.any((ec.ReflectCapability capability) => |
1856 capability == ec.metadataCapability); | 1880 capability == ec.metadataCapability); |
1857 } | 1881 } |
1858 | 1882 |
| 1883 bool get _supportsUri { |
| 1884 return _capabilities.any( |
| 1885 (ec.ReflectCapability capability) => capability == ec.uriCapability); |
| 1886 } |
| 1887 |
1859 /// Returns [true] iff these [Capabilities] specify reflection support | 1888 /// Returns [true] iff these [Capabilities] specify reflection support |
1860 /// where the set of classes must be downwards closed, i.e., extra classes | 1889 /// where the set of classes must be downwards closed, i.e., extra classes |
1861 /// must be added beyond the ones that are directly covered by the given | 1890 /// must be added beyond the ones that are directly covered by the given |
1862 /// metadata and global quantifiers, such that coverage on a class `C` | 1891 /// metadata and global quantifiers, such that coverage on a class `C` |
1863 /// implies coverage of every class `D` such that `D` is a subtype of `C`. | 1892 /// implies coverage of every class `D` such that `D` is a subtype of `C`. |
1864 bool get _impliesDownwardsClosure { | 1893 bool get _impliesDownwardsClosure { |
1865 return _capabilities.any((ec.ReflectCapability capability) => | 1894 return _capabilities.any((ec.ReflectCapability capability) => |
1866 capability == ec.subtypeQuantifyCapability); | 1895 capability == ec.subtypeQuantifyCapability); |
1867 } | 1896 } |
1868 | 1897 |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2277 assert(_isImportableLibrary(reflector.library, dataId, _resolver)); | 2306 assert(_isImportableLibrary(reflector.library, dataId, _resolver)); |
2278 importCollector._addLibrary(reflector.library); | 2307 importCollector._addLibrary(reflector.library); |
2279 return new _ReflectorDomain(_resolver, dataId, reflector, capabilities); | 2308 return new _ReflectorDomain(_resolver, dataId, reflector, capabilities); |
2280 }); | 2309 }); |
2281 } | 2310 } |
2282 | 2311 |
2283 /// Adds [library] to the supported libraries of [reflector]. | 2312 /// Adds [library] to the supported libraries of [reflector]. |
2284 void addLibrary(LibraryElement library, ClassElement reflector) { | 2313 void addLibrary(LibraryElement library, ClassElement reflector) { |
2285 _ReflectorDomain domain = getReflectorDomain(reflector); | 2314 _ReflectorDomain domain = getReflectorDomain(reflector); |
2286 if (domain._capabilities.supportsLibraries) { | 2315 if (domain._capabilities.supportsLibraries) { |
2287 assert(_isImportableLibrary(reflector.library, dataId, _resolver)); | 2316 assert(_isImportableLibrary(library, dataId, _resolver)); |
2288 importCollector._addLibrary(library); | 2317 importCollector._addLibrary(library); |
2289 domain._libraries.add(library); | 2318 domain._libraries.add(library); |
2290 } | 2319 } |
2291 } | 2320 } |
2292 | 2321 |
2293 /// Adds a [_ClassDomain] representing [type] to the supported classes of | 2322 /// Adds a [_ClassDomain] representing [type] to the supported classes of |
2294 /// [reflector]; also adds the enclosing library of [type] to the | 2323 /// [reflector]; also adds the enclosing library of [type] to the |
2295 /// supported libraries. | 2324 /// supported libraries. |
2296 void addClassDomain(ClassElement type, ClassElement reflector) { | 2325 void addClassDomain(ClassElement type, ClassElement reflector) { |
2297 if (!_isImportable(type, dataId, _resolver)) { | 2326 if (!_isImportable(type, dataId, _resolver)) { |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2380 | 2409 |
2381 // Populate [globalPatterns] and [globalMetadata]. | 2410 // Populate [globalPatterns] and [globalMetadata]. |
2382 _findGlobalQuantifyAnnotations(globalPatterns, globalMetadata); | 2411 _findGlobalQuantifyAnnotations(globalPatterns, globalMetadata); |
2383 | 2412 |
2384 // Visits all libraries and all classes in the given entry point, | 2413 // Visits all libraries and all classes in the given entry point, |
2385 // gets their reflectors, and adds them to the domain of that | 2414 // gets their reflectors, and adds them to the domain of that |
2386 // reflector. | 2415 // reflector. |
2387 for (LibraryElement library in _resolver.libraries) { | 2416 for (LibraryElement library in _resolver.libraries) { |
2388 for (ClassElement reflector | 2417 for (ClassElement reflector |
2389 in getReflectors(library.name, library.metadata)) { | 2418 in getReflectors(library.name, library.metadata)) { |
2390 assert(_isImportableLibrary(reflector.library, dataId, _resolver)); | 2419 assert(_isImportableLibrary(library, dataId, _resolver)); |
2391 addLibrary(library, reflector); | 2420 addLibrary(library, reflector); |
2392 } | 2421 } |
2393 | 2422 |
2394 for (CompilationUnitElement unit in library.units) { | 2423 for (CompilationUnitElement unit in library.units) { |
2395 for (ClassElement type in unit.types) { | 2424 for (ClassElement type in unit.types) { |
2396 for (ClassElement reflector | 2425 for (ClassElement reflector |
2397 in getReflectors(_qualifiedName(type), type.metadata)) { | 2426 in getReflectors(_qualifiedName(type), type.metadata)) { |
2398 addClassDomain(type, reflector); | 2427 addClassDomain(type, reflector); |
2399 } | 2428 } |
2400 } | 2429 } |
(...skipping 1283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3684 return classElement == null | 3713 return classElement == null |
3685 ? "null" | 3714 ? "null" |
3686 : "${classElement.library.name}.${classElement.name}"; | 3715 : "${classElement.library.name}.${classElement.name}"; |
3687 } | 3716 } |
3688 | 3717 |
3689 String _qualifiedFunctionName(FunctionElement functionElement) { | 3718 String _qualifiedFunctionName(FunctionElement functionElement) { |
3690 return functionElement == null | 3719 return functionElement == null |
3691 ? "null" | 3720 ? "null" |
3692 : "${functionElement.library.name}.${functionElement.name}"; | 3721 : "${functionElement.library.name}.${functionElement.name}"; |
3693 } | 3722 } |
OLD | NEW |