| // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| part of dart2js.mirrors; |
| |
| abstract class ClassMirrorMixin implements ClassSourceMirror { |
| bool get hasReflectedType => false; |
| Type get reflectedType { |
| throw new UnsupportedError("ClassMirror.reflectedType is not supported."); |
| } |
| InstanceMirror newInstance(Symbol constructorName, |
| List positionalArguments, |
| [Map<Symbol, dynamic> namedArguments]) { |
| throw new UnsupportedError("ClassMirror.newInstance is not supported."); |
| } |
| } |
| |
| abstract class Dart2JsTypeMirror |
| implements Dart2JsDeclarationMirror, TypeSourceMirror { |
| DartType get _type; |
| |
| String get _simpleNameString => _type.name; |
| |
| Dart2JsDeclarationMirror get owner => library; |
| |
| Dart2JsLibraryMirror get library; |
| |
| bool get hasReflectedType => throw new UnimplementedError(); |
| |
| Type get reflectedType => throw new UnimplementedError(); |
| |
| bool get isOriginalDeclaration => true; |
| |
| TypeMirror get originalDeclaration => this; |
| |
| List<TypeMirror> get typeArguments => const <TypeMirror>[]; |
| |
| List<TypeVariableMirror> get typeVariables => const <TypeVariableMirror>[]; |
| |
| TypeMirror createInstantiation(List<TypeMirror> typeArguments) { |
| if (typeArguments.isEmpty) return this; |
| throw new ArgumentError('Cannot create generic instantiation of $_type.'); |
| } |
| |
| bool get isVoid => false; |
| |
| bool get isDynamic => false; |
| |
| bool isSubtypeOf(TypeMirror other) { |
| if (other is Dart2JsTypeMirror) { |
| return mirrorSystem.compiler.types.isSubtype(this._type, other._type); |
| } else { |
| throw new ArgumentError(other); |
| } |
| } |
| |
| bool isAssignableTo(TypeMirror other) { |
| if (other is Dart2JsTypeMirror) { |
| return mirrorSystem.compiler.types.isAssignable(this._type, other._type); |
| } else { |
| throw new ArgumentError(other); |
| } |
| } |
| |
| String toString() => _type.toString(); |
| |
| } |
| |
| /// Base implementations for mirrors on element based types. |
| abstract class Dart2JsTypeElementMirror |
| extends Dart2JsElementMirror |
| with Dart2JsTypeMirror |
| implements TypeSourceMirror { |
| final DartType _type; |
| |
| Dart2JsTypeElementMirror(Dart2JsMirrorSystem system, DartType type) |
| : super(system, type.element), |
| this._type = type; |
| |
| Dart2JsLibraryMirror get library { |
| return mirrorSystem._getLibrary(_type.element.library); |
| } |
| } |
| |
| abstract class DeclarationMixin implements TypeMirror { |
| |
| bool get isOriginalDeclaration => true; |
| |
| TypeMirror get originalDeclaration => this; |
| |
| List<TypeMirror> get typeArguments => const <TypeMirror>[]; |
| } |
| |
| abstract class Dart2JsGenericTypeMirror extends Dart2JsTypeElementMirror { |
| List<TypeMirror> _typeArguments; |
| List<TypeVariableMirror> _typeVariables; |
| |
| Dart2JsGenericTypeMirror(Dart2JsMirrorSystem system, GenericType type) |
| : super(system, type); |
| |
| TypeDeclarationElement get _element => super._element; |
| |
| GenericType get _type => super._type; |
| |
| bool get isOriginalDeclaration => false; |
| |
| TypeMirror get originalDeclaration => |
| mirrorSystem._getTypeDeclarationMirror(_element); |
| |
| List<TypeMirror> get typeArguments { |
| if (_typeArguments == null) { |
| _typeArguments = <TypeMirror>[]; |
| if (!_type.isRaw) { |
| for (DartType type in _type.typeArguments) { |
| _typeArguments.add(_getTypeMirror(type)); |
| } |
| } |
| } |
| return _typeArguments; |
| } |
| |
| List<TypeVariableMirror> get typeVariables { |
| if (_typeVariables == null) { |
| _typeVariables = <TypeVariableMirror>[]; |
| for (TypeVariableType typeVariable in _element.typeVariables) { |
| _typeVariables.add( |
| new Dart2JsTypeVariableMirror(mirrorSystem, typeVariable)); |
| } |
| } |
| return _typeVariables; |
| } |
| |
| Iterable<Dart2JsMemberMirror> _getDeclarationMirrors(Element element) { |
| if (element.isTypeVariable) { |
| assert(invariant(_element, _element == element.enclosingElement, |
| message: 'Foreigned type variable element $element.')); |
| for (Dart2JsTypeVariableMirror mirror in typeVariables) { |
| if (mirror._element == element) return [mirror]; |
| } |
| } |
| return super._getDeclarationMirrors(element); |
| } |
| |
| TypeMirror _getTypeMirror(DartType type) { |
| return super._getTypeMirror( |
| type.subst(_type.typeArguments, _type.element.typeVariables)); |
| } |
| |
| TypeSourceMirror createInstantiation( |
| List<TypeSourceMirror> newTypeArguments) { |
| if (newTypeArguments.isEmpty) return owner._getTypeMirror(_type.asRaw()); |
| if (newTypeArguments.length != typeVariables.length) { |
| throw new ArgumentError('Cannot create generic instantiation of $_type ' |
| 'with ${newTypeArguments.length} arguments, ' |
| 'expect ${typeVariables.length} arguments.'); |
| } |
| List<DartType> builder = <DartType>[]; |
| for (TypeSourceMirror newTypeArgument in newTypeArguments) { |
| if (newTypeArgument.isVoid) { |
| throw new ArgumentError('Cannot use void as type argument.'); |
| } |
| if (newTypeArgument is Dart2JsTypeMirror) { |
| builder.add(newTypeArgument._type); |
| } else { |
| throw new UnsupportedError( |
| 'Cannot create instantiation using a type ' |
| 'mirror from a different mirrorSystem implementation.'); |
| } |
| } |
| return owner._getTypeMirror(_type.createInstantiation(builder)); |
| } |
| } |
| |
| class Dart2JsInterfaceTypeMirror |
| extends Dart2JsGenericTypeMirror |
| with ObjectMirrorMixin, ClassMirrorMixin, ContainerMixin |
| implements ClassMirror { |
| Dart2JsInterfaceTypeMirror(Dart2JsMirrorSystem system, |
| InterfaceType interfaceType) |
| : super(system, interfaceType); |
| |
| ClassElement get _element => super._element; |
| |
| InterfaceType get _type => super._type; |
| |
| bool get isNameSynthetic { |
| if (_element.isMixinApplication) { |
| MixinApplicationElement mixinApplication = _element; |
| return mixinApplication.isUnnamedMixinApplication; |
| } |
| return false; |
| } |
| |
| void _forEachElement(f(Element element)) { |
| _element.forEachMember((_, element) => f(element)); |
| } |
| |
| ClassMirror get superclass { |
| if (_element.supertype != null) { |
| return _getTypeMirror(_element.supertype); |
| } |
| return null; |
| } |
| |
| bool isSubclassOf(Mirror other) { |
| if (other is Dart2JsTypeMirror) { |
| return other._type.element != null && |
| _element.isSubclassOf(other._type.element); |
| } else { |
| throw new ArgumentError(other); |
| } |
| } |
| |
| ClassMirror get mixin { |
| if (_element.isMixinApplication) { |
| MixinApplicationElement mixinApplication = _element; |
| return _getTypeMirror(mixinApplication.mixinType); |
| } |
| return this; |
| } |
| |
| List<ClassMirror> get superinterfaces { |
| var list = <ClassMirror>[]; |
| Link<DartType> link = _element.interfaces; |
| while (!link.isEmpty) { |
| var type = _getTypeMirror(link.head); |
| list.add(type); |
| link = link.tail; |
| } |
| return list; |
| } |
| |
| Map<Symbol, MethodMirror> get instanceMembers => null; |
| Map<Symbol, MethodMirror> get staticMembers => null; |
| |
| bool get isAbstract => _element.isAbstract; |
| |
| bool operator ==(other) { |
| if (identical(this, other)) { |
| return true; |
| } |
| if (other is! ClassMirror) { |
| return false; |
| } |
| return _type == other._type; |
| } |
| |
| String toString() => 'Mirror on interface type $_type'; |
| } |
| |
| class Dart2JsClassDeclarationMirror |
| extends Dart2JsInterfaceTypeMirror |
| with DeclarationMixin { |
| |
| Dart2JsClassDeclarationMirror(Dart2JsMirrorSystem system, |
| InterfaceType type) |
| : super(system, type); |
| |
| bool isSubclassOf(ClassMirror other) { |
| if (other is Dart2JsClassDeclarationMirror) { |
| Dart2JsClassDeclarationMirror otherDeclaration = |
| other.originalDeclaration; |
| return _element.isSubclassOf(otherDeclaration._element); |
| } else if (other is FunctionTypeMirror) { |
| return false; |
| } |
| throw new ArgumentError(other); |
| } |
| |
| String toString() => 'Mirror on class ${_type.name}'; |
| } |
| |
| class Dart2JsTypedefMirror |
| extends Dart2JsGenericTypeMirror |
| implements TypedefMirror { |
| final Dart2JsLibraryMirror _library; |
| List<TypeVariableMirror> _typeVariables; |
| var _definition; |
| |
| Dart2JsTypedefMirror(Dart2JsMirrorSystem system, TypedefType _typedef) |
| : this._library = system._getLibrary(_typedef.element.library), |
| super(system, _typedef); |
| |
| Dart2JsTypedefMirror.fromLibrary(Dart2JsLibraryMirror library, |
| TypedefType _typedef) |
| : this._library = library, |
| super(library.mirrorSystem, _typedef); |
| |
| TypedefType get _typedef => _type; |
| |
| LibraryMirror get library => _library; |
| |
| bool get isTypedef => true; |
| |
| FunctionTypeMirror get referent { |
| if (_definition == null) { |
| _definition = _getTypeMirror(_typedef.element.alias); |
| } |
| return _definition; |
| } |
| |
| bool get isClass => false; |
| |
| bool get isAbstract => false; |
| |
| String toString() => 'Mirror on typedef $_type'; |
| } |
| |
| class Dart2JsTypedefDeclarationMirror |
| extends Dart2JsTypedefMirror |
| with DeclarationMixin { |
| Dart2JsTypedefDeclarationMirror(Dart2JsMirrorSystem system, |
| TypedefType type) |
| : super(system, type); |
| |
| String toString() => 'Mirror on typedef ${_type.name}'; |
| } |
| |
| class Dart2JsTypeVariableMirror extends Dart2JsTypeElementMirror |
| implements TypeVariableMirror { |
| Dart2JsDeclarationMirror _owner; |
| |
| Dart2JsTypeVariableMirror(Dart2JsMirrorSystem system, |
| TypeVariableType typeVariableType) |
| : super(system, typeVariableType); |
| |
| TypeVariableType get _type => super._type; |
| |
| Dart2JsDeclarationMirror get owner { |
| if (_owner == null) { |
| _owner = mirrorSystem._getTypeDeclarationMirror( |
| _type.element.typeDeclaration); |
| } |
| return _owner; |
| } |
| |
| bool get isStatic => false; |
| |
| TypeMirror get upperBound => owner._getTypeMirror(_type.element.bound); |
| |
| bool operator ==(var other) { |
| if (identical(this, other)) { |
| return true; |
| } |
| if (other is! TypeVariableMirror) { |
| return false; |
| } |
| if (owner != other.owner) { |
| return false; |
| } |
| return qualifiedName == other.qualifiedName; |
| } |
| |
| String toString() => 'Mirror on type variable $_type'; |
| } |
| |
| class Dart2JsFunctionTypeMirror extends Dart2JsTypeElementMirror |
| with ObjectMirrorMixin, ClassMirrorMixin, DeclarationMixin |
| implements FunctionTypeMirror { |
| List<ParameterMirror> _parameters; |
| |
| Dart2JsFunctionTypeMirror(Dart2JsMirrorSystem system, |
| FunctionType functionType) |
| : super(system, functionType) { |
| assert (functionType.element != null); |
| } |
| |
| FunctionType get _type => super._type; |
| |
| // TODO(johnniwinther): Is this the qualified name of a function type? |
| Symbol get qualifiedName => originalDeclaration.qualifiedName; |
| |
| // TODO(johnniwinther): Substitute type arguments for type variables. |
| Map<Symbol, DeclarationMirror> get declarations { |
| var method = callMethod; |
| if (method != null) { |
| var map = new Map<Symbol, DeclarationMirror>.from( |
| originalDeclaration.declarations); |
| var name = method.qualifiedName; |
| assert(!map.containsKey(name)); |
| map[name] = method; |
| return new UnmodifiableMapView<Symbol, DeclarationMirror>(map); |
| } |
| return originalDeclaration.declarations; |
| } |
| |
| bool get isFunction => true; |
| |
| MethodMirror get callMethod => _convertElementMethodToMethodMirror( |
| mirrorSystem._getLibrary(_type.element.library), |
| _type.element); |
| |
| ClassMirror get originalDeclaration => |
| mirrorSystem._getTypeDeclarationMirror( |
| mirrorSystem.compiler.functionClass); |
| |
| // TODO(johnniwinther): Substitute type arguments for type variables. |
| ClassMirror get superclass => originalDeclaration.superclass; |
| |
| // TODO(johnniwinther): Substitute type arguments for type variables. |
| List<ClassMirror> get superinterfaces => originalDeclaration.superinterfaces; |
| |
| Map<Symbol, MethodMirror> get instanceMembers => null; |
| Map<Symbol, MethodMirror> get staticMembers => null; |
| |
| ClassMirror get mixin => this; |
| |
| bool get isPrivate => false; |
| |
| bool get isAbstract => false; |
| |
| List<TypeVariableMirror> get typeVariables => |
| originalDeclaration.typeVariables; |
| |
| TypeMirror get returnType => owner._getTypeMirror(_type.returnType); |
| |
| List<ParameterMirror> get parameters { |
| if (_parameters == null) { |
| _parameters = _parametersFromFunctionSignature( |
| owner, _type.element.functionSignature); |
| } |
| return _parameters; |
| } |
| |
| String toString() => 'Mirror on function type $_type'; |
| |
| bool isSubclassOf(ClassMirror other) => false; |
| } |
| |
| /// Common superclass for mirrors on `dynamic` and `void`. |
| abstract class Dart2JsBuiltinTypeMirror extends Dart2JsDeclarationMirror |
| with Dart2JsTypeMirror |
| implements TypeSourceMirror { |
| final Dart2JsMirrorSystem mirrorSystem; |
| final DartType _type; |
| |
| Dart2JsBuiltinTypeMirror(Dart2JsMirrorSystem this.mirrorSystem, |
| DartType this._type); |
| |
| Symbol get qualifiedName => simpleName; |
| |
| /** |
| * The builtin types have has no location. |
| */ |
| SourceLocation get location => null; |
| |
| /** |
| * The builtin types have has no owner. |
| */ |
| Dart2JsDeclarationMirror get owner => null; |
| |
| /** |
| * The builtin types have no library. |
| */ |
| Dart2JsLibraryMirror get library => null; |
| |
| /** |
| * The builtin types have no metadata. |
| */ |
| List<InstanceMirror> get metadata => const <InstanceMirror>[]; |
| } |
| |
| class Dart2JsVoidMirror extends Dart2JsBuiltinTypeMirror { |
| Dart2JsVoidMirror(Dart2JsMirrorSystem mirrorSystem, VoidType type) |
| : super(mirrorSystem, type); |
| |
| bool get isVoid => true; |
| |
| bool operator ==(other) { |
| if (identical(this, other)) { |
| return true; |
| } |
| if (other is! TypeMirror) { |
| return false; |
| } |
| return other.isVoid; |
| } |
| |
| int get hashCode => 13 * _type.hashCode; |
| |
| String toString() => 'Mirror on void'; |
| } |
| |
| class Dart2JsDynamicMirror extends Dart2JsBuiltinTypeMirror { |
| Dart2JsDynamicMirror(Dart2JsMirrorSystem mirrorSystem, DynamicType type) |
| : super(mirrorSystem, type); |
| |
| bool get isDynamic => true; |
| |
| bool operator ==(other) { |
| if (identical(this, other)) { |
| return true; |
| } |
| if (other is! TypeMirror) { |
| return false; |
| } |
| return other.isDynamic; |
| } |
| |
| int get hashCode => 13 * _type.hashCode; |
| |
| String toString() => 'Mirror on dynamic'; |
| } |