blob: 575f5cf65db52762909bce4bf59b9757b1ce5ce1 [file] [log] [blame]
// 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.
// For the purposes of the mirrors library, we adopt a naming
// convention with respect to getters and setters. Specifically, for
// some variable or field...
//
// var myField;
//
// ...the getter is named 'myField' and the setter is named
// 'myField='. This allows us to assign unique names to getters and
// setters for the purposes of member lookup.
/**
* Basic reflection in Dart,
* with support for introspection and dynamic invocation.
*
* *Introspection* is that subset of reflection by which a running
* program can examine its own structure. For example, a function
* that prints out the names of all the members of an arbitrary object.
*
* *Dynamic invocation* refers the ability to evaluate code that
* has not been literally specified at compile time, such as calling a method
* whose name is provided as an argument (because it is looked up
* in a database, or provided interactively by the user).
*
* ## How to interpret this library's documentation
*
* As a rule, the names of Dart declarations are represented using
* instances of class [Symbol]. Whenever the doc speaks of an object *s*
* of class [Symbol] denoting a name, it means the string that
* was used to construct *s*.
*
* The documentation frequently abuses notation with
* Dart pseudo-code such as [:o.x(a):], where
* o and a are defined to be objects; what is actually meant in these
* cases is [:o'.x(a'):] where *o'* and *a'* are Dart variables
* bound to *o* and *a* respectively. Furthermore, *o'* and *a'*
* are assumed to be fresh variables (meaning that they are
* distinct from any other variables in the program).
*
* Sometimes the documentation refers to *serializable* objects.
* An object is serializable across isolates if and only if it is an instance of
* num, bool, String, a list of objects that are serializable
* across isolates, or a map with keys and values that are all serializable across
* isolates.
*
* ## Status: Unstable
*
* The dart:mirrors library is unstable and its API might change slightly as a
* result of user feedback. This library is platform dependent and therefore it
* has implementations for both dart2js and the Dart VM. Both are under
* development and may not support all operations yet.
*/
library dart.mirrors;
import 'dart:async' show Future;
import "dart:async" show Future;
import "dart:collection" show UnmodifiableListView, UnmodifiableMapView;
import "dart:_internal" as internal;
/**
* A [MirrorSystem] is the main interface used to reflect on a set of
* associated libraries.
*
* At runtime each running isolate has a distinct [MirrorSystem].
*
* It is also possible to have a [MirrorSystem] which represents a set
* of libraries which are not running -- perhaps at compile-time. In
* this case, all available reflective functionality would be
* supported, but runtime functionality (such as invoking a function
* or inspecting the contents of a variable) would fail dynamically.
*/
abstract class MirrorSystem {
/**
* All libraries known to the mirror system, indexed by their URI.
*
* Returns an unmodifiable map of the libraries with [LibraryMirror.uri] as
* keys.
*
* For a runtime mirror system, only libraries which are currently loaded
* are included, and repeated calls of this method may return different maps
* as libraries are loaded.
*/
Map<Uri, LibraryMirror> get libraries;
/**
* Returns the unique library named [libraryName] if it exists.
*
* If no unique library exists, an error is thrown.
*/
LibraryMirror findLibrary(Symbol libraryName) {
var candidates =
libraries.values.where((lib) => lib.simpleName == libraryName);
if (candidates.length == 1) {
return candidates.single;
}
if (candidates.length > 1) {
var uris = candidates.map((lib) => lib.uri.toString()).toList();
throw new Exception("There are multiple libraries named "
"'${getName(libraryName)}': $uris");
}
throw new Exception("There is no library named '${getName(libraryName)}'");
}
/**
* A mirror on the isolate associated with this [MirrorSystem].
*
* This may be null if this mirror system is not running.
*/
IsolateMirror get isolate;
/**
* A mirror on the [:dynamic:] type.
*/
TypeMirror get dynamicType;
/**
* A mirror on the [:void:] type.
*/
TypeMirror get voidType;
/**
* Returns the name of [symbol].
*
* The following text is non-normative:
*
* Using this method may result in larger output. If possible, use
* [MirrorsUsed] to specify which symbols must be retained in clear text.
*/
static String getName(Symbol symbol) {
return internal.Symbol.getUnmangledName(symbol);
}
/**
* Returns a symbol for [name].
*
* If [library] is not a [LibraryMirror] or if [name] is a private identifier
* and [library] is `null`, throws an [ArgumentError]. If [name] is a private
* identifier, the symbol returned is with respect to [library].
*
* The following text is non-normative:
*
* Using this method may result in larger output. If possible, use
* the const constructor of [Symbol] or symbol literals.
*/
static Symbol getSymbol(String name, [LibraryMirror library]) {
if ((library != null && library is! _LocalLibraryMirror) ||
((name.length > 0) && (name[0] == '_') && (library == null))) {
throw new ArgumentError(library);
}
if (library != null) name = _mangleName(name, library._reflectee);
return new internal.Symbol.unvalidated(name);
}
static _mangleName(String name, _MirrorReference lib)
native "Mirrors_mangleName";
}
/**
* Returns a [MirrorSystem] for the current isolate.
*/
MirrorSystem currentMirrorSystem() {
return _Mirrors.currentMirrorSystem();
}
/**
* Reflects an instance.
*
* Returns an [InstanceMirror] reflecting [reflectee]. If [reflectee] is a
* function or an instance of a class that has a [:call:] method, the returned
* instance mirror will be a [ClosureMirror].
*
* Note that since one cannot obtain an object from another isolate, this
* function can only be used to obtain mirrors on objects of the current
* isolate.
*/
InstanceMirror reflect(Object reflectee) {
return _Mirrors.reflect(reflectee);
}
/**
* Reflects a class declaration.
*
* Let *C* be the original class declaration of the class represented by [key].
* This function returns a [ClassMirror] reflecting *C*.
*
* If [key] is not an instance of [Type], then this function throws an
* [ArgumentError]. If [key] is the Type for dynamic or a function typedef,
* throws an [ArgumentError].
*
* Note that since one cannot obtain a [Type] object from another isolate, this
* function can only be used to obtain class mirrors on classes of the current
* isolate.
*/
ClassMirror reflectClass(Type key) {
return _Mirrors.reflectClass(key);
}
/**
* Reflects the type represented by [key].
*
* If [key] is not an instance of [Type], then this function throws an
* [ArgumentError].
*
* Optionally takes a list of [typeArguments] for generic classes. If the list
* is provided, then the [key] must be a generic class type, and the number of
* the provided type arguments must be equal to the number of type variables
* declared by the class.
*
* Note that since one cannot obtain a [Type] object from another isolate, this
* function can only be used to obtain type mirrors on types of the current
* isolate.
*/
TypeMirror reflectType(Type key, [List<Type> typeArguments]) {
return _Mirrors.reflectType(key, typeArguments);
}
/**
* A [Mirror] reflects some Dart language entity.
*
* Every [Mirror] originates from some [MirrorSystem].
*/
abstract class Mirror {}
/**
* An [IsolateMirror] reflects an isolate.
*/
abstract class IsolateMirror implements Mirror {
/**
* A unique name used to refer to the isolate in debugging messages.
*/
String get debugName;
/**
* Whether this mirror reflects the currently running isolate.
*/
bool get isCurrent;
/**
* The root library for the reflected isolate.
*/
LibraryMirror get rootLibrary;
/**
* Whether [other] is an [IsolateMirror] on the same isolate as this mirror.
*
* The equality holds if and only if
*
* 1. [other] is a mirror of the same kind, and
* 2. the isolate being reflected by this mirror is the same isolate being
* reflected by [other].
*/
bool operator ==(other);
}
/**
* A [DeclarationMirror] reflects some entity declared in a Dart program.
*/
abstract class DeclarationMirror implements Mirror {
/**
* The simple name for this Dart language entity.
*
* The simple name is in most cases the identifier name of the entity,
* such as 'myMethod' for a method, [:void myMethod() {...}:] or 'mylibrary'
* for a [:library 'mylibrary';:] declaration.
*/
Symbol get simpleName;
/**
* The fully-qualified name for this Dart language entity.
*
* This name is qualified by the name of the owner. For instance,
* the qualified name of a method 'method' in class 'Class' in
* library 'library' is 'library.Class.method'.
*
* Returns a [Symbol] constructed from a string representing the
* fully qualified name of the reflectee.
* Let *o* be the [owner] of this mirror, let *r* be the reflectee of
* this mirror, let *p* be the fully qualified
* name of the reflectee of *o*, and let *s* be the simple name of *r*
* computed by [simpleName].
* The fully qualified name of *r* is the
* concatenation of *p*, '.', and *s*.
*
* Because an isolate can contain more than one library with the same name (at
* different URIs), a fully-qualified name does not uniquely identify any
* language entity.
*/
Symbol get qualifiedName;
/**
* A mirror on the owner of this Dart language entity.
*
* The owner is the declaration immediately surrounding the reflectee:
*
* * For a library, the owner is [:null:].
* * For a class declaration, typedef or top level function or variable, the
* owner is the enclosing library.
* * For a mixin application `S with M`, the owner is the owner of `M`.
* * For a constructor, the owner is the immediately enclosing class.
* * For a method, instance variable or a static variable, the owner is the
* immediately enclosing class, unless the class is a mixin application
* `S with M`, in which case the owner is `M`. Note that `M` may be an
* invocation of a generic.
* * For a parameter, local variable or local function the owner is the
* immediately enclosing function.
*/
DeclarationMirror get owner;
/**
* Whether this declaration is library private.
*
* Always returns `false` for a library declaration,
* otherwise returns `true` if the declaration's name starts with an
* underscore character (`_`), and `false` if it doesn't.
*/
bool get isPrivate;
/**
* Whether this declaration is top-level.
*
* A declaration is considered top-level if its [owner] is a [LibraryMirror].
*/
bool get isTopLevel;
/**
* The source location of this Dart language entity, or [:null:] if the
* entity is synthetic.
*
* If the reflectee is a variable, the returned location gives the position
* of the variable name at its point of declaration.
*
* If the reflectee is a library, class, typedef, function or type variable
* with associated metadata, the returned location gives the position of the
* first metadata declaration associated with the reflectee.
*
* Otherwise:
*
* If the reflectee is a library, the returned location gives the position of
* the keyword 'library' at the reflectee's point of declaration, if the
* reflectee is a named library, or the first character of the first line in
* the compilation unit defining the reflectee if the reflectee is anonymous.
*
* If the reflectee is an abstract class, the returned location gives the
* position of the keyword 'abstract' at the reflectee's point of declaration.
* Otherwise, if the reflectee is a class, the returned location gives the
* position of the keyword 'class' at the reflectee's point of declaration.
*
* If the reflectee is a typedef the returned location gives the position of
* the of the keyword 'typedef' at the reflectee's point of declaration.
*
* If the reflectee is a function with a declared return type, the returned
* location gives the position of the function's return type at the
* reflectee's point of declaration. Otherwise. the returned location gives
* the position of the function's name at the reflectee's point of
* declaration.
*
* This operation is optional and may throw an [UnsupportedError].
*/
SourceLocation get location;
/**
* A list of the metadata associated with this declaration.
*
* Let *D* be the declaration this mirror reflects.
* If *D* is decorated with annotations *A1, ..., An*
* where *n > 0*, then for each annotation *Ai* associated
* with *D, 1 <= i <= n*, let *ci* be the constant object
* specified by *Ai*. Then this method returns a list whose
* members are instance mirrors on *c1, ..., cn*.
* If no annotations are associated with *D*, then
* an empty list is returned.
*
* If evaluating any of *c1, ..., cn* would cause a
* compilation error
* the effect is the same as if a non-reflective compilation error
* had been encountered.
*/
List<InstanceMirror> get metadata;
}
/**
* An [ObjectMirror] is a common superinterface of [InstanceMirror],
* [ClassMirror], and [LibraryMirror] that represents their shared
* functionality.
*
* For the purposes of the mirrors library, these types are all
* object-like, in that they support method invocation and field
* access. Real Dart objects are represented by the [InstanceMirror]
* type.
*
* See [InstanceMirror], [ClassMirror], and [LibraryMirror].
*/
abstract class ObjectMirror implements Mirror {
/**
* Invokes the named function and returns a mirror on the result.
*
* Let *o* be the object reflected by this mirror, let *f* be the simple name
* of the member denoted by [memberName], let *a1, ..., an* be the elements
* of [positionalArguments], let *k1, ..., km* be the identifiers denoted by
* the elements of [namedArguments.keys], and let *v1, ..., vm* be the
* elements of [namedArguments.values]. Then this method will perform the
* method invocation *o.f(a1, ..., an, k1: v1, ..., km: vm)* in a scope that
* has access to the private members of *o* (if *o* is a class or library) or
* the private members of the class of *o* (otherwise).
*
* If the invocation returns a result *r*, this method returns the result of
* calling [reflect]\(*r*\).
*
* If the invocation causes a compilation error the effect is the same as if
* a non-reflective compilation error had been encountered.
*
* If the invocation throws an exception *e* (that it does not catch), this
* method throws *e*.
*/
/*
* TODO(turnidge): Handle ambiguous names.
* TODO(turnidge): Handle optional & named arguments.
*/
InstanceMirror invoke(Symbol memberName, List positionalArguments,
[Map<Symbol, dynamic> namedArguments]);
/**
* Invokes a getter and returns a mirror on the result.
*
* The getter can be the implicit getter for a field or a user-defined getter
* method.
*
* Let *o* be the object reflected by this mirror,
* let *f* be the simple name of the getter denoted by [fieldName].
*
* Then this method will perform the getter invocation *o.f* in a scope that
* has access to the private members of *o* (if *o* is a class or library) or
* the private members of the class of *o* (otherwise).
*
* If this mirror is an [InstanceMirror], and [fieldName] denotes an instance
* method on its reflectee, the result of the invocation is an instance
* mirror on a closure corresponding to that method.
*
* If this mirror is a [LibraryMirror], and [fieldName] denotes a top-level
* method in the corresponding library, the result of the invocation is an
* instance mirror on a closure corresponding to that method.
*
* If this mirror is a [ClassMirror], and [fieldName] denotes a static method
* in the corresponding class, the result of the invocation is an instance
* mirror on a closure corresponding to that method.
*
* If the invocation returns a result *r*, this method returns the result of
* calling [reflect]\(*r*\).
*
* If the invocation causes a compilation error, the effect is the same as if
* a non-reflective compilation error had been encountered.
*
* If the invocation throws an exception *e* (that it does not catch), this
* method throws *e*.
*/
// TODO(ahe): Remove stuff about scope and private members. [fieldName] is a
// capability giving access to private members.
InstanceMirror getField(Symbol fieldName);
/**
* Invokes a setter and returns a mirror on the result.
*
* The setter may be either the implicit setter for a non-final field or a
* user-defined setter method.
*
* Let *o* be the object reflected by this mirror,
* let *f* be the simple name of the getter denoted by [fieldName],
* and let *a* be the object bound to [value].
*
* Then this method will perform the setter invocation *o.f = a* in a scope
* that has access to the private members of *o* (if *o* is a class or
* library) or the private members of the class of *o* (otherwise).
*
* If the invocation returns a result *r*, this method returns the result of
* calling [reflect]\([value]\).
*
* If the invocation causes a compilation error, the effect is the same as if
* a non-reflective compilation error had been encountered.
*
* If the invocation throws an exception *e* (that it does not catch) this
* method throws *e*.
*/
/* TODO(turnidge): Handle ambiguous names.*/
InstanceMirror setField(Symbol fieldName, Object value);
/**
* Performs [invocation] on [reflectee].
*
* Equivalent to
*
* if (invocation.isGetter) {
* return this.getField(invocation.memberName).reflectee;
* } else if (invocation.isSetter) {
* return this.setField(invocation.memberName,
* invocation.positionArguments[0]).reflectee;
* } else {
* return this.invoke(invocation.memberName,
* invocation.positionalArguments,
* invocation.namedArguments).reflectee;
* }
*/
delegate(Invocation invocation);
}
/**
* An [InstanceMirror] reflects an instance of a Dart language object.
*/
abstract class InstanceMirror implements ObjectMirror {
/**
* A mirror on the type of the reflectee.
*
* Returns a mirror on the actual class of the reflectee.
* The class of the reflectee may differ from
* the object returned by invoking [runtimeType] on
* the reflectee.
*/
ClassMirror get type;
/**
* Whether [reflectee] will return the instance reflected by this mirror.
*
* This will always be true in the local case (reflecting instances in the
* same isolate), but only true in the remote case if this mirror reflects a
* simple value.
*
* A value is simple if one of the following holds:
*
* * the value is [:null:]
* * the value is of type [num]
* * the value is of type [bool]
* * the value is of type [String]
*/
bool get hasReflectee;
/**
* If the [InstanceMirror] reflects an instance it is meaningful to
* have a local reference to, we provide access to the actual
* instance here.
*
* If you access [reflectee] when [hasReflectee] is false, an
* exception is thrown.
*/
get reflectee;
/**
* Whether this mirror is equal to [other].
*
* The equality holds if and only if
*
* 1. [other] is a mirror of the same kind, and
* 2. either
*
* a. [hasReflectee] is true and so is
* [:identical(reflectee, other.reflectee):], or
*
* b. the remote objects reflected by this mirror and by [other] are
* identical.
*/
bool operator ==(other);
}
/**
* A [ClosureMirror] reflects a closure.
*
* A [ClosureMirror] provides the ability to execute its reflectee and
* introspect its function.
*/
abstract class ClosureMirror implements InstanceMirror {
/**
* A mirror on the function associated with this closure.
*
* The function associated with an implicit closure of a function is that
* function.
*
* The function associated with an instance of a class that has a [:call:]
* method is that [:call:] method.
*
* A Dart implementation might choose to create a class for each closure
* expression, in which case [:function:] would be the same as
* [:type.declarations[#call]:]. But the Dart language model does not require
* this. A more typical implementation involves a single closure class for
* each type signature, where the call method dispatches to a function held
* in the closure rather the call method
* directly implementing the closure body. So one cannot rely on closures from
* distinct closure expressions having distinct classes ([:type:]), but one
* can rely on them having distinct functions ([:function:]).
*/
MethodMirror get function;
/**
* Executes the closure and returns a mirror on the result.
*
* Let *f* be the closure reflected by this mirror,
* let *a1, ..., an* be the elements of [positionalArguments],
* let *k1, ..., km* be the identifiers denoted by the elements of
* [namedArguments.keys],
* and let *v1, ..., vm* be the elements of [namedArguments.values].
*
* Then this method will perform the method invocation
* *f(a1, ..., an, k1: v1, ..., km: vm)*.
*
* If the invocation returns a result *r*, this method returns the result of
* calling [reflect]\(*r*\).
*
* If the invocation causes a compilation error, the effect is the same as if
* a non-reflective compilation error had been encountered.
*
* If the invocation throws an exception *e* (that it does not catch), this
* method throws *e*.
*/
InstanceMirror apply(List positionalArguments,
[Map<Symbol, dynamic> namedArguments]);
}
/**
* A [LibraryMirror] reflects a Dart language library, providing
* access to the variables, functions, and classes of the
* library.
*/
abstract class LibraryMirror implements DeclarationMirror, ObjectMirror {
/**
* The absolute uri of the library.
*/
Uri get uri;
/**
* Returns an immutable map of the declarations actually given in the library.
*
* This map includes all regular methods, getters, setters, fields, classes
* and typedefs actually declared in the library. The map is keyed by the
* simple names of the declarations.
*/
Map<Symbol, DeclarationMirror> get declarations;
/**
* Whether this mirror is equal to [other].
*
* The equality holds if and only if
*
* 1. [other] is a mirror of the same kind, and
* 2. The library being reflected by this mirror and the library being
* reflected by [other] are the same library in the same isolate.
*/
bool operator ==(other);
/**
* Returns a list of the imports and exports in this library;
*/
List<LibraryDependencyMirror> get libraryDependencies;
}
/// A mirror on an import or export declaration.
abstract class LibraryDependencyMirror implements Mirror {
/// Is `true` if this dependency is an import.
bool get isImport;
/// Is `true` if this dependency is an export.
bool get isExport;
/// Returns true iff this dependency is a deferred import. Otherwise returns
/// false.
bool get isDeferred;
/// Returns the library mirror of the library that imports or exports the
/// [targetLibrary].
LibraryMirror get sourceLibrary;
/// Returns the library mirror of the library that is imported or exported,
/// or null if the library is not loaded.
LibraryMirror get targetLibrary;
/// Returns the prefix if this is a prefixed import and `null` otherwise.
Symbol get prefix;
/// Returns the list of show/hide combinators on the import/export
/// declaration.
List<CombinatorMirror> get combinators;
/// Returns the source location for this import/export declaration.
SourceLocation get location;
List<InstanceMirror> get metadata;
/// Returns a future that completes with a library mirror on the library being
/// imported or exported when it is loaded, and initiates a load of that
/// library if it is not loaded.
Future<LibraryMirror> loadLibrary();
}
/// A mirror on a show/hide combinator declared on a library dependency.
abstract class CombinatorMirror implements Mirror {
/// The list of identifiers on the combinator.
List<Symbol> get identifiers;
/// Is `true` if this is a 'show' combinator.
bool get isShow;
/// Is `true` if this is a 'hide' combinator.
bool get isHide;
}
/**
* A [TypeMirror] reflects a Dart language class, typedef,
* function type or type variable.
*/
abstract class TypeMirror implements DeclarationMirror {
/**
* Returns true if this mirror reflects dynamic, a non-generic class or
* typedef, or an instantiated generic class or typedef in the current
* isolate. Otherwise, returns false.
*/
bool get hasReflectedType;
/**
* If [:hasReflectedType:] returns true, returns the corresponding [Type].
* Otherwise, an [UnsupportedError] is thrown.
*/
Type get reflectedType;
/**
* An immutable list with mirrors for all type variables for this type.
*
* If this type is a generic declaration or an invocation of a generic
* declaration, the returned list contains mirrors on the type variables
* declared in the original declaration.
* Otherwise, the returned list is empty.
*
* This list preserves the order of declaration of the type variables.
*/
List<TypeVariableMirror> get typeVariables;
/**
* An immutable list with mirrors for all type arguments for
* this type.
*
* If the reflectee is an invocation of a generic class,
* the type arguments are the bindings of its type parameters.
* If the reflectee is the original declaration of a generic,
* it has no type arguments and this method returns an empty list.
* If the reflectee is not generic, then
* it has no type arguments and this method returns an empty list.
*
* This list preserves the order of declaration of the type variables.
*/
List<TypeMirror> get typeArguments;
/**
* Is this the original declaration of this type?
*
* For most classes, they are their own original declaration. For
* generic classes, however, there is a distinction between the
* original class declaration, which has unbound type variables, and
* the instantiations of generic classes, which have bound type
* variables.
*/
bool get isOriginalDeclaration;
/**
* A mirror on the original declaration of this type.
*
* For most classes, they are their own original declaration. For
* generic classes, however, there is a distinction between the
* original class declaration, which has unbound type variables, and
* the instantiations of generic classes, which have bound type
* variables.
*/
TypeMirror get originalDeclaration;
/**
* Checks the subtype relationship, denoted by `<:` in the language
* specification.
*
* This is the type relationship used in `is` test checks.
*/
bool isSubtypeOf(TypeMirror other);
/**
* Checks the assignability relationship, denoted by `<=>` in the language
* specification.
*
* This is the type relationship tested on assignment in checked mode.
*/
bool isAssignableTo(TypeMirror other);
}
/**
* A [ClassMirror] reflects a Dart language class.
*/
abstract class ClassMirror implements TypeMirror, ObjectMirror {
/**
* A mirror on the superclass on the reflectee.
*
* If this type is [:Object:], the superclass will be null.
*/
ClassMirror get superclass;
/**
* A list of mirrors on the superinterfaces of the reflectee.
*/
List<ClassMirror> get superinterfaces;
/**
* Is the reflectee abstract?
*/
bool get isAbstract;
/**
* Is the reflectee an enum?
*/
bool get isEnum;
/**
* Returns an immutable map of the declarations actually given in the class
* declaration.
*
* This map includes all regular methods, getters, setters, fields,
* constructors and type variables actually declared in the class. Both
* static and instance members are included, but no inherited members are
* included. The map is keyed by the simple names of the declarations.
*
* This does not include inherited members.
*/
Map<Symbol, DeclarationMirror> get declarations;
/**
* Returns a map of the methods, getters and setters of an instance of the
* class.
*
* The intent is to capture those members that constitute the API of an
* instance. Hence fields are not included, but the getters and setters
* implicitly introduced by fields are included. The map includes methods,
* getters and setters that are inherited as well as those introduced by the
* class itself.
*
* The map is keyed by the simple names of the members.
*/
Map<Symbol, MethodMirror> get instanceMembers;
/**
* Returns a map of the static methods, getters and setters of the class.
*
* The intent is to capture those members that constitute the API of a class.
* Hence fields are not included, but the getters and setters implicitly
* introduced by fields are included.
*
* The map is keyed by the simple names of the members.
*/
Map<Symbol, MethodMirror> get staticMembers;
/**
* The mixin of this class.
*
* If this class is the result of a mixin application of the form S with M,
* returns a class mirror on M. Otherwise returns a class mirror on
* [reflectee].
*/
ClassMirror get mixin;
// TODO(ahe): What about:
// /// Finds the instance member named [name] declared or inherited in the
// /// reflected class.
// DeclarationMirror instanceLookup(Symbol name);
/**
* Invokes the named constructor and returns a mirror on the result.
*
* Let *c* be the class reflected by this mirror,
* let *a1, ..., an* be the elements of [positionalArguments],
* let *k1, ..., km* be the identifiers denoted by the elements of
* [namedArguments.keys],
* and let *v1, ..., vm* be the elements of [namedArguments.values].
*
* If [constructorName] was created from the empty string, then this method
* will execute the instance creation expression
* *new c(a1, ..., an, k1: v1, ..., km: vm)* in a scope that has access to
* the private members of *c*.
*
* Otherwise, let *f* be the simple name of the constructor denoted by
* [constructorName]. Then this method will execute the instance creation
* expression *new c.f(a1, ..., an, k1: v1, ..., km: vm)* in a scope that has
* access to the private members of *c*.
*
* In either case:
*
* * If the expression evaluates to a result *r*, this method returns the
* result of calling [reflect]\(*r*\).
* * If evaluating the expression causes a compilation error, the effect is
* the same as if a non-reflective compilation error had been encountered.
* * If evaluating the expression throws an exception *e* (that it does not
* catch), this method throws *e*.
*/
InstanceMirror newInstance(Symbol constructorName, List positionalArguments,
[Map<Symbol, dynamic> namedArguments]);
/**
* Whether this mirror is equal to [other].
*
* The equality holds if and only if
*
* 1. [other] is a mirror of the same kind, and
* 2. This mirror and [other] reflect the same class.
*
* Note that if the reflected class is an invocation of a generic class, 2.
* implies that the reflected class and [other] have equal type arguments.
*/
bool operator ==(other);
/**
* Returns whether the class denoted by the receiver is a subclass of the
* class denoted by the argument.
*
* Note that the subclass relationship is reflexive.
*/
bool isSubclassOf(ClassMirror other);
}
/**
* A [FunctionTypeMirror] represents the type of a function in the
* Dart language.
*/
abstract class FunctionTypeMirror implements ClassMirror {
/**
* Returns the return type of the reflectee.
*/
TypeMirror get returnType;
/**
* Returns a list of the parameter types of the reflectee.
*/
List<ParameterMirror> get parameters;
/**
* A mirror on the [:call:] method for the reflectee.
*/
// This is only here because in the past the VM did not implement a call
// method on closures.
MethodMirror get callMethod;
}
/**
* A [TypeVariableMirror] represents a type parameter of a generic type.
*/
abstract class TypeVariableMirror extends TypeMirror {
/**
* A mirror on the type that is the upper bound of this type variable.
*/
TypeMirror get upperBound;
/**
* Is the reflectee static?
*
* For the purposes of the mirrors library, type variables are considered
* non-static.
*/
bool get isStatic;
/**
* Whether [other] is a [TypeVariableMirror] on the same type variable as this
* mirror.
*
* The equality holds if and only if
*
* 1. [other] is a mirror of the same kind, and
* 2. [:simpleName == other.simpleName:] and [:owner == other.owner:].
*/
bool operator ==(other);
}
/**
* A [TypedefMirror] represents a typedef in a Dart language program.
*/
abstract class TypedefMirror implements TypeMirror {
/**
* The defining type for this typedef.
*
* If the type referred to by the reflectee is a function type *F*, the
* result will be [:FunctionTypeMirror:] reflecting *F* which is abstract
* and has an abstract method [:call:] whose signature corresponds to *F*.
* For instance [:void f(int):] is the referent for [:typedef void f(int):].
*/
FunctionTypeMirror get referent;
}
/**
* A [MethodMirror] reflects a Dart language function, method,
* constructor, getter, or setter.
*/
abstract class MethodMirror implements DeclarationMirror {
/**
* A mirror on the return type for the reflectee.
*/
TypeMirror get returnType;
/**
* The source code for the reflectee, if available. Otherwise null.
*/
String get source;
/**
* A list of mirrors on the parameters for the reflectee.
*/
List<ParameterMirror> get parameters;
/**
* A function is considered non-static iff it is permited to refer to 'this'.
*
* Note that generative constructors are considered non-static, whereas
* factory constructors are considered static.
*/
bool get isStatic;
/**
* Is the reflectee abstract?
*/
bool get isAbstract;
/**
* Returns true if the reflectee is synthetic, and returns false otherwise.
*
* A reflectee is synthetic if it is a getter or setter implicitly introduced
* for a field or Type, or if it is a constructor that was implicitly
* introduced as a default constructor or as part of a mixin application.
*/
bool get isSynthetic;
/**
* Is the reflectee a regular function or method?
*
* A function or method is regular if it is not a getter, setter, or
* constructor. Note that operators, by this definition, are
* regular methods.
*/
bool get isRegularMethod;
/**
* Is the reflectee an operator?
*/
bool get isOperator;
/**
* Is the reflectee a getter?
*/
bool get isGetter;
/**
* Is the reflectee a setter?
*/
bool get isSetter;
/**
* Is the reflectee a constructor?
*/
bool get isConstructor;
/**
* The constructor name for named constructors and factory methods.
*
* For unnamed constructors, this is the empty string. For
* non-constructors, this is the empty string.
*
* For example, [:'bar':] is the constructor name for constructor
* [:Foo.bar:] of type [:Foo:].
*/
Symbol get constructorName;
/**
* Is the reflectee a const constructor?
*/
bool get isConstConstructor;
/**
* Is the reflectee a generative constructor?
*/
bool get isGenerativeConstructor;
/**
* Is the reflectee a redirecting constructor?
*/
bool get isRedirectingConstructor;
/**
* Is the reflectee a factory constructor?
*/
bool get isFactoryConstructor;
/**
* Whether this mirror is equal to [other].
*
* The equality holds if and only if
*
* 1. [other] is a mirror of the same kind, and
* 2. [:simpleName == other.simpleName:] and [:owner == other.owner:].
*/
bool operator ==(other);
}
/**
* A [VariableMirror] reflects a Dart language variable declaration.
*/
abstract class VariableMirror implements DeclarationMirror {
/**
* Returns a mirror on the type of the reflectee.
*/
TypeMirror get type;
/**
* Returns [:true:] if the reflectee is a static variable.
* Otherwise returns [:false:].
*
* For the purposes of the mirror library, top-level variables are
* implicitly declared static.
*/
bool get isStatic;
/**
* Returns [:true:] if the reflectee is a final variable.
* Otherwise returns [:false:].
*/
bool get isFinal;
/**
* Returns [:true:] if the reflectee is declared [:const:].
* Otherwise returns [:false:].
*/
bool get isConst;
/**
* Whether this mirror is equal to [other].
*
* The equality holds if and only if
*
* 1. [other] is a mirror of the same kind, and
* 2. [:simpleName == other.simpleName:] and [:owner == other.owner:].
*/
bool operator ==(other);
}
/**
* A [ParameterMirror] reflects a Dart formal parameter declaration.
*/
abstract class ParameterMirror implements VariableMirror {
/**
* A mirror on the type of this parameter.
*/
TypeMirror get type;
/**
* Returns [:true:] if the reflectee is an optional parameter.
* Otherwise returns [:false:].
*/
bool get isOptional;
/**
* Returns [:true:] if the reflectee is a named parameter.
* Otherwise returns [:false:].
*/
bool get isNamed;
/**
* Returns [:true:] if the reflectee has explicitly declared a default value.
* Otherwise returns [:false:].
*/
bool get hasDefaultValue;
/**
* Returns the default value of an optional parameter.
*
* Returns an [InstanceMirror] on the (compile-time constant)
* default value for an optional parameter.
* If no default value is declared, it defaults to `null`
* and a mirror of `null` is returned.
*
* Returns `null` for a required parameter.
*/
InstanceMirror get defaultValue;
}
/**
* A [SourceLocation] describes the span of an entity in Dart source code.
*/
abstract class SourceLocation {
/**
* The 1-based line number for this source location.
*
* A value of 0 means that the line number is unknown.
*/
int get line;
/**
* The 1-based column number for this source location.
*
* A value of 0 means that the column number is unknown.
*/
int get column;
/**
* Returns the URI where the source originated.
*/
Uri get sourceUri;
}
/**
* Class used for encoding comments as metadata annotations.
*/
class Comment {
/**
* The comment text as written in the source text.
*/
final String text;
/**
* The comment text without the start, end, and padding text.
*
* For example, if [text] is [: /** Comment text. */ :] then the [trimmedText]
* is [: Comment text. :].
*/
final String trimmedText;
/**
* Is [:true:] if this comment is a documentation comment.
*
* That is, that the comment is either enclosed in [: /** ... */ :] or starts
* with [: /// :].
*/
final bool isDocComment;
const Comment(this.text, this.trimmedText, this.isDocComment);
}
/**
* Annotation describing how "dart:mirrors" is used (EXPERIMENTAL).
*
* When used as metadata on an import of "dart:mirrors" in library *L*, this
* class describes how "dart:mirrors" is used by library *L* unless overridden.
* See [override].
*
* The following text is non-normative:
*
* In some scenarios, for example, when minifying Dart code, or when generating
* JavaScript code from a Dart program, the size and performance of the output
* can suffer from use of reflection. In those cases, telling the compiler
* what is used, can have a significant impact.
*
* Example usage:
*
* @MirrorsUsed(symbols: 'foo')
* import 'dart:mirrors';
*
* class Foo {
* noSuchMethod(Invocation invocation) {
* print(MirrorSystem.getName(invocation.memberName));
* }
* }
*
* main() {
* new Foo().foo(); // Prints "foo".
* new Foo().bar(); // Might print an arbitrary (mangled) name, "bar".
* }
*
* For a detailed description of the parameters to the [MirrorsUsed] constructor
* see the comments for [symbols], [targets], [metaTargets] and [override].
*
* An import of `dart:mirrors` may have multiple [MirrorsUsed] annotations. This
* is particularly helpful to specify overrides for specific libraries. For
* example:
*
* @MirrorsUsed(targets: 'foo.Bar', override: 'foo')
* @MirrorsUsed(targets: 'Bar')
* import 'dart:mirrors';
*
* will ensure that the target `Bar` from the current library and from library
* `foo` is available for reflection. See also [override].
*/
class MirrorsUsed {
// Note: the fields of this class are untyped. This is because the most
// convenient way to specify symbols today is using a single string. In
// some cases, a const list of classes might be convenient. Some
// might prefer to use a const list of symbols.
/**
* The list of strings passed to new [Symbol], and symbols that might be
* passed to [MirrorSystem.getName].
*
* Combined with the names of [targets], [metaTargets] and their members,
* this forms the complete list of strings passed to new [Symbol], and
* symbols that might be passed to [MirrorSystem.getName] by the library to
* which this metadata applies.
*
* The following text is non-normative:
*
* Dart2js currently supports the following formats to specify symbols:
*
* * A constant [List] of [String] constants representing symbol names,
* e.g., `const ['foo', 'bar']`.
* * A single [String] constant whose value is a comma-separated list of
* symbol names, e.g., `"foo, bar"`.
*
* Specifying the `symbols` field turns off the following warnings emitted by
* dart2js:
*
* * Using "MirrorSystem.getName" may result in larger output.
* * Using "new Symbol" may result in larger output.
*
* For example, if you're using [noSuchMethod] to interact with a database,
* extract all the possible column names and include them in this list.
* Similarly, if you're using [noSuchMethod] to interact with another
* language (JavaScript, for example) extract all the identifiers from the
* API you use and include them in this list.
*
* Note that specifying a symbol only ensures that the symbol will be
* available under that name at runtime. It does not mark targets with
* that name as available for reflection. See [targets] and [metaTargets]
* for that purpose.
*/
final symbols;
/**
* A list of reflective targets.
*
* Combined with [metaTargets], this provides the complete list of reflective
* targets used by the library to which this metadata applies.
*
* The following text is non-normative:
*
* For now, there is no formal description of what a reflective target is.
* Informally, a target is a library, a class, a method or a field.
*
* Dart2js currently supports the following formats to specify targets:
*
* * A constant [List] containing [String] constants representing (qualified)
* names of targets and Dart types.
* * A single [String] constant whose value is a comma-separated list of
* (qualified) names.
* * A single Dart type.
*
* A (qualified) name is resolved to a target as follows:
*
* 1. If the qualified name matches a library name, the matching library is
* the target.
* 2. Else, find the longest prefix of the name such that the prefix ends
* just before a `.` and is a library name.
* 3. Use that library as current scope. If no matching prefix was found, use
* the current library, i.e., the library where the [MirrorsUsed]
* annotation was placed.
* 4. Split the remaining suffix (the entire name if no library name was
* found in step 3) into a list of [String] using `.` as a
* separator.
* 5. Select all targets in the current scope whose name matches a [String]
* from the list.
*
* For example:
*
* library my.library.one;
*
* class A {
* var aField;
* }
*
* library main;
*
* @MirrorsUsed(targets: "my.library.one.A.aField")
* import "dart:mirrors";
*
* The [MirrorsUsed] annotation specifies `A` and `aField` from library
* `my.library.one` as targets. This will mark the class `A` as a reflective
* target. The target specification for `aField` has no effect, as there is
* no target in `my.library.one` with that name.
*
* Note that everything within a target also is available for reflection.
* So, if a library is specified as target, all classes in that library
* become targets for reflection. Likewise, if a class is a target, all
* its methods and fields become targets for reflection. As a consequence,
* `aField` in the above example is also a reflective target.
*
*/
final targets;
/**
* A list of classes that when used as metadata indicates a reflective
* target. See also [targets].
*
* The following text is non-normative:
*
* The format for specifying the list of classes is the same as used for
* specifying [targets]. However, as a library cannot be used as a metadata
* annotation in Dart, adding a library to the list of [metaTargets] has no
* effect. In particular, adding a library to [metaTargets] does not make
* the library's classes valid metadata annotations to enable reflection.
*
* If an instance of a class specified in [metaTargets] is used as
* metadata annotation on a library, class, field or method, that library,
* class, field or method is added to the set of targets for reflection.
*
* Example usage:
*
* library example;
* @MirrorsUsed(metaTargets: "example.Reflectable")
* import "dart:mirrors";
*
* class Reflectable {
* const Reflectable();
* }
*
* class Foo {
* @Reflectable()
* reflectableMethod() { ... }
*
* nonReflectableMethod() { ... }
* }
*
* In the above example. `reflectableMethod` is marked as reflectable by
* using the `Reflectable` class, which in turn is specified in the
* [metaTargets] annotation.
*
* The method `nonReflectableMethod` lacks a metadata annotation and thus
* will not be reflectable at runtime.
*/
final metaTargets;
/**
* A list of library names or "*".
*
* When used as metadata on an import of "dart:mirrors", this metadata does
* not apply to the library in which the annotation is used, but instead
* applies to the other libraries (all libraries if "*" is used).
*
* The following text is non-normative:
*
* Dart2js currently supports the following formats to specify libraries:
*
* * A constant [List] containing [String] constants representing names of
* libraries.
* * A single [String] constant whose value is a comma-separated list of
* library names.
*
* Conceptually, a [MirrorsUsed] annotation with [override] has the same
* effect as placing the annotation directly on the import of `dart:mirrors`
* in each of the referenced libraries. Thus, if the library had no
* [MirrorsUsed] annotation before, its unconditional import of
* `dart:mirrors` is overridden by an annotated import.
*
* Note that, like multiple explicit [MirrorsUsed] annotations, using
* override on a library with an existing [MirrorsUsed] annotation is
* additive. That is, the overall set of reflective targets is the union
* of the reflective targets that arise from the original and the
* overriding [MirrorsUsed] annotations.
*
* The use of [override] is only meaningful for libraries that have an
* import of `dart:mirrors` without annotation because otherwise it would
* work exactly the same way without the [override] parameter.
*
* While the annotation will apply to the given target libraries, the
* [symbols], [targets] and [metaTargets] are still evaluated in the
* scope of the annotation. Thus, to select a target from library `foo`,
* a qualified name has to be used or, if the target is visible in the
* current scope, its type may be referenced.
*
* For example, the following code marks all targets in the library `foo`
* as reflectable that have a metadata annotation using the `Reflectable`
* class from the same library.
*
* @MirrorsUsed(metaTargets: "foo.Reflectable", override: "foo")
*
* However, the following code would require the use of the `Reflectable`
* class from the current library, instead.
*
* @MirrorsUsed(metaTargets: "Reflectable", override: "foo")
*
*/
final override;
/**
* See the documentation for [MirrorsUsed.symbols], [MirrorsUsed.targets],
* [MirrorsUsed.metaTargets] and [MirrorsUsed.override] for documentation
* of the parameters.
*/
const MirrorsUsed(
{this.symbols, this.targets, this.metaTargets, this.override});
}
Symbol _computeQualifiedName(DeclarationMirror owner, Symbol simpleName) {
if (owner == null) return simpleName;
return _s('${_n(owner.qualifiedName)}.${_n(simpleName)}');
}
final _emptyList = new UnmodifiableListView([]);
class _InternalMirrorError {
final String _msg;
const _InternalMirrorError(this._msg);
String toString() => _msg;
}
String _n(Symbol symbol) => internal.Symbol.getName(symbol);
Symbol _s(String name) {
if (name == null) return null;
return new internal.Symbol.unvalidated(name);
}
var _dirty = false;
String _makeSignatureString(
TypeMirror returnType, List<ParameterMirror> parameters) {
StringBuffer buf = new StringBuffer();
buf.write('(');
bool found_optional_positional = false;
bool found_optional_named = false;
for (int i = 0; i < parameters.length; i++) {
var param = parameters[i];
if (param.isOptional && param.isNamed && !found_optional_named) {
buf.write('{');
found_optional_named = true;
}
if (param.isOptional && !param.isNamed && !found_optional_positional) {
buf.write('[');
found_optional_positional = true;
}
if (param.isNamed) {
buf.write(_n(param.simpleName));
buf.write(': ');
}
buf.write(_n(param.type.qualifiedName));
if (i < (parameters.length - 1)) {
buf.write(', ');
}
}
if (found_optional_named) {
buf.write('}');
}
if (found_optional_positional) {
buf.write(']');
}
buf.write(') -> ');
buf.write(_n(returnType.qualifiedName));
return buf.toString();
}
SourceLocation _location(reflectee) native "DeclarationMirror_location";
List _metadata(reflectee) native 'DeclarationMirror_metadata';
bool _subtypeTest(Type a, Type b) native 'TypeMirror_subtypeTest';
class _AccessorCacheAssociation {
String key;
Function value;
bool usedSinceGrowth = true;
_AccessorCacheAssociation(this.key, this.value);
}
/**
* A map that will grow as associations are added but will prefer to evict
* associations that have not been used since the last growth when needing to
* grow again. Implemented as an open addressing hash table.
*/
class _AccessorCache {
List table;
int shift;
int mask;
int capacity; // Max number of associations before we start evicting/growing.
int size = 0; // Current number of associations.
/**
* Create a cache whose capacity is 75% of 2^shift.
*/
_AccessorCache.withInitialShift(int shift) {
// The scheme used here for handling collisions relies on there always
// being at least one empty slot.
if (shift < 1) throw new Exception("_AccessorCache requires a shift >= 1");
initWithShift(shift);
}
void initWithShift(int shift) {
this.shift = shift;
this.mask = (1 << shift) - 1;
this.capacity = (1 << shift) * 3 ~/ 4;
this.table = new List(1 << shift);
assert(table.length > capacity);
}
int scanFor(String key) {
var start = key.hashCode & mask;
var index = start;
do {
var assoc = table[index];
if (null == assoc || assoc.key == key) {
return index;
}
index = (index + 1) & mask;
} while (index != start);
// Should never happen because we start evicting associations before the
// table is full.
throw new Exception("Internal error: _AccessorCache table full");
}
int scanForEmpty(String key) {
var start = key.hashCode & mask;
var index = start;
do {
if (null == table[index]) {
return index;
}
index = (index + 1) & mask;
} while (index != start);
// Should never happen because we start evicting associations before the
// table is full.
throw new Exception("Internal error: _AccessorCache table full");
}
void fixCollisionsAfter(int start) {
var assoc;
var index = (start + 1) & mask;
while (null != (assoc = table[index])) {
var newIndex = scanFor(assoc.key);
if (newIndex != index) {
assert(table[newIndex] == null);
table[newIndex] = assoc;
table[index] = null;
}
index = (index + 1) & mask;
}
}
void grow() {
var oldTable = table;
initWithShift(shift + 1);
for (int oldIndex = 0; oldIndex < oldTable.length; oldIndex++) {
var assoc = oldTable[oldIndex];
if (assoc != null) {
var newIndex = scanForEmpty(assoc.key);
assoc.usedSinceGrowth = false;
table[newIndex] = assoc;
}
}
}
void tryToShrinkOtherwiseGrow() {
// Remove any associations not accessed since the last growth. If we are
// unable to free any slots, grow.
bool needToGrow = true;
for (int i = 0; i < table.length; i++) {
var assoc = table[i];
if (null != assoc && (!assoc.usedSinceGrowth || null == assoc.value)) {
table[i] = null;
size--;
fixCollisionsAfter(i);
needToGrow = false;
}
}
if (needToGrow) grow();
}
operator []=(String key, Function value) {
int index = scanFor(key);
var assoc = table[index];
if (null != assoc) {
// Existing key, replace value.
assert(assoc.key == key);
assoc.value = value;
assoc.usedSinceGrowth = true;
} else {
// New key.
var newAssoc = new _AccessorCacheAssociation(key, value);
if (size == capacity) {
// No free slots.
tryToShrinkOtherwiseGrow();
index = scanFor(key);
assert(table[index] == null);
}
table[index] = newAssoc;
size++;
}
}
Function operator [](String key) {
var index = scanFor(key);
var assoc = table[index];
if (null == assoc) return null;
assoc.usedSinceGrowth = true;
return assoc.value;
}
}
class _LocalMirrorSystem extends MirrorSystem {
final TypeMirror dynamicType = new _SpecialTypeMirror('dynamic');
final TypeMirror voidType = new _SpecialTypeMirror('void');
var _libraries;
Map<Uri, LibraryMirror> get libraries {
if ((_libraries == null) || _dirty) {
_libraries = new Map<Uri, LibraryMirror>.fromIterable(_computeLibraries(),
key: (e) => e.uri);
_dirty = false;
}
return _libraries;
}
static _computeLibraries() native "MirrorSystem_libraries";
var _isolate;
IsolateMirror get isolate {
if (_isolate == null) {
_isolate = _computeIsolate();
}
return _isolate;
}
static _computeIsolate() native "MirrorSystem_isolate";
String toString() => "MirrorSystem for isolate '${isolate.debugName}'";
}
class _SourceLocation implements SourceLocation {
_SourceLocation(uriString, this.line, this.column)
: this.sourceUri = Uri.parse(uriString);
// Line and column positions are 1-origin, or 0 if unknown.
final int line;
final int column;
final Uri sourceUri;
String toString() {
return column == 0 ? "$sourceUri:$line" : "$sourceUri:$line:$column";
}
}
abstract class _LocalMirror implements Mirror {}
class _LocalIsolateMirror extends _LocalMirror implements IsolateMirror {
final String debugName;
final LibraryMirror rootLibrary;
_LocalIsolateMirror(this.debugName, this.rootLibrary);
bool get isCurrent => true;
String toString() => "IsolateMirror on '$debugName'";
}
class _SyntheticAccessor implements MethodMirror {
final DeclarationMirror owner;
final Symbol simpleName;
final bool isGetter;
final bool isStatic;
final bool isTopLevel;
final _target;
_SyntheticAccessor(this.owner, this.simpleName, this.isGetter, this.isStatic,
this.isTopLevel, this._target);
bool get isSynthetic => true;
bool get isRegularMethod => false;
bool get isOperator => false;
bool get isConstructor => false;
bool get isConstConstructor => false;
bool get isGenerativeConstructor => false;
bool get isFactoryConstructor => false;
bool get isExternal => false;
bool get isRedirectingConstructor => false;
bool get isAbstract => false;
bool get isSetter => !isGetter;
bool get isPrivate => _n(simpleName).startsWith('_');
Symbol get qualifiedName => _computeQualifiedName(owner, simpleName);
Symbol get constructorName => const Symbol('');
TypeMirror get returnType => _target.type;
List<ParameterMirror> get parameters {
if (isGetter) return _emptyList;
return new UnmodifiableListView(
[new _SyntheticSetterParameter(this, this._target)]);
}
SourceLocation get location => null;
List<InstanceMirror> get metadata => _emptyList;
String get source => null;
}
class _SyntheticSetterParameter implements ParameterMirror {
final DeclarationMirror owner;
final VariableMirror _target;
_SyntheticSetterParameter(this.owner, this._target);
Symbol get simpleName => _target.simpleName;
Symbol get qualifiedName => _computeQualifiedName(owner, simpleName);
TypeMirror get type => _target.type;
bool get isOptional => false;
bool get isNamed => false;
bool get isStatic => false;
bool get isTopLevel => false;
bool get isConst => false;
bool get isFinal => true;
bool get isPrivate => false;
bool get hasDefaultValue => false;
InstanceMirror get defaultValue => null;
SourceLocation get location => null;
List<InstanceMirror> get metadata => _emptyList;
}
abstract class _LocalObjectMirror extends _LocalMirror implements ObjectMirror {
final _reflectee; // May be a MirrorReference or an ordinary object.
_LocalObjectMirror(this._reflectee);
InstanceMirror invoke(Symbol memberName, List positionalArguments,
[Map<Symbol, dynamic> namedArguments]) {
int numPositionalArguments = positionalArguments.length;
int numNamedArguments = namedArguments != null ? namedArguments.length : 0;
int numArguments = numPositionalArguments + numNamedArguments;
List arguments = new List(numArguments);
arguments.setRange(0, numPositionalArguments, positionalArguments);
List names = new List(numNamedArguments);
int argumentIndex = numPositionalArguments;
int nameIndex = 0;
if (numNamedArguments > 0) {
namedArguments.forEach((name, value) {
arguments[argumentIndex++] = value;
names[nameIndex++] = _n(name);
});
}
return reflect(this._invoke(_reflectee, _n(memberName), arguments, names));
}
InstanceMirror getField(Symbol memberName) {
return reflect(this._invokeGetter(_reflectee, _n(memberName)));
}
InstanceMirror setField(Symbol memberName, Object value) {
this._invokeSetter(_reflectee, _n(memberName), value);
return reflect(value);
}
delegate(Invocation invocation) {
if (invocation.isMethod) {
return this
.invoke(invocation.memberName, invocation.positionalArguments,
invocation.namedArguments)
.reflectee;
}
if (invocation.isGetter) {
return this.getField(invocation.memberName).reflectee;
}
if (invocation.isSetter) {
var unwrapped = _n(invocation.memberName);
var withoutEqual = _s(unwrapped.substring(0, unwrapped.length - 1));
var arg = invocation.positionalArguments[0];
this.setField(withoutEqual, arg).reflectee;
return arg;
}
throw "UNREACHABLE";
}
}
class _MirrorReference {
factory _MirrorReference._uninstantiable() {
throw new UnsupportedError("class _MirrorReference cannot be instantiated");
}
bool operator ==(other) native "MirrorReference_equals";
}
class _LocalClosureMirror extends _LocalInstanceMirror
implements ClosureMirror {
_LocalClosureMirror(reflectee) : super(reflectee);
MethodMirror _function;
MethodMirror get function {
if (_function == null) {
_function = _computeFunction(reflectee);
}
return _function;
}
InstanceMirror apply(List<Object> positionalArguments,
[Map<Symbol, Object> namedArguments]) {
return this.invoke(#call, positionalArguments, namedArguments);
}
String toString() => "ClosureMirror on '${Error.safeToString(_reflectee)}'";
static _computeFunction(reflectee) native 'ClosureMirror_function';
}
class _LocalClassMirror extends _LocalObjectMirror implements ClassMirror {
final Type _reflectedType;
Symbol _simpleName;
DeclarationMirror _owner;
final bool isAbstract;
final bool _isGeneric;
final bool _isMixinAlias;
final bool _isGenericDeclaration;
final bool isEnum;
Type _instantiator;
_LocalClassMirror(
reflectee,
reflectedType,
String simpleName,
this._owner,
this.isAbstract,
this._isGeneric,
this._isMixinAlias,
this._isGenericDeclaration,
this.isEnum)
: this._simpleName = _s(simpleName),
this._reflectedType = reflectedType,
this._instantiator = reflectedType,
super(reflectee);
bool get hasReflectedType => !_isGenericDeclaration;
Type get reflectedType {
if (!hasReflectedType) {
throw new UnsupportedError(
"Declarations of generics have no reflected type");
}
return _reflectedType;
}
Symbol get simpleName {
// All but anonymous mixin applications have their name set at construction.
if (_simpleName == null) {
_simpleName = this._mixinApplicationName;
}
return _simpleName;
}
Symbol _qualifiedName = null;
Symbol get qualifiedName {
if (_qualifiedName == null) {
_qualifiedName = _computeQualifiedName(owner, simpleName);
}
return _qualifiedName;
}
DeclarationMirror get owner {
if (_owner == null) {
var uri = _LocalClassMirror._libraryUri(_reflectee);
_owner = currentMirrorSystem().libraries[Uri.parse(uri)];
}
return _owner;
}
bool get isPrivate => _n(simpleName).startsWith('_');
bool get isTopLevel => true;
SourceLocation get location {
return _location(_reflectee);
}
ClassMirror _trueSuperclassField;
ClassMirror get _trueSuperclass {
if (_trueSuperclassField == null) {
Type supertype = isOriginalDeclaration
? _supertype(_reflectedType)
: _supertypeInstantiated(_reflectedType);
if (supertype == null) {
// Object has no superclass.
return null;
}
_trueSuperclassField = reflectType(supertype);
_trueSuperclassField._instantiator = _instantiator;
}
return _trueSuperclassField;
}
ClassMirror get superclass {
return _isMixinAlias ? _trueSuperclass._trueSuperclass : _trueSuperclass;
}
var _superinterfaces;
List<ClassMirror> get superinterfaces {
if (_superinterfaces == null) {
_superinterfaces = isOriginalDeclaration
? _nativeInterfaces(_reflectedType)
: _nativeInterfacesInstantiated(_reflectedType);
_superinterfaces =
new UnmodifiableListView(_superinterfaces.map(reflectType));
}
return _superinterfaces;
}
get _mixinApplicationName {
var mixins = new List<ClassMirror>();
var klass = this;
while (_nativeMixin(klass._reflectedType) != null) {
mixins.add(klass.mixin);
klass = klass.superclass;
}
return _s(_n(klass.qualifiedName) +
' with ' +
mixins.reversed.map((m) => _n(m.qualifiedName)).join(', '));
}
var _mixin;
ClassMirror get mixin {
if (_mixin == null) {
if (_isMixinAlias) {
Type mixinType = _nativeMixinInstantiated(
_trueSuperclass._reflectedType, _instantiator);
_mixin = reflectType(mixinType);
} else {
Type mixinType =
_nativeMixinInstantiated(_reflectedType, _instantiator);
if (mixinType == null) {
// The reflectee is not a mixin application.
_mixin = this;
} else {
_mixin = reflectType(mixinType);
}
}
}
return _mixin;
}
var _cachedStaticMembers;
Map<Symbol, MethodMirror> get staticMembers {
if (_cachedStaticMembers == null) {
var result = new Map<Symbol, MethodMirror>();
declarations.values.forEach((decl) {
if (decl is MethodMirror && decl.isStatic && !decl.isConstructor) {
result[decl.simpleName] = decl;
}
if (decl is VariableMirror && decl.isStatic) {
var getterName = decl.simpleName;
result[getterName] =
new _SyntheticAccessor(this, getterName, true, true, false, decl);
if (!decl.isFinal) {
var setterName = _asSetter(decl.simpleName, this.owner);
result[setterName] = new _SyntheticAccessor(
this, setterName, false, true, false, decl);
}
}
});
_cachedStaticMembers =
new UnmodifiableMapView<Symbol, MethodMirror>(result);
}
return _cachedStaticMembers;
}
var _cachedInstanceMembers;
Map<Symbol, MethodMirror> get instanceMembers {
if (_cachedInstanceMembers == null) {
var result = new Map<Symbol, MethodMirror>();
if (superclass != null) {
result.addAll(superclass.instanceMembers);
}
declarations.values.forEach((decl) {
if (decl is MethodMirror &&
!decl.isStatic &&
!decl.isConstructor &&
!decl.isAbstract) {
result[decl.simpleName] = decl;
}
if (decl is VariableMirror && !decl.isStatic) {
var getterName = decl.simpleName;
result[getterName] = new _SyntheticAccessor(
this, getterName, true, false, false, decl);
if (!decl.isFinal) {
var setterName = _asSetter(decl.simpleName, this.owner);
result[setterName] = new _SyntheticAccessor(
this, setterName, false, false, false, decl);
}
}
});
_cachedInstanceMembers =
new UnmodifiableMapView<Symbol, MethodMirror>(result);
}
return _cachedInstanceMembers;
}
Map<Symbol, DeclarationMirror> _declarations;
Map<Symbol, DeclarationMirror> get declarations {
if (_declarations != null) return _declarations;
var decls = new Map<Symbol, DeclarationMirror>();
var whoseMembers = _isMixinAlias ? _trueSuperclass : this;
var members =
mixin._computeMembers(_instantiator, whoseMembers.mixin._reflectee);
for (var member in members) {
decls[member.simpleName] = member;
}
var constructors = _computeConstructors(_instantiator, _reflectee);
var stringName = _n(simpleName);
for (var constructor in constructors) {
constructor._patchConstructorName(stringName);
decls[constructor.simpleName] = constructor;
}
for (var typeVariable in typeVariables) {
decls[typeVariable.simpleName] = typeVariable;
}
return _declarations =
new UnmodifiableMapView<Symbol, DeclarationMirror>(decls);
}
bool get _isAnonymousMixinApplication {
if (_isMixinAlias) return false; // Named mixin application.
if (mixin == this) return false; // Not a mixin application.
return true;
}
List<TypeVariableMirror> _typeVariables = null;
List<TypeVariableMirror> get typeVariables {
if (_typeVariables == null) {
if (_isAnonymousMixinApplication) return _typeVariables = _emptyList;
_typeVariables = new List<TypeVariableMirror>();
List params = _ClassMirror_type_variables(_reflectee);
ClassMirror owner = originalDeclaration;
var mirror;
for (var i = 0; i < params.length; i += 2) {
mirror = new _LocalTypeVariableMirror(params[i + 1], params[i], owner);
_typeVariables.add(mirror);
}
_typeVariables = new UnmodifiableListView(_typeVariables);
}
return _typeVariables;
}
List<TypeMirror> _typeArguments = null;
List<TypeMirror> get typeArguments {
if (_typeArguments == null) {
if (_isGenericDeclaration || _isAnonymousMixinApplication) {
_typeArguments = _emptyList;
} else {
_typeArguments =
new UnmodifiableListView(_computeTypeArguments(_reflectedType));
}
}
return _typeArguments;
}
bool get isOriginalDeclaration => !_isGeneric || _isGenericDeclaration;
ClassMirror get originalDeclaration {
if (isOriginalDeclaration) {
return this;
} else {
return reflectClass(_reflectedType);
}
}
String toString() => "ClassMirror on '${MirrorSystem.getName(simpleName)}'";
InstanceMirror newInstance(Symbol constructorName, List positionalArguments,
[Map<Symbol, dynamic> namedArguments]) {
// Native code will add the 1 or 2 implicit arguments depending on whether
// we end up invoking a factory or constructor respectively.
int numPositionalArguments = positionalArguments.length;
int numNamedArguments = namedArguments != null ? namedArguments.length : 0;
int numArguments = numPositionalArguments + numNamedArguments;
List arguments = new List(numArguments);
arguments.setRange(0, numPositionalArguments, positionalArguments);
List names = new List(numNamedArguments);
int argumentIndex = numPositionalArguments;
int nameIndex = 0;
if (numNamedArguments > 0) {
namedArguments.forEach((name, value) {
arguments[argumentIndex++] = value;
names[nameIndex++] = _n(name);
});
}
return reflect(_invokeConstructor(
_reflectee, _reflectedType, _n(constructorName), arguments, names));
}
List<InstanceMirror> get metadata {
// Get the metadata objects, convert them into InstanceMirrors using
// reflect() and then make them into a Dart list.
return new UnmodifiableListView(_metadata(_reflectee).map(reflect));
}
bool operator ==(other) {
return this.runtimeType == other.runtimeType &&
this._reflectee == other._reflectee &&
this._reflectedType == other._reflectedType &&
this._isGenericDeclaration == other._isGenericDeclaration;
}
int get hashCode => simpleName.hashCode;
bool isSubtypeOf(TypeMirror other) {
if (other == currentMirrorSystem().dynamicType) return true;
if (other == currentMirrorSystem().voidType) return false;
return _subtypeTest(_reflectedType, other._reflectedType);
}
bool isAssignableTo(TypeMirror other) {
if (other == currentMirrorSystem().dynamicType) return true;
if (other == currentMirrorSystem().voidType) return false;
return _subtypeTest(_reflectedType, other._reflectedType) ||
_subtypeTest(other._reflectedType, _reflectedType);
}
bool isSubclassOf(ClassMirror other) {
if (other is! ClassMirror) throw new ArgumentError(other);
ClassMirror otherDeclaration = other.originalDeclaration;
ClassMirror c = this;
while (c != null) {
c = c.originalDeclaration;
if (c == otherDeclaration) return true;
c = c.superclass;
}
return false;
}
static _libraryUri(reflectee) native "ClassMirror_libraryUri";
static _supertype(reflectedType) native "ClassMirror_supertype";
static _supertypeInstantiated(reflectedType)
native "ClassMirror_supertype_instantiated";
static _nativeInterfaces(reflectedType) native "ClassMirror_interfaces";
static _nativeInterfacesInstantiated(reflectedType)
native "ClassMirror_interfaces_instantiated";
static _nativeMixin(reflectedType) native "ClassMirror_mixin";
static _nativeMixinInstantiated(reflectedType, instantiator)
native "ClassMirror_mixin_instantiated";
_computeMembers(reflectee, instantiator) native "ClassMirror_members";
_computeConstructors(reflectee, instantiator)
native "ClassMirror_constructors";
_invoke(reflectee, memberName, arguments, argumentNames)
native 'ClassMirror_invoke';
_invokeGetter(reflectee, getterName) native 'ClassMirror_invokeGetter';
_invokeSetter(reflectee, setterName, value) native 'ClassMirror_invokeSetter';
static _invokeConstructor(reflectee, type, constructorName, arguments,
argumentNames) native 'ClassMirror_invokeConstructor';
static _ClassMirror_type_variables(reflectee)
native "ClassMirror_type_variables";
static _computeTypeArguments(reflectee) native "ClassMirror_type_arguments";
}
class _LocalFunctionTypeMirror extends _LocalClassMirror
implements FunctionTypeMirror {
final _functionReflectee;
_LocalFunctionTypeMirror(reflectee, this._functionReflectee, reflectedType)
: super(reflectee, reflectedType, null, null, false, false, false, false,
false);
bool get _isAnonymousMixinApplication => false;
// FunctionTypeMirrors have a simpleName generated from their signature.
Symbol _simpleName = null;
Symbol get simpleName {
if (_simpleName == null) {
_simpleName = _s(_makeSignatureString(returnType, parameters));
}
return _simpleName;
}
MethodMirror _callMethod;
MethodMirror get callMethod {
if (_callMethod == null) {
_callMethod = _FunctionTypeMirror_call_method(_functionReflectee);
}
return _callMethod;
}
TypeMirror _returnType = null;
TypeMirror get returnType {
if (_returnType == null) {
_returnType = reflectType(
_FunctionTypeMirror_return_type(_functionReflectee, _instantiator));
}
return _returnType;
}
List<ParameterMirror> _parameters = null;
List<ParameterMirror> get parameters {
if (_parameters == null) {
_parameters = _FunctionTypeMirror_parameters(_functionReflectee);
_parameters = new UnmodifiableListView(_parameters);
}
return _parameters;
}
bool get isOriginalDeclaration => true;
get originalDeclaration => this;
get typeVariables => _emptyList;
get typeArguments => _emptyList;
get metadata => _emptyList;
get location => null;
String toString() => "FunctionTypeMirror on '${_n(simpleName)}'";
MethodMirror _FunctionTypeMirror_call_method(functionReflectee)
native "FunctionTypeMirror_call_method";
static Type _FunctionTypeMirror_return_type(functionReflectee, instantiator)
native "FunctionTypeMirror_return_type";
List<ParameterMirror> _FunctionTypeMirror_parameters(functionReflectee)
native "FunctionTypeMirror_parameters";
}
abstract class _LocalDeclarationMirror extends _LocalMirror
implements DeclarationMirror {
final _reflectee;
Symbol _simpleName;
_LocalDeclarationMirror(this._reflectee, this._simpleName);
Symbol get simpleName => _simpleName;
Symbol _qualifiedName = null;
Symbol get qualifiedName {
if (_qualifiedName == null) {
_qualifiedName = _computeQualifiedName(owner, simpleName);
}
return _qualifiedName;
}
bool get isPrivate => _n(simpleName).startsWith('_');
SourceLocation get location {
return _location(_reflectee);
}
List<InstanceMirror> get metadata {
// Get the metadata objects, convert them into InstanceMirrors using
// reflect() and then make them into a Dart list.
return new UnmodifiableListView(_metadata(_reflectee).map(reflect));
}
bool operator ==(other) {
return this.runtimeType == other.runtimeType &&
this._reflectee == other._reflectee;
}
int get hashCode => simpleName.hashCode;
}
class _LocalTypeVariableMirror extends _LocalDeclarationMirror
implements TypeVariableMirror {
_LocalTypeVariableMirror(reflectee, String simpleName, this._owner)
: super(reflectee, _s(simpleName));
DeclarationMirror _owner;
DeclarationMirror get owner {
if (_owner == null) {
_owner = _TypeVariableMirror_owner(_reflectee).originalDeclaration;
}
return _owner;
}
bool get isStatic => false;
bool get isTopLevel => false;
TypeMirror _upperBound = null;
TypeMirror get upperBound {
if (_upperBound == null) {
_upperBound = reflectType(_TypeVariableMirror_upper_bound(_reflectee));
}
return _upperBound;
}
bool get hasReflectedType => false;
Type get reflectedType {
throw new UnsupportedError('Type variables have no reflected type');
}
Type get _reflectedType => _reflectee;
List<TypeVariableMirror> get typeVariables => _emptyList;
List<TypeMirror> get typeArguments => _emptyList;
bool get isOriginalDeclaration => true;
TypeMirror get originalDeclaration => this;
String toString() => "TypeVariableMirror on '${_n(simpleName)}'";
operator ==(other) {
return other is TypeVariableMirror &&
simpleName == other.simpleName &&
owner == other.owner;
}
int get hashCode => simpleName.hashCode;
bool isSubtypeOf(TypeMirror other) {
if (other == currentMirrorSystem().dynamicType) return true;
if (other == currentMirrorSystem().voidType) return false;
return _subtypeTest(_reflectedType, other._reflectedType);
}
bool isAssignableTo(TypeMirror other) {
if (other == currentMirrorSystem().dynamicType) return true;
if (other == currentMirrorSystem().voidType) return false;
return _subtypeTest(_reflectedType, other._reflectedType) ||
_subtypeTest(other._reflectedType, _reflectedType);
}
static DeclarationMirror _TypeVariableMirror_owner(reflectee)
native "TypeVariableMirror_owner";
static Type _TypeVariableMirror_upper_bound(reflectee)
native "TypeVariableMirror_upper_bound";
}
class _LocalTypedefMirror extends _LocalDeclarationMirror
implements TypedefMirror {
final Type _reflectedType;
final bool _isGeneric;
final bool _isGenericDeclaration;
_LocalTypedefMirror(reflectee, this._reflectedType, String simpleName,
this._isGeneric, this._isGenericDeclaration, this._owner)
: super(reflectee, _s(simpleName));
bool get isTopLevel => true;
DeclarationMirror _owner;
DeclarationMirror get owner {
if (_owner == null) {
var uri = _LocalClassMirror._libraryUri(_reflectee);
_owner = currentMirrorSystem().libraries[Uri.parse(uri)];
}
return _owner;
}
TypeMirror _referent = null;
TypeMirror get referent {
if (_referent == null) {
_referent = _nativeReferent(_reflectedType);
_referent._instantiator = _reflectedType;
}
return _referent;
}
bool get hasReflectedType => !_isGenericDeclaration;
Type get reflectedType {
if (!hasReflectedType) {
throw new UnsupportedError(
"Declarations of generics have no reflected type");
}
return _reflectedType;
}
bool get isOriginalDeclaration => !_isGeneric || _isGenericDeclaration;
TypedefMirror get originalDeclaration {
if (isOriginalDeclaration) {
return this;
} else {
return _nativeDeclaration(_reflectedType);
}
}
List<TypeVariableMirror> _typeVariables = null;
List<TypeVariableMirror> get typeVariables {
if (_typeVariables == null) {
_typeVariables = new List<TypeVariableMirror>();
List params = _LocalClassMirror._ClassMirror_type_variables(_reflectee);
TypedefMirror owner = originalDeclaration;
var mirror;
for (var i = 0; i < params.length; i += 2) {
mirror = new _LocalTypeVariableMirror(params[i + 1], params[i], owner);
_typeVariables.add(mirror);
}
}
return _typeVariables;
}
List<TypeMirror> _typeArguments = null;
List<TypeMirror> get typeArguments {
if (_typeArguments == null) {
if (_isGenericDeclaration) {
_typeArguments = _emptyList;
} else {
_typeArguments = new UnmodifiableListView(
_LocalClassMirror._computeTypeArguments(_reflectedType));
}
}
return _typeArguments;
}
String toString() => "TypedefMirror on '${_n(simpleName)}'";
bool isSubtypeOf(TypeMirror other) {
if (other == currentMirrorSystem().dynamicType) return true;
if (other == currentMirrorSystem().voidType) return false;
return _subtypeTest(_reflectedType, other._reflectedType);
}
bool isAssignableTo(TypeMirror other) {
if (other == currentMirrorSystem().dynamicType) return true;
if (other == currentMirrorSystem().voidType) return false;
return _subtypeTest(_reflectedType, other._reflectedType) ||
_subtypeTest(other._reflectedType, _reflectedType);
}
static _nativeReferent(reflectedType) native "TypedefMirror_referent";
static _nativeDeclaration(reflectedType) native "TypedefMirror_declaration";
}
Symbol _asSetter(Symbol getter, LibraryMirror library) {
var unwrapped = MirrorSystem.getName(getter);
return MirrorSystem.getSymbol('${unwrapped}=', library);
}
class _LocalLibraryMirror extends _LocalObjectMirror implements LibraryMirror {
final Symbol simpleName;
final Uri uri;
_LocalLibraryMirror(reflectee, String simpleName, String url)
: this.simpleName = _s(simpleName),
this.uri = Uri.parse(url),
super(reflectee);
// The simple name and the qualified name are the same for a library.
Symbol get qualifiedName => simpleName;
DeclarationMirror get owner => null;
bool get isPrivate => false;
bool get isTopLevel => false;
Type get _instantiator => null;
Map<Symbol, DeclarationMirror> _declarations;
Map<Symbol, DeclarationMirror> get declarations {
if (_declarations != null) return _declarations;
var decls = new Map<Symbol, DeclarationMirror>();
var members = _computeMembers(_reflectee);
for (var member in members) {
decls[member.simpleName] = member;
}
return _declarations =
new UnmodifiableMapView<Symbol, DeclarationMirror>(decls);
}
SourceLocation get location {
return _location(_reflectee);
}
List<InstanceMirror> get metadata {
// Get the metadata objects, convert them into InstanceMirrors using
// reflect() and then make them into a Dart list.
return new UnmodifiableListView(_metadata(_reflectee).map(reflect));
}
bool operator ==(other) {
return this.runtimeType == other.runtimeType &&
this._reflectee == other._reflectee;
}
int get hashCode => simpleName.hashCode;
String toString() => "LibraryMirror on '${_n(simpleName)}'";
var _cachedLibraryDependencies;
get libraryDependencies {
if (_cachedLibraryDependencies == null) {
_cachedLibraryDependencies = _libraryDependencies(_reflectee);
}
return _cachedLibraryDependencies;
}
_libraryDependencies(reflectee) native 'LibraryMirror_libraryDependencies';
_invoke(reflectee, memberName, arguments, argumentNames)
native 'LibraryMirror_invoke';
_invokeGetter(reflectee, getterName) native 'LibraryMirror_invokeGetter';
_invokeSetter(reflectee, setterName, value)
native 'LibraryMirror_invokeSetter';
_computeMembers(reflectee) native "LibraryMirror_members";
}
class _LocalLibraryDependencyMirror extends _LocalMirror
implements LibraryDependencyMirror {
final LibraryMirror sourceLibrary;
var _targetMirrorOrPrefix;
final List<CombinatorMirror> combinators;
final Symbol prefix;
final bool isImport;
final bool isDeferred;
final List<InstanceMirror> metadata;
_LocalLibraryDependencyMirror(
this.sourceLibrary,
this._targetMirrorOrPrefix,
this.combinators,
prefixString,
this.isImport,
this.isDeferred,
unwrappedMetadata)
: prefix = _s(prefixString),
metadata = new UnmodifiableListView(unwrappedMetadata.map(reflect));
bool get isExport => !isImport;
LibraryMirror get targetLibrary {
if (_targetMirrorOrPrefix is _LocalLibraryMirror) {
return _targetMirrorOrPrefix;
}
var mirrorOrNull = _tryUpgradePrefix(_targetMirrorOrPrefix);
if (mirrorOrNull != null) {
_targetMirrorOrPrefix = mirrorOrNull;
}
return mirrorOrNull;
}
Future<LibraryMirror> loadLibrary() {
if (_targetMirrorOrPrefix is _LocalLibraryMirror) {
return new Future.value(_targetMirrorOrPrefix);
}
var savedPrefix = _targetMirrorOrPrefix;
return savedPrefix.loadLibrary().then((_) {
return _tryUpgradePrefix(savedPrefix);
});
}
static _tryUpgradePrefix(libraryPrefix) native "LibraryMirror_fromPrefix";
}
class _LocalCombinatorMirror extends _LocalMirror implements CombinatorMirror {
final List<Symbol> identifiers;
final bool isShow;
_LocalCombinatorMirror(identifierString, this.isShow)
: this.identifiers = [_s(identifierString)];
bool get isHide => !isShow;
}
class _LocalMethodMirror extends _LocalDeclarationMirror
implements MethodMirror {
final Type _instantiator;
final bool isStatic;
final int _kindFlags;
_LocalMethodMirror(reflectee, String simpleName, this._owner,
this._instantiator, this.isStatic, this._kindFlags)
: super(reflectee, _s(simpleName));
static const kAbstract = 0;
static const kGetter = 1;
static const kSetter = 2;
static const kConstructor = 3;
static const kConstCtor = 4;
static const kGenerativeCtor = 5;
static const kRedirectingCtor = 6;
static const kFactoryCtor = 7;
static const kExternal = 8;
// These offsets much be kept in sync with those in mirrors.h.
bool get isAbstract => 0 != (_kindFlags & (1 << kAbstract));
bool get isGetter => 0 != (_kindFlags & (1 << kGetter));
bool get isSetter => 0 != (_kindFlags & (1 << kSetter));
bool get isConstructor => 0 != (_kindFlags & (1 << kConstructor));
bool get isConstConstructor => 0 != (_kindFlags & (1 << kConstCtor));
bool get isGenerativeConstructor =>
0 != (_kindFlags & (1 << kGenerativeCtor));
bool get isRedirectingConstructor =>
0 != (_kindFlags & (1 << kRedirectingCtor));
bool get isFactoryConstructor => 0 != (_kindFlags & (1 << kFactoryCtor));
bool get isExternal => 0 != (_kindFlags & (1 << kExternal));
static const _operators = const [
"%", "&", "*", "+", "-", "/", "<", "<<", //
"<=", "==", ">", ">=", ">>", "[]", "[]=",
"^", "|", "~", "unary-", "~/",
];
bool get isOperator => _operators.contains(_n(simpleName));
DeclarationMirror _owner;
DeclarationMirror get owner {
// For nested closures it is possible, that the mirror for the owner has not
// been created yet.
if (_owner == null) {
_owner = _MethodMirror_owner(_reflectee, _instantiator);
}
return _owner;
}
bool get isPrivate =>
_n(simpleName).startsWith('_') || _n(constructorName).startsWith('_');
bool get isTopLevel => owner is LibraryMirror;
bool get isSynthetic => false;
TypeMirror _returnType = null;
TypeMirror get returnType {
if (_returnType == null) {
if (isConstructor) {
_returnType = owner;
} else {
_returnType =
reflectType(_MethodMirror_return_type(_reflectee, _instantiator));
}
}
return _returnType;
}
List<ParameterMirror> _parameters = null;
List<ParameterMirror> get parameters {
if (_parameters == null) {
_parameters = _MethodMirror_parameters(_reflectee);
_parameters = new UnmodifiableListView(_parameters);
}
return _parameters;
}
bool get isRegularMethod => !isGetter && !isSetter && !isConstructor;
Symbol _constructorName = null;
Symbol get constructorName {
if (_constructorName == null) {
if (!isConstructor) {
_constructorName = _s('');
} else {
var parts = MirrorSystem.getName(simpleName).split('.');
if (parts.length > 2) {
throw new _InternalMirrorError(
'Internal error in MethodMirror.constructorName: '
'malformed name <$simpleName>');
} else if (parts.length == 2) {
LibraryMirror definingLibrary = owner.owner;
_constructorName = MirrorSystem.getSymbol(parts[1], definingLibrary);
} else {
_constructorName = _s('');
}
}
}
return _constructorName;
}
String get source => _MethodMirror_source(_reflectee);
void _patchConstructorName(ownerName) {
var cn = _n(constructorName);
if (cn == '') {
_simpleName = _s(ownerName);
} else {
_simpleName = _s(ownerName + "." + cn);
}
}
String toString() => "MethodMirror on '${MirrorSystem.getName(simpleName)}'";
static dynamic _MethodMirror_owner(reflectee, instantiator)
native "MethodMirror_owner";
static dynamic _MethodMirror_return_type(reflectee, instantiator)
native "MethodMirror_return_type";
List<ParameterMirror> _MethodMirror_parameters(reflectee)
native "MethodMirror_parameters";
static String _MethodMirror_source(reflectee) native "MethodMirror_source";
}
class _LocalVariableMirror extends _LocalDeclarationMirror
implements VariableMirror {
final DeclarationMirror owner;
final bool isStatic;
final bool isFinal;
final bool isConst;
_LocalVariableMirror(reflectee, String simpleName, this.owner, this._type,
this.isStatic, this.isFinal, this.isConst)
: super(reflectee, _s(simpleName));
bool get isTopLevel => owner is LibraryMirror;
Type get _instantiator {
return owner._instantiator;
}
TypeMirror _type;
TypeMirror get type {
if (_type == null) {
_type = reflectType(_VariableMirror_type(_reflectee, _instantiator));
}
return _type;
}
String toString() =>
"VariableMirror on '${MirrorSystem.getName(simpleName)}'";
static _VariableMirror_type(reflectee, instantiator)
native "VariableMirror_type";
}
class _LocalParameterMirror extends _LocalVariableMirror
implements ParameterMirror {
final int _position;
final bool isOptional;
final bool isNamed;
final List _unmirroredMetadata;
_LocalParameterMirror(
reflectee,
String simpleName,
DeclarationMirror owner,
this._position,
this.isOptional,
this.isNamed,
bool isFinal,
this._defaultValueReflectee,
this._unmirroredMetadata)
: super(
reflectee,
simpleName,
owner,
null, // We override the type.
false, // isStatic does not apply.
isFinal,
false // Not const.
);
Object _defaultValueReflectee;
InstanceMirror _defaultValue;
InstanceMirror get defaultValue {
if (!isOptional) {
return null;
}
if (_defaultValue == null) {
_defaultValue = reflect(_defaultValueReflectee);
}
return _defaultValue;
}
bool get hasDefaultValue => _defaultValueReflectee != null;
SourceLocation get location {
throw new UnsupportedError("ParameterMirror.location unimplemented");
}
List<InstanceMirror> get metadata {
if (_unmirroredMetadata == null) return _emptyList;
return new UnmodifiableListView(_unmirroredMetadata.map(reflect));
}
Type get _instantiator {
return owner._instantiator;
}
TypeMirror _type = null;
TypeMirror get type {
if (_type == null) {
_type = reflectType(
_ParameterMirror_type(_reflectee, _position, _instantiator));
}
return _type;
}
String toString() => "ParameterMirror on '${_n(simpleName)}'";
static Type _ParameterMirror_type(_reflectee, _position, instantiator)
native "ParameterMirror_type";
}
class _SpecialTypeMirror extends _LocalMirror
implements TypeMirror, DeclarationMirror {
final Symbol simpleName;
_SpecialTypeMirror(String name) : simpleName = _s(name);
bool get isPrivate => false;
bool get isTopLevel => true;
DeclarationMirror get owner => null;
SourceLocation get location => null;
List<InstanceMirror> get metadata => _emptyList;
bool get hasReflectedType => simpleName == #dynamic;
Type get reflectedType {
if (simpleName == #dynamic) return dynamic;
throw new UnsupportedError("void has no reflected type");
}
List<TypeVariableMirror> get typeVariables => _emptyList;
List<TypeMirror> get typeArguments => _emptyList;
bool get isOriginalDeclaration => true;
TypeMirror get originalDeclaration => this;
Symbol get qualifiedName => simpleName;
bool operator ==(other) {
if (other is! _SpecialTypeMirror) {
return false;
}
return this.simpleName == other.simpleName;
}
int get hashCode => simpleName.hashCode;
String toString() => "TypeMirror on '${_n(simpleName)}'";
bool isSubtypeOf(TypeMirror other) {
return simpleName == #dynamic || other is _SpecialTypeMirror;
}
bool isAssignableTo(TypeMirror other) {
return simpleName == #dynamic || other is _SpecialTypeMirror;
}
}
class _Mirrors {
static MirrorSystem _currentMirrorSystem = new _LocalMirrorSystem();
static MirrorSystem currentMirrorSystem() {
return _currentMirrorSystem;
}
// Creates a new local mirror for some Object.
static InstanceMirror reflect(Object reflectee) {
return reflectee is Function
? new _LocalClosureMirror(reflectee)
: new _LocalInstanceMirror(reflectee);
}
static ClassMirror makeLocalClassMirror(Type key)
native "Mirrors_makeLocalClassMirror";
static TypeMirror makeLocalTypeMirror(Type key)
native "Mirrors_makeLocalTypeMirror";
static Type instantiateGenericType(Type key, typeArguments)
native "Mirrors_instantiateGenericType";
static Expando<ClassMirror> _declarationCache = new Expando("ClassMirror");
static Expando<TypeMirror> _instantiationCache = new Expando("TypeMirror");
static ClassMirror reflectClass(Type key) {
var classMirror = _declarationCache[key];
if (classMirror == null) {
classMirror = makeLocalClassMirror(key);
_declarationCache[key] = classMirror;
if (!classMirror._isGeneric) {
_instantiationCache[key] = classMirror;
}
}
return classMirror;
}
static TypeMirror reflectType(Type key, [List<Type> typeArguments]) {
if (typeArguments != null) {
key = _instantiateType(key, typeArguments);
}
var typeMirror = _instantiationCache[key];
if (typeMirror == null) {
typeMirror = makeLocalTypeMirror(key);
_instantiationCache[key] = typeMirror;
if (typeMirror is ClassMirror && !typeMirror._isGeneric) {
_declarationCache[key] = typeMirror;
}
}
return typeMirror;
}
static Type _instantiateType(Type key, List<Type> typeArguments) {
if (typeArguments.isEmpty) {
throw new ArgumentError.value(typeArguments, 'typeArguments',
'Type arguments list cannot be empty.');
}
return instantiateGenericType(key, typeArguments.toList(growable: