Index: sdk/lib/mirrors/mirrors.dart |
diff --git a/sdk/lib/mirrors/mirrors.dart b/sdk/lib/mirrors/mirrors.dart |
index 715342430186bd2824323216a6f574a61de82c7f..5d736417011b437452633ccb8771e821d9a8459a 100644 |
--- a/sdk/lib/mirrors/mirrors.dart |
+++ b/sdk/lib/mirrors/mirrors.dart |
@@ -1196,7 +1196,7 @@ class Comment { |
* |
* Example usage: |
* |
- * @MirrorsUsed(symbols: 'foo', override: '*') |
+ * @MirrorsUsed(symbols: 'foo') |
* import 'dart:mirrors'; |
* |
* class Foo { |
@@ -1209,12 +1209,25 @@ class Comment { |
* 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]. |
*/ |
-// TODO(ahe): Remove ", override: '*'" when it isn't necessary anymore. |
class MirrorsUsed { |
// Note: the fields of this class are untyped. This is because the most |
- // convenient way to specify to specify symbols today is using a single |
- // string. In some cases, a const list of classes might be convenient. Some |
+ // 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. |
/** |
@@ -1228,19 +1241,29 @@ class MirrorsUsed { |
* |
* The following text is non-normative: |
* |
- * Specifying this option turns off the following warnings emitted by |
+ * 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 #{name}" may result in larger output. |
+ * * Using "new Symbol" may result in larger output. |
* |
- * Use symbols = "*" to turn off the warnings mentioned above. |
+ * 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. |
* |
- * For example, if using [noSuchMethod] to interact with a database, extract |
- * all the possible column names and include them in this list. Similarly, |
- * if using [noSuchMethod] to interact with another language (JavaScript, for |
- * example) extract all the identifiers from API used 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; |
@@ -1253,16 +1276,97 @@ class MirrorsUsed { |
* The following text is non-normative: |
* |
* For now, there is no formal description of what a reflective target is. |
- * Informally, it is a list of things that are expected to have fully |
- * functional mirrors. |
+ * 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. |
+ * 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() { ... } |
* |
- * See [targets]. |
+ * 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; |
@@ -1271,10 +1375,58 @@ class MirrorsUsed { |
* |
* 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). |
+ * 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}); |
} |