| Index: reflectable/lib/src/transformer_implementation.dart
|
| diff --git a/reflectable/lib/src/transformer_implementation.dart b/reflectable/lib/src/transformer_implementation.dart
|
| index 8e7db3d0651339f53ed92cacb2a2b8716e1d0cf2..8a89fbe792f3eb0c75a26ff8354a6681adc17ec1 100644
|
| --- a/reflectable/lib/src/transformer_implementation.dart
|
| +++ b/reflectable/lib/src/transformer_implementation.dart
|
| @@ -815,7 +815,7 @@ class _ReflectorDomain {
|
| // Generate code for listing [Type] instances.
|
| String typesCode =
|
| _formatAsConstList("Type", classes.map((ClassElement classElement) {
|
| - return _typeCodeOfClass(classElement, importCollector);
|
| + return _dynamicTypeCodeOfClass(classElement, importCollector);
|
| }));
|
|
|
| // Generate code for creation of library mirrors.
|
| @@ -1139,6 +1139,10 @@ class _ReflectorDomain {
|
| .map(indexOf));
|
| }
|
|
|
| + String dynamicReflectedTypeCode =
|
| + "${importCollector._getPrefix(classElement.library)}"
|
| + "${classElement.name}";
|
| +
|
| return 'new r.GenericClassMirrorImpl(r"${classDomain._simpleName}", '
|
| 'r"${_qualifiedName(classElement)}", $descriptor, $classIndex, '
|
| '${_constConstructionCode(importCollector)}, '
|
| @@ -1146,7 +1150,7 @@ class _ReflectorDomain {
|
| '$superclassIndex, $staticGettersCode, $staticSettersCode, '
|
| '$constructorsCode, $ownerIndex, $mixinIndex, '
|
| '$superinterfaceIndices, $classMetadataCode, $isCheckCode, '
|
| - '$typeParameterIndices)';
|
| + '$typeParameterIndices, $dynamicReflectedTypeCode)';
|
| }
|
| }
|
|
|
| @@ -1169,17 +1173,23 @@ class _ReflectorDomain {
|
| String reflectedTypeCode = reflectedTypeRequested
|
| ? _typeCode(accessorElement.variable.type, importCollector)
|
| : "null";
|
| + String dynamicReflectedTypeCode = reflectedTypeRequested
|
| + ? _dynamicTypeCodeOrNull(
|
| + accessorElement.variable.type, importCollector)
|
| + : "null";
|
| // The `indexOf` is non-null: `accessorElement` came from `members`.
|
| int selfIndex = members.indexOf(accessorElement) + fields.length;
|
| if (accessorElement.isGetter) {
|
| return 'new r.ImplicitGetterMirrorImpl('
|
| '${_constConstructionCode(importCollector)}, '
|
| - '$variableMirrorIndex, $reflectedTypeCode, $selfIndex)';
|
| + '$variableMirrorIndex, $reflectedTypeCode, '
|
| + '$dynamicReflectedTypeCode, $selfIndex)';
|
| } else {
|
| assert(accessorElement.isSetter);
|
| return 'new r.ImplicitSetterMirrorImpl('
|
| '${_constConstructionCode(importCollector)}, '
|
| - '$variableMirrorIndex, $reflectedTypeCode, $selfIndex)';
|
| + '$variableMirrorIndex, $reflectedTypeCode, '
|
| + '$dynamicReflectedTypeCode, $selfIndex)';
|
| }
|
| } else {
|
| // [element] is a method, a function, or an explicitly declared
|
| @@ -1194,14 +1204,17 @@ class _ReflectorDomain {
|
| String reflectedReturnTypeCode = element.returnType.isVoid
|
| ? "null"
|
| : _typeCode(element.returnType, importCollector);
|
| + String dynamicReflectedReturnTypeCode = element.returnType.isVoid
|
| + ? "null"
|
| + : _dynamicTypeCodeOrNull(element.returnType, importCollector);
|
| String metadataCode = _capabilities._supportsMetadata
|
| ? _extractMetadataCode(
|
| element, _resolver, importCollector, logger, _generatedLibraryId)
|
| : null;
|
| return 'new r.MethodMirrorImpl(r"${element.name}", $descriptor, '
|
| '$ownerIndex, $returnTypeIndex, $reflectedReturnTypeCode, '
|
| - '$parameterIndicesCode, ${_constConstructionCode(importCollector)}, '
|
| - '$metadataCode)';
|
| + '$dynamicReflectedReturnTypeCode, $parameterIndicesCode, '
|
| + '${_constConstructionCode(importCollector)}, $metadataCode)';
|
| }
|
| }
|
|
|
| @@ -1217,6 +1230,9 @@ class _ReflectorDomain {
|
| String reflectedTypeCode = reflectedTypeRequested
|
| ? _typeCode(element.type, importCollector)
|
| : "null";
|
| + String dynamicReflectedTypeCode = reflectedTypeRequested
|
| + ? _dynamicTypeCodeOrNull(element.type, importCollector)
|
| + : "null";
|
| String metadataCode;
|
| if (_capabilities._supportsMetadata) {
|
| metadataCode = _extractMetadataCode(
|
| @@ -1228,7 +1244,8 @@ class _ReflectorDomain {
|
| }
|
| return 'new r.VariableMirrorImpl(r"${element.name}", $descriptor, '
|
| '$ownerIndex, ${_constConstructionCode(importCollector)}, '
|
| - '$classMirrorIndex, $reflectedTypeCode, $metadataCode)';
|
| + '$classMirrorIndex, $reflectedTypeCode, '
|
| + '$dynamicReflectedTypeCode, $metadataCode)';
|
| }
|
|
|
| String _fieldMirrorCode(
|
| @@ -1242,6 +1259,9 @@ class _ReflectorDomain {
|
| String reflectedTypeCode = reflectedTypeRequested
|
| ? _typeCode(element.type, importCollector)
|
| : "null";
|
| + String dynamicReflectedTypeCode = reflectedTypeRequested
|
| + ? _dynamicTypeCodeOrNull(element.type, importCollector)
|
| + : "null";
|
| String metadataCode;
|
| if (_capabilities._supportsMetadata) {
|
| metadataCode = _extractMetadataCode(
|
| @@ -1253,7 +1273,8 @@ class _ReflectorDomain {
|
| }
|
| return 'new r.VariableMirrorImpl(r"${element.name}", $descriptor, '
|
| '$ownerIndex, ${_constConstructionCode(importCollector)}, '
|
| - '$classMirrorIndex, $reflectedTypeCode, $metadataCode)';
|
| + '$classMirrorIndex, $reflectedTypeCode, '
|
| + '$dynamicReflectedTypeCode, $metadataCode)';
|
| }
|
|
|
| String _typeCode(DartType dartType, _ImportCollector importCollector) {
|
| @@ -1262,19 +1283,140 @@ class _ReflectorDomain {
|
| return 'const r.FakeType(r"${_qualifiedName(owningClassElement)}.'
|
| '${dartType.element}")';
|
| }
|
| - return _typeCodeOfClass(dartType.element, importCollector);
|
| + return _typeCodeOfClass(dartType, importCollector);
|
| + }
|
| +
|
| + /// Returns a string containing code that in the generated library will
|
| + /// evaluate to a [Type] value like the value we would have obtained by
|
| + /// evaluating the [typeDefiningElement] as an expression in the library
|
| + /// where it occurs, but with all type arguments erased to `dynamic`.
|
| + /// Furthermore, return "null" for non-generic classes (that is used to
|
| + /// avoid duplication of identical expressions). [importCollector] is used
|
| + /// to find the library prefixes needed in order to obtain values from other
|
| + /// libraries.
|
| + String _dynamicTypeCodeOrNull(
|
| + DartType dartType, _ImportCollector importCollector) {
|
| + if (dartType is InterfaceType) {
|
| + return dartType.typeArguments.isEmpty
|
| + ? "null"
|
| + : _dynamicTypeCodeOfClass(dartType.element, importCollector);
|
| + }
|
| + // Not an interface type, let `_dynamicTypeCodeOfClass` handle it.
|
| + return _dynamicTypeCodeOfClass(dartType.element, importCollector);
|
| + }
|
| +
|
| + /// Returns true iff the given [type] is not and does not contain a type
|
| + /// variable.
|
| + bool _isTypeVariableFree(DartType type) {
|
| + if (type is TypeParameterType) return false;
|
| + if (type is InterfaceType) {
|
| + if (type.typeArguments.isEmpty) return true;
|
| + return type.typeArguments.every(_isTypeVariableFree);
|
| + }
|
| + // Possible kinds of types at this point (apart from several types
|
| + // indicating an error that we do not expect here): `BottomTypeImpl`,
|
| + // `DynamicTypeImpl`, `FunctionTypeImpl`, `VoidTypeImpl`. None of these
|
| + // have type variables.
|
| + return true;
|
| }
|
|
|
| - String _typeCodeOfClass(TypeDefiningElement typeDefiningElement,
|
| + /// Returns a string containing a type expression that in the generated
|
| + /// library will serve as a type argument with the same meaning as the
|
| + /// [classElement] has where it occurs. The [importCollector] is used to
|
| + /// find the library prefixes needed in order to obtain values from other
|
| + /// libraries.
|
| + String _typeCodeOfTypeArgument(
|
| + DartType dartType, _ImportCollector importCollector) {
|
| + fail() {
|
| + return unimplementedError(
|
| + "Attempt to generate code for an unsupported kind of type $dartType");
|
| + }
|
| +
|
| + if (dartType.isDynamic) return "dynamic";
|
| + if (dartType is InterfaceType) {
|
| + ClassElement classElement = dartType.element;
|
| + if ((classElement is MixinApplication &&
|
| + classElement.declaredName == null) ||
|
| + classElement.isPrivate) {
|
| + throw fail();
|
| + }
|
| + String prefix = importCollector._getPrefix(classElement.library);
|
| + if (classElement.typeParameters.isEmpty) {
|
| + return "$prefix${classElement.name}";
|
| + } else {
|
| + if (dartType.typeArguments.every(_isTypeVariableFree)) {
|
| + String arguments = dartType.typeArguments
|
| + .map((DartType typeArgument) =>
|
| + _typeCodeOfTypeArgument(typeArgument, importCollector))
|
| + .join(', ');
|
| + return "$prefix${classElement.name}<$arguments>";
|
| + } else {
|
| + throw fail();
|
| + }
|
| + }
|
| + } else {
|
| + throw fail();
|
| + }
|
| + }
|
| +
|
| + /// Returns a string containing code that in the generated library will
|
| + /// evaluate to a [Type] value like the value we would have obtained by
|
| + /// evaluating the [typeDefiningElement] as an expression in the library
|
| + /// where it occurs. [importCollector] is used to find the library prefixes
|
| + /// needed in order to obtain values from other libraries.
|
| + String _typeCodeOfClass(DartType dartType, _ImportCollector importCollector) {
|
| + if (dartType.isDynamic) return "dynamic";
|
| + if (dartType is InterfaceType) {
|
| + ClassElement classElement = dartType.element;
|
| + if ((classElement is MixinApplication &&
|
| + classElement.declaredName == null) ||
|
| + classElement.isPrivate) {
|
| + return 'const r.FakeType(r"${_qualifiedName(classElement)}")';
|
| + }
|
| + String prefix = importCollector._getPrefix(classElement.library);
|
| + if (classElement.typeParameters.isEmpty) {
|
| + return "$prefix${classElement.name}";
|
| + } else {
|
| + if (dartType.typeArguments.every(_isTypeVariableFree)) {
|
| + return "const m.TypeValue"
|
| + "<${_typeCodeOfTypeArgument(dartType, importCollector)}>().type";
|
| + } else {
|
| + String arguments = dartType.typeArguments
|
| + .map((DartType typeArgument) => typeArgument.toString())
|
| + .join(', ');
|
| + return 'const r.FakeType('
|
| + 'r"${_qualifiedName(classElement)}<$arguments>")';
|
| + }
|
| + }
|
| + } else {
|
| + throw unimplementedError(
|
| + "Attempt to generate code for an unsupported kind of type $dartType");
|
| + }
|
| + }
|
| +
|
| + /// Returns a string containing code that in the generated library will
|
| + /// evaluate to a [Type] value like the value we would have obtained by
|
| + /// evaluating the [typeDefiningElement] as an expression in the library
|
| + /// where it occurs, except that all type arguments are stripped such
|
| + /// that we get the fully dynamic instantiation if it is a generic class.
|
| + /// [importCollector] is used to find the library prefixes needed in order
|
| + /// to obtain values from other libraries.
|
| + String _dynamicTypeCodeOfClass(TypeDefiningElement typeDefiningElement,
|
| _ImportCollector importCollector) {
|
| - if ((typeDefiningElement is MixinApplication &&
|
| - typeDefiningElement.declaredName == null) ||
|
| - typeDefiningElement.isPrivate) {
|
| + DartType type = typeDefiningElement.type;
|
| + if (type.isDynamic) return "dynamic";
|
| + if (type is InterfaceType) {
|
| + ClassElement classElement = type.element;
|
| + if ((classElement is MixinApplication &&
|
| + classElement.declaredName == null) ||
|
| + classElement.isPrivate) {
|
| + return 'const r.FakeType(r"${_qualifiedName(classElement)}")';
|
| + }
|
| + String prefix = importCollector._getPrefix(classElement.library);
|
| + return "$prefix${classElement.name}";
|
| + } else {
|
| return 'const r.FakeType(r"${_qualifiedName(typeDefiningElement)}")';
|
| }
|
| - if (typeDefiningElement.type.isDynamic) return "dynamic";
|
| - String prefix = importCollector._getPrefix(typeDefiningElement.library);
|
| - return "$prefix${typeDefiningElement.name}";
|
| }
|
|
|
| String _libraryMirrorCode(
|
| @@ -1373,6 +1515,9 @@ class _ReflectorDomain {
|
| String reflectedTypeCode = reflectedTypeRequested
|
| ? _typeCode(element.type, importCollector)
|
| : "null";
|
| + String dynamicReflectedTypeCode = reflectedTypeRequested
|
| + ? _dynamicTypeCodeOrNull(element.type, importCollector)
|
| + : "null";
|
| String metadataCode = "null";
|
| if (_capabilities._supportsMetadata) {
|
| FormalParameter node = element.computeNode();
|
| @@ -1397,8 +1542,8 @@ class _ReflectorDomain {
|
| }
|
| return 'new r.ParameterMirrorImpl(r"${element.name}", $descriptor, '
|
| '$ownerIndex, ${_constConstructionCode(importCollector)}, '
|
| - '$classMirrorIndex, $reflectedTypeCode, $metadataCode, '
|
| - '$defaultValueCode)';
|
| + '$classMirrorIndex, $reflectedTypeCode, $dynamicReflectedTypeCode, '
|
| + '$metadataCode, $defaultValueCode)';
|
| }
|
| }
|
|
|
| @@ -2222,7 +2367,8 @@ class _ImportCollector {
|
| Map<LibraryElement, String> _mapping = <LibraryElement, String>{};
|
| int _count = 0;
|
|
|
| - /// Returns the prefix associated with [library].
|
| + /// Returns the prefix associated with [library]. Iff it is non-empty
|
| + /// it includes the period.
|
| String _getPrefix(LibraryElement library) {
|
| if (library.isDartCore) return "";
|
| String prefix = _mapping[library];
|
|
|