reflectable 0.5.1

  • Installing
  • Versions
  • --


A listing of known limitations is given at the end of this page.


This package provides support for reflection which may be tailored to cover certain reflective features and omit others, thus reducing the resource requirements at runtime.

The core idea is that the desired level of support for reflection is specified explicitly and statically, and any usage of reflection at runtime must stay within the boundaries thus specified; otherwise a NoSuchCapabilityError is thrown. In return for statically confining the required reflection support, programs can be smaller. Other than that, using this package and using dart:mirrors is very similar.

The core concept in the reflection support specification is that of a reflectable capability. For a more detailed discussion about capabilities, please consult the reflectable capability design document. On this page we just use a couple of simple special cases.

The resource benefits obtained by using this package are established by transformation. That is, this package includes a pub transformer. The transformer receives a specification of which programs to transform (see the description of entry_points: below), and it uses certain elements in the program itself to decide how to transform it. As a result, the transformed program will contain generated code providing the requested level of support for reflection. If a quick turn-around is more important than space economy, it is also possible to run the code without transformation. In this case, the behavior of the program is identical, but it is implemented by delegation to dart:mirrors, which means that the execution may be costly in terms of space.

In other words, the package can be used in two modes: transformed mode and untransformed mode.

For both modes, your code will not depend directly on dart:mirrors. In the untransformed mode there is an indirect dependency because the support for reflective features is implemented by delegation to mirror objects from dart:mirrors. In the transformed mode there is no dependency on dart:mirrors at all, because the reflectable transformer generates specialized, static code that supports the required reflective features.

The use of dynamic reflection is supported if and only if the usage is covered by the set of capabilities specified.

In general, reflection is provided via a subclass of the class Reflectable (we use the term reflector to designate an instance of such a subclass).

class Reflector extends Reflectable {
  const Reflector() : super(capability1, capability2, ...);

Reflection is disabled by default, and it is enabled by specifying reflectable capabilities. With Reflector we have specified that capability1, capability2, and so on must be supported. The main case for using this is annotating a given class A with a reflector. This implies that the specified level of reflection support for that reflector should be provided for the class A and its instances.

class A {

Only classes covered by a reflector R and their instances can be accessed reflectively using R, and that access is constrained by the capabilities passed as the superinitializer in the class of R. The basic case is when R is used as an annotation of a given class (as is the case with A above), but a class C can also be covered by a reflector R because a supertype A of C is annotated by a reflector which specifies that subtypes of A are covered. There are several other indirect mechanisms in addition to subtype based coverage, as described in the capability design document.

As a result, the available universe of reflection related operations is so well-known at compile time that it is possible to specialize the support for reflection to a purely static form that satisfies the requirements of the given annotations and capabilities.


Here is a simple usage example. Assume that we have the following code in the file web/main.dart:

import 'package:reflectable/reflectable.dart';

// Annotate with this class to enable reflection.
class Reflector extends Reflectable {
  const Reflector()
      : super(invokingCapability); // Request the capability to invoke methods.

const reflector = const Reflector();

@reflector // This annotation enables reflection on A.
class A {
  final int a;
  greater(int x) => x > a;
  lessEqual(int x) => x <= a;

main() {
  A x = new A(10);
  // Reflect upon [x] using the const instance of the reflector:
  InstanceMirror instanceMirror = reflector.reflect(x);
  int weekday = new;
  // On Fridays we test if 3 is greater than 10, on other days if it is less
  // than or equal.
  String methodName = weekday == DateTime.FRIDAY ? "greater" : "lessEqual";
  // Reflectable invocation:
  print(instanceMirror.invoke(methodName, [3]));

You can directly run this code in untransformed mode, for instance using the Dart VM. To avoid the dependency on dart:mirrors and save space, you can transform the code using the transformer in this package.

In order to do this, add the following to your 'pubspec.yaml':

  reflectable: any

- reflectable:
      - web/main.dart # The path to your main file
    formatted: true # Optional.

Now run pub build --mode=debug web to perform the transformation. This will rename the file web/main.dart and generate a new file build/web/main.dart. That file contains the data needed for reflection, and a main function that will initialize the reflection framework before running the original main. When you run this file, it is important that the package-root is set to build/web/packages, because the reflectable package itself is transformed to a version that uses the generated data, instead of using dart:mirrors.

Some elements in this scenario are optional: In the pub build.. command, you could omit the final argument when it is equal to web, because that is the default. You could also omit --mode=debug if you do not wish to inspect or use the generated Dart code (typically, that would be because you only need the final JavaScript output). In 'pubspec.yaml', the formatted option can be omitted, in which case the output from the transformer will skip the formatting step (saving time and space, but putting most of the generated code into one very long line). Finally, in 'pubspec.yaml' you can use one more option: 'suppress_warnings'; e.g., you could specify 'suppress_warnings: missing_entry_point' in order to suppress the warnings given in the situation where an entry point has been specified in 'pubspec.yaml', but no corresponding library (aka 'asset') has been provided by pub to the transformer.

For a more advanced example, you could look at serialize_test.dart and its library, where the base of a serialization framework is implemented; or you could look at meta_reflectors_test.dart and the libraries it imports, which illustrates how reflectable can be used to dynamically make a choice among several kinds of reflection, and how to eliminate several kinds of static dependencies among libraries.

Comparison with dart:mirrors with MirrorsUsed annotations

A lot of the overhead of dart:mirrors can be mitigated by using a suitable MirrorsUsed annotation, which has a similar purpose as the capabilities of reflectable. So why do we have both?

First, on some Dart platforms there is no support for reflection at all, in which case it is necessary to use an approach that offers execution without any built-in reflection mechanism, and the reflectable transformer does just that.

Even when there is support for reflection, it makes sense to use reflectable. In particular, the concepts and mechanisms embedded in the reflectable capabilities represent a significant further development and generalization of the approach used with MirrorsUsed, which means that the level of reflection support can be tailored more precisely.

Another advantage of the reflectable approach is that the same restrictions are implemented both for running untransformed code (on top of dart:mirrors), and for running transformed code. The behaviour will thus be the same on Dartium and with code that is transformed and then compiled with Dart2js.

Another advantage is that whereas the interaction between two different MirrorsUsed annotations often is hard to predict, reflectable allows for several separate mirror-systems (reflectors) with different capabilities. This means that for some reflection targets used by one sub-system of the program (say, a serializer) detailed information can be generated. Another sub-system with simpler requirements could then be supported by a much smaller amount of information.

Known limitations

Several parts of the library have not yet been implemented. In particular, the following parts are still incomplete:

  • Reflection on functions/closures. We do not have the required primitives to support this feature, so it is expected to remain unsupported for a while.

  • Private declarations. There is currently almost no support for reflection on private declarations, as this would require special support from the runtime for accessing private names from other libraries. As an example of a case where there is some support, library mirrors can deliver class mirrors for private classes, and instanceMembers includes public members inherited from private superclasses. But in the vast majority of situations, private declarations are not supported.

  • uri's of libraries. The transformer framework does not give us access to good uri's of libraries, so these are currently only partially supported: A unique uri containing the name given in the library directive (if any) is generated for each library; this means that equality tests will work, and the toString() of a uri will be somewhat human readable. But this kind of uri does not give any information about the location of a corresponding file on disk.

  • Type arguments of generic types are only supported in the simple cases. E.g., when it is known that a given list of actual type arguments is empty then the empty list is returned. However, when a parameterized type has a non-trivial list of actual type arguments then returning the actual type arguments would require runtime support that does not currently exist.

  • The mirror methods delegate, isAssignableTo, isSubtypeOf, and libraryDependencies have not yet been implemented with transformed code.

  • When an attempt to invoke a method, getter, or setter fails, it is sometimes not possible to distinguish the situation where the method is missing (in which case noSuchMethod should be invoked) and the situation where the method is present, but the requested capabilities do not provide access to it (in which case a NoSuchCapabilityError should be thrown).

Feature requests and bug reports

Please file feature requests and bugs using the github issue tracker for this repository.



  • Changes the version constraint on analyzer to 0.27.1, to avoid an issue with version 0.27.1+1 which breaks all reflectable transformations. Note that this is a tight constraint (just one version allowed), but currently all other versions above 0.27.0 will fail so there is no point in trying them.
  • Bug fix: The transformer now treats the entry points as a set such that duplicates are eliminated; duplicates of entry points are not useful, and they can trigger an infinite loop if present.


  • Breaking: The methods hasBestEffortReflectedType and bestEffortReflectedType are now deprecated. They will be removed in the next published version.
  • Breaking: Implements a new semantics for no-such-method situations: When a reflectable invocation (invoke, invokeGetter, invokeSetter, newInstance, delegate) fails due to an unknown selector or an argument list with the wrong shape, a ReflectableNoSuchMethodError is thrown. (In particular, noSuchMethod is not invoked, and no NoSuchMethodError is thrown). For more details, please consult the capability design document near occurrences of 'no-such-method'.
  • Fixes issue 51, which is concerned with coverage of getters/setters for variables inherited from non-covered classes.
  • Breaking: Changes coverage such that it requires a SuperclassQuantifyCapability in order to include support for an anonymous mixin application (like A with M in class B extends A with M..). Such mixin applications used to be included even without the SuperclassQuantifyCapability, but that was an anomaly.
  • Breaking: Changes the semantics of superclass to strictly follow the documentation: It is now required to have a TypeRelationsCapability in order to perform superclass, even in the cases where this yields a mixin application.
  • Breaking: Changes the semantics of instanceMembers and staticMembers to strictly follow the documentation: It is now required to have a DeclarationsCapability in order to perform these methods.
  • Breaking: Eliminates the non-trivial upper bound on the version of the analyzer package (because the constant evaluation issue has been resolved). The analyzer dependency is now '^0.27.0'. Switches to code_transformers version '^0.3.0'.
  • Updates the capability design document to document the new treatment of no-such-method situations.
  • Implements isSubtypeOf and isAssignableTo for type mirrors.
  • Fixes issue 48, which is about wrong code generation involving mixin applications.
  • Implements delegate on instance mirrors, and adds a delegateCapability to enable it. The reason why this requires a separate capability is that the cost of storing maps between strings and symbols needed by delegate is non-trivial.
  • Changes code generation to avoid generating code for some unused mirrors.
  • Fixes bug which prevented recognition of some forms of metadata during metadata based capability checking.


  • Changes the representation of reflected types such that duplication of Type expressions is avoided (by using indices into a shared list).
  • Adds methods dynamicReflectedType and hasDynamicReflectedType to several mirror classes, yielding the erased version of the reflected type (for List<int> it would return List<dynamic>, i.e., List). This method is capable of returning a result in some cases where reflectedType fails.
  • Corrects the behavior of methods reflectedType and hasReflectedType, such that reflectedType returns an instantiated generic class when that is appropriate, and hasReflectedType returns false in some cases where it used to return true, because the correct instantiated generic class cannot be obtained.
  • Adds method bestEffortReflectedType which will use reflectedType and dynamicReflectedType to obtain a reflected type if at all possible (though with a less precise specification, because it may be one or the other). Adds method hasBestEffortReflectedType to go with it. This pair of methods resembles the 0.3.3 and earlier semantics of reflectedType.

The version number is stepped up to 0.4.0 because reflectedType behaves differently now than it did in 0.3.3 and earlier, which turned out to break some programs. In some cases the best reaction may be to replace invocations of reflectedType and hasReflectedType by the corresponding "best effort" methods, but it may also be better to use both the reflectedType and the dynamicReflectedType method pairs, taking the precise semantics into account when using the returned result.

Note that version 0.3.4 also deals with reflectedType in a stricter way than 0.3.3 and earlier versions, but at that point the changes were considered to be bug fixes or implementations of missing features.


  • NB Adds a non-trivial upper version constraint on analyzer in order to require version 0.26.1+14 or older. This is necessary because newer versions of analyzer have changed in ways that are incompatible with reflectable in several ways. We expect to be able to allow using the newest version of analyzer again soon.
  • Implements support for moving additional kinds of expressions (for argument default values and metadata), esp. when they use a library prefix (such as @myLib.myMetadata).
  • Adds test cases for previously untested capabilities (NewInstanceMetaCapability and TypingCapability).
  • Fixes bug where pre-transform check would attempt to use null but should instead throw NoSuchCapabilityError.
  • Adds missing checks in pre-transform code (e.g., checking that a LibraryCapability is available when performing a top-level invocation).
  • Corrects inconsistency among the type hierarchies for pre/post-transform capabilities (which caused the post-transform code to act incorrectly).
  • Corrects treatment of TypingCapability, adjusted it to include LibraryCapability.
  • Introduces UnreachableError and adjusted error handling to throw this in all cases where a location should never be reached.
  • Several '' files updated to match the current status.
  • A couple of smaller unimplemented methods implemented.
  • Eliminates many of the 'Missing entry point' messages: If it is specified that an entry point 'web/foo.dart' must be transformed, but no such asset is provided to the transformer, then the warning is only emitted if the file does not exist (with pub build test, 'web/foo.dart' is not provided to the transformer, but that is not a problem).
  • Corrects the bug that typeRelationsCapability was sometimes not required with certain operations (including superclass), even though the documentation states that it is required. Similarly, a TypeCapability is now required in a few extra cases where it should be required.
  • Correct the cyclic-dependency bug which previously made 'expanding_generics_test.dart' fail.
  • Adds support for enum classes.
  • Implement support for all the trivial parts of genericity: empty lists of type arguments are now delivered rather than throwing UnimplementedError, and static information like type variables (that is, formals) is supported.
  • Implement several missing class members, including isEnum, isPrivate, isOriginalDeclaration, originalDeclaration.
  • Correct several bugs in the implementation of LibraryMirror.
  • Correct several bugs with owner.
  • Implement several features for top-level entities, especially variables.
  • Correct several incorrect type annotations (e.g., List required, but only Iterable justified).
  • Implement simple code coverage support.


  • Update many DartDoc comments in 'capability.dart'.
  • Update the document The Design of Reflectable Capabilities to match the current selection of quantifiers and their semantics.
  • Add very limited support for private classes: They are preserved such that iteration over all superclasses will work even if some of them are private, and private class mirrors are included in declarations of library mirrors. However, it is not possible to reflect on an instance of a private class, to create new instances with newInstance, nor to call its static methods.
  • Fix bug where some private names were used in generated code (which makes subsequent compilation fail).
  • Add option to format the generated code (off by default).
  • Add correspondingSetterQuantifyCapability, which will add the corresponding setter for each already included explicitly declared getter.
  • Change generated code: Eliminate many invocations of new UnmodifiableListView.., replace many plain list literals by const list literals, for better startup time and more redundancy elimination.
  • Fix bug where an InvokingMetaCapability was treated as a NewInstanceMetaCapability.
  • Fix bugs in the publication support script.


  • Introduce reflectedTypeCapability which enables methods reflectedType on variable and parameter mirrors, and reflectedReturnType on method mirrors. This enables limited access to type annotations while avoiding the generation of many class mirrors.
  • Introduce Reflectable.getInstance which delivers the canonical instance of any given reflector class which is being used in the current program. An example shows how this enables "meta-reflection".
  • Fixed bugs in methods isAbstract, isSynthetic; fixed bug in selection of supported members of library mirrors; and implemented methods libraries and declarations for library mirrors; and fixed several other library related bugs.


  • Fix bug where metadata was searched the same way for invocation and for declarations with InstanceInvokeMetaCapability (invocation must traverse superclasses).
  • Fix bug where some libraries were imported into generated code, even though they cannot be imported (private to core).
  • Fix bugs in publication support script.


  • Breaking: Add support for type annotation quantification. This is a breaking change: we used to do that implicitly, but that is expensive, and now it is only available on request.
  • Change the way the set of supported classes are computed.
  • Fix crash when transforming certain dart:html classes.
  • Fix memory leak from the transformer.


  • Recognize private identifier constants as metadata in certain cases.
  • Bump required SDK version in pubspec.yaml.
  • Correct generation of imports of the original entry point.
  • Fix issues with the computation of static members.
  • Allows the metadata capabilities to recognize any subtype of the given type.


  • Breaking: Enforces the use of a TypeCapability as specified in the design document, and makes it a supertype of several other capabilities such that it is automatically included with, e.g., declarationsCapability.
  • Fixed homepage link in pubspec
  • Fix several bug with mixins in the transformer.
  • Add excludeUpperBound flag to SuperClassQuantifyCapability.
  • Use a static initializer in the generated code which helps avoiding a stack overflow.


  • Support for return types of getters and setters.
  • Support for superTypeQuantifyCapability.
  • Fix bug in the mirror-based implementation's collection of classes that could lead to infinite loops.
  • Fix bug related to generating code for operator~ in the transformer.
  • Avoid crashing the transformer when an entry-point has no member named main


  • Support for subtype quantification in transformed code.
  • Code generation bugs fixed; metadata/library related bugs fixed.
  • Faster version of test procedure.


  • Non-transformed code supports subTypeQuantifyCapability
  • Transformer implements .superinterfaces
  • Transformer implements .mixin
  • Transformer implements reflection on libraries.
  • Better support for default values in transformed code.


  • Our tests started failing because of a version conflict introduced by an update to code_transformers. Changed pubspec.yaml to avoid the conflict.
  • Made changes to avoid deprecated features in the new version of analyzer.
  • Implemented support for implicit accessors (setters, getters).
  • Implemented support for staticMembers on ClassMirror.


  • Transformer implements .type of fields and parameters.
  • Transformer has support for main function that is not in the entry-point file.
  • Transformer supports async main returning a Future.
  • Other bug fixes...


  • First published release.


  • Initial project creation

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:

  reflectable: ^0.5.1

2. Install it

You can install packages from the command line:

with pub:

$ pub get

Alternatively, your editor might support pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:

import 'package:reflectable/reflectable.dart';
Version Uploaded Documentation Archive
2.0.8 Oct 30, 2018 Go to the documentation of reflectable 2.0.8 Download reflectable 2.0.8 archive
2.0.7 Sep 17, 2018 Go to the documentation of reflectable 2.0.7 Download reflectable 2.0.7 archive
2.0.6 Sep 6, 2018 Go to the documentation of reflectable 2.0.6 Download reflectable 2.0.6 archive
2.0.5 Aug 30, 2018 Go to the documentation of reflectable 2.0.5 Download reflectable 2.0.5 archive
2.0.4 Aug 22, 2018 Go to the documentation of reflectable 2.0.4 Download reflectable 2.0.4 archive
2.0.3 Aug 17, 2018 Go to the documentation of reflectable 2.0.3 Download reflectable 2.0.3 archive
2.0.2 Jul 20, 2018 Go to the documentation of reflectable 2.0.2 Download reflectable 2.0.2 archive
2.0.1 May 30, 2018 Go to the documentation of reflectable 2.0.1 Download reflectable 2.0.1 archive
2.0.0 Apr 9, 2018 Go to the documentation of reflectable 2.0.0 Download reflectable 2.0.0 archive
1.0.4 Aug 24, 2017 Go to the documentation of reflectable 1.0.4 Download reflectable 1.0.4 archive

All 34 versions...

Describes how popular the package is relative to other packages. [more]
Code health derived from static analysis. [more]
Reflects how tidy and up-to-date the package is. [more]
Weighted score of the above. [more]
Learn more about scoring.

This package version is not analyzed, because it is more than two years old. Check the latest stable version for its analysis.


Package Constraint Resolved Available
Direct dependencies
Dart SDK >=1.12.0 <2.0.0