OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 // For the purposes of the mirrors library, we adopt a naming | 5 // For the purposes of the mirrors library, we adopt a naming |
6 // convention with respect to getters and setters. Specifically, for | 6 // convention with respect to getters and setters. Specifically, for |
7 // some variable or field... | 7 // some variable or field... |
8 // | 8 // |
9 // var myField; | 9 // var myField; |
10 // | 10 // |
(...skipping 1178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1189 * | 1189 * |
1190 * The following text is non-normative: | 1190 * The following text is non-normative: |
1191 * | 1191 * |
1192 * In some scenarios, for example, when minifying Dart code, or when generating | 1192 * In some scenarios, for example, when minifying Dart code, or when generating |
1193 * JavaScript code from a Dart program, the size and performance of the output | 1193 * JavaScript code from a Dart program, the size and performance of the output |
1194 * can suffer from use of reflection. In those cases, telling the compiler | 1194 * can suffer from use of reflection. In those cases, telling the compiler |
1195 * what is used, can have a significant impact. | 1195 * what is used, can have a significant impact. |
1196 * | 1196 * |
1197 * Example usage: | 1197 * Example usage: |
1198 * | 1198 * |
1199 * @MirrorsUsed(symbols: 'foo', override: '*') | 1199 * @MirrorsUsed(symbols: 'foo') |
1200 * import 'dart:mirrors'; | 1200 * import 'dart:mirrors'; |
1201 * | 1201 * |
1202 * class Foo { | 1202 * class Foo { |
1203 * noSuchMethod(Invocation invocation) { | 1203 * noSuchMethod(Invocation invocation) { |
1204 * print(MirrorSystem.getName(invocation.memberName)); | 1204 * print(MirrorSystem.getName(invocation.memberName)); |
1205 * } | 1205 * } |
1206 * } | 1206 * } |
1207 * | 1207 * |
1208 * main() { | 1208 * main() { |
1209 * new Foo().foo(); // Prints "foo". | 1209 * new Foo().foo(); // Prints "foo". |
1210 * new Foo().bar(); // Might print an arbitrary (mangled) name, "bar". | 1210 * new Foo().bar(); // Might print an arbitrary (mangled) name, "bar". |
1211 * } | 1211 * } |
| 1212 * |
| 1213 * For a detailed description of the parameters to the [MirrorsUsed] constructor |
| 1214 * see the comments for [symbols], [targets], [metaTargets] and [override]. |
| 1215 * |
| 1216 * An import of `dart:mirrors` may have multiple [MirrorsUsed] annotations. This |
| 1217 * is particularly helpful to specify overrides for specific libraries. For |
| 1218 * example: |
| 1219 * |
| 1220 * @MirrorsUsed(targets: 'foo.Bar', override: 'foo') |
| 1221 * @MirrorsUsed(targets: 'Bar') |
| 1222 * import 'dart:mirrors'; |
| 1223 * |
| 1224 * will ensure that the target `Bar` from the current library and from library |
| 1225 * `foo` is available for reflection. See also [override]. |
1212 */ | 1226 */ |
1213 // TODO(ahe): Remove ", override: '*'" when it isn't necessary anymore. | |
1214 class MirrorsUsed { | 1227 class MirrorsUsed { |
1215 // Note: the fields of this class are untyped. This is because the most | 1228 // Note: the fields of this class are untyped. This is because the most |
1216 // convenient way to specify to specify symbols today is using a single | 1229 // convenient way to specify symbols today is using a single string. In |
1217 // string. In some cases, a const list of classes might be convenient. Some | 1230 // some cases, a const list of classes might be convenient. Some |
1218 // might prefer to use a const list of symbols. | 1231 // might prefer to use a const list of symbols. |
1219 | 1232 |
1220 /** | 1233 /** |
1221 * The list of strings passed to new [Symbol], and symbols that might be | 1234 * The list of strings passed to new [Symbol], and symbols that might be |
1222 * passed to [MirrorSystem.getName]. | 1235 * passed to [MirrorSystem.getName]. |
1223 * | 1236 * |
1224 * Combined with the names of [targets], [metaTargets] and their members, | 1237 * Combined with the names of [targets], [metaTargets] and their members, |
1225 * this forms the complete list of strings passed to new [Symbol], and | 1238 * this forms the complete list of strings passed to new [Symbol], and |
1226 * symbols that might be passed to [MirrorSystem.getName] by the library to | 1239 * symbols that might be passed to [MirrorSystem.getName] by the library to |
1227 * which this metadata applies. | 1240 * which this metadata applies. |
1228 * | 1241 * |
1229 * The following text is non-normative: | 1242 * The following text is non-normative: |
1230 * | 1243 * |
1231 * Specifying this option turns off the following warnings emitted by | 1244 * Dart2js currently supports the following formats to specify symbols: |
| 1245 * |
| 1246 * * A constant [List] of [String] constants representing symbol names, |
| 1247 * e.g., `const ['foo', 'bar']`. |
| 1248 * * A single [String] constant whose value is a comma-separated list of |
| 1249 * symbol names, e.g., `"foo, bar"`. |
| 1250 * |
| 1251 * Specifying the `symbols` field turns off the following warnings emitted by |
1232 * dart2js: | 1252 * dart2js: |
1233 * | 1253 * |
1234 * * Using "MirrorSystem.getName" may result in larger output. | 1254 * * Using "MirrorSystem.getName" may result in larger output. |
1235 * * Using "new #{name}" may result in larger output. | 1255 * * Using "new Symbol" may result in larger output. |
1236 * | 1256 * |
1237 * Use symbols = "*" to turn off the warnings mentioned above. | 1257 * For example, if you're using [noSuchMethod] to interact with a database, |
| 1258 * extract all the possible column names and include them in this list. |
| 1259 * Similarly, if you're using [noSuchMethod] to interact with another |
| 1260 * language (JavaScript, for example) extract all the identifiers from the |
| 1261 * API you use and include them in this list. |
1238 * | 1262 * |
1239 * For example, if using [noSuchMethod] to interact with a database, extract | 1263 * Note that specifying a symbol only ensures that the symbol will be |
1240 * all the possible column names and include them in this list. Similarly, | 1264 * available under that name at runtime. It does not mark targets with |
1241 * if using [noSuchMethod] to interact with another language (JavaScript, for | 1265 * that name as available for reflection. See [targets] and [metaTargets] |
1242 * example) extract all the identifiers from API used and include them in | 1266 * for that purpose. |
1243 * this list. | |
1244 */ | 1267 */ |
1245 final symbols; | 1268 final symbols; |
1246 | 1269 |
1247 /** | 1270 /** |
1248 * A list of reflective targets. | 1271 * A list of reflective targets. |
1249 * | 1272 * |
1250 * Combined with [metaTargets], this provides the complete list of reflective | 1273 * Combined with [metaTargets], this provides the complete list of reflective |
1251 * targets used by the library to which this metadata applies. | 1274 * targets used by the library to which this metadata applies. |
1252 * | 1275 * |
1253 * The following text is non-normative: | 1276 * The following text is non-normative: |
1254 * | 1277 * |
1255 * For now, there is no formal description of what a reflective target is. | 1278 * For now, there is no formal description of what a reflective target is. |
1256 * Informally, it is a list of things that are expected to have fully | 1279 * Informally, a target is a library, a class, a method or a field. |
1257 * functional mirrors. | 1280 * |
| 1281 * Dart2js currently supports the following formats to specify targets: |
| 1282 * |
| 1283 * * A constant [List] containing [String] constants representing (qualified) |
| 1284 * names of targets and Dart types. |
| 1285 * * A single [String] constant whose value is a comma-separated list of |
| 1286 * (qualified) names. |
| 1287 * * A single Dart type. |
| 1288 * |
| 1289 * A (qualified) name is resolved to a target as follows: |
| 1290 * |
| 1291 * 1. If the qualified name matches a library name, the matching library is |
| 1292 * the target. |
| 1293 * 2. Else, find the longest prefix of the name such that the prefix ends |
| 1294 * just before a `.` and is a library name. |
| 1295 * 3. Use that library as current scope. If no matching prefix was found, use |
| 1296 * the current library, i.e., the library where the [MirrorsUsed] |
| 1297 * annotation was placed. |
| 1298 * 4. Split the remaining suffix (the entire name if no library name was |
| 1299 * found in step 3) into a list of [String] using `.` as a |
| 1300 * separator. |
| 1301 * 5. Select all targets in the current scope whose name matches a [String] |
| 1302 * from the list. |
| 1303 * |
| 1304 * For example: |
| 1305 * |
| 1306 * library my.library.one; |
| 1307 * |
| 1308 * class A { |
| 1309 * var aField; |
| 1310 * } |
| 1311 * |
| 1312 * library main; |
| 1313 * |
| 1314 * @MirrorsUsed(targets: "my.library.one.A.aField") |
| 1315 * import "dart:mirrors"; |
| 1316 * |
| 1317 * The [MirrorsUsed] annotation specifies `A` and `aField` from library |
| 1318 * `my.library.one` as targets. This will mark the class `A` as a reflective |
| 1319 * target. The target specification for `aField` has no effect, as there is |
| 1320 * no target in `my.library.one` with that name. |
| 1321 * |
| 1322 * Note that everything within a target also is available for reflection. |
| 1323 * So, if a library is specified as target, all classes in that library |
| 1324 * become targets for reflection. Likewise, if a class is a target, all |
| 1325 * its methods and fields become targets for reflection. As a consequence, |
| 1326 * `aField` in the above example is also a reflective target. |
| 1327 * |
1258 */ | 1328 */ |
1259 final targets; | 1329 final targets; |
1260 | 1330 |
1261 /** | 1331 /** |
1262 * A list of classes that when used as metadata indicates a reflective | 1332 * A list of classes that when used as metadata indicates a reflective |
1263 * target. | 1333 * target. See also [targets]. |
1264 * | 1334 * |
1265 * See [targets]. | 1335 * The following text is non-normative: |
| 1336 * |
| 1337 * The format for specifying the list of classes is the same as used for |
| 1338 * specifying [targets]. However, as a library cannot be used as a metadata |
| 1339 * annotation in Dart, adding a library to the list of [metaTargets] has no |
| 1340 * effect. In particular, adding a library to [metaTargets] does not make |
| 1341 * the library's classes valid metadata annotations to enable reflection. |
| 1342 * |
| 1343 * If an instance of a class specified in [metaTargets] is used as |
| 1344 * metadata annotation on a library, class, field or method, that library, |
| 1345 * class, field or method is added to the set of targets for reflection. |
| 1346 * |
| 1347 * Example usage: |
| 1348 * |
| 1349 * library example; |
| 1350 * @MirrorsUsed(metaTargets: "example.Reflectable") |
| 1351 * import "dart:mirrors"; |
| 1352 * |
| 1353 * class Reflectable { |
| 1354 * const Reflectable(); |
| 1355 * } |
| 1356 * |
| 1357 * class Foo { |
| 1358 * @Reflectable() |
| 1359 * reflectableMethod() { ... } |
| 1360 * |
| 1361 * nonReflectableMethod() { ... } |
| 1362 * } |
| 1363 * |
| 1364 * In the above example. `reflectableMethod` is marked as reflectable by |
| 1365 * using the `Reflectable` class, which in turn is specified in the |
| 1366 * [metaTargets] annotation. |
| 1367 * |
| 1368 * The method `nonReflectableMethod` lacks a metadata annotation and thus |
| 1369 * will not be reflectable at runtime. |
1266 */ | 1370 */ |
1267 final metaTargets; | 1371 final metaTargets; |
1268 | 1372 |
1269 /** | 1373 /** |
1270 * A list of library names or "*". | 1374 * A list of library names or "*". |
1271 * | 1375 * |
1272 * When used as metadata on an import of "dart:mirrors", this metadata does | 1376 * When used as metadata on an import of "dart:mirrors", this metadata does |
1273 * not apply to the library in which the annotation is used, but instead | 1377 * not apply to the library in which the annotation is used, but instead |
1274 * applies to the other libraries (all libraries if "*" is used). | 1378 * applies to the other libraries (all libraries if "*" is used). |
| 1379 * |
| 1380 * The following text is non-normative: |
| 1381 * |
| 1382 * Dart2js currently supports the following formats to specify libraries: |
| 1383 * |
| 1384 * * A constant [List] containing [String] constants representing names of |
| 1385 * libraries. |
| 1386 * * A single [String] constant whose value is a comma-separated list of |
| 1387 * library names. |
| 1388 * |
| 1389 * Conceptually, a [MirrorsUsed] annotation with [override] has the same |
| 1390 * effect as placing the annotation directly on the import of `dart:mirrors` |
| 1391 * in each of the referenced libraries. Thus, if the library had no |
| 1392 * [MirrorsUsed] annotation before, its unconditional import of |
| 1393 * `dart:mirrors` is overridden by an annotated import. |
| 1394 * |
| 1395 * Note that, like multiple explicit [MirrorsUsed] annotations, using |
| 1396 * override on a library with an existing [MirrorsUsed] annotation is |
| 1397 * additive. That is, the overall set of reflective targets is the union |
| 1398 * of the reflective targets that arise from the original and the |
| 1399 * overriding [MirrorsUsed] annotations. |
| 1400 * |
| 1401 * The use of [override] is only meaningful for libraries that have an |
| 1402 * import of `dart:mirrors` without annotation because otherwise it would |
| 1403 * work exactly the same way without the [override] parameter. |
| 1404 * |
| 1405 * While the annotation will apply to the given target libraries, the |
| 1406 * [symbols], [targets] and [metaTargets] are still evaluated in the |
| 1407 * scope of the annotation. Thus, to select a target from library `foo`, |
| 1408 * a qualified name has to be used or, if the target is visible in the |
| 1409 * current scope, its type may be referenced. |
| 1410 * |
| 1411 * For example, the following code marks all targets in the library `foo` |
| 1412 * as reflectable that have a metadata annotation using the `Reflectable` |
| 1413 * class from the same library. |
| 1414 * |
| 1415 * @MirrorsUsed(metaTargets: "foo.Reflectable", override: "foo") |
| 1416 * |
| 1417 * However, the following code would require the use of the `Reflectable` |
| 1418 * class from the current library, instead. |
| 1419 * |
| 1420 * @MirrorsUsed(metaTargets: "Reflectable", override: "foo") |
| 1421 * |
1275 */ | 1422 */ |
1276 final override; | 1423 final override; |
1277 | 1424 |
| 1425 /** |
| 1426 * See the documentation for [MirrorsUsed.symbols], [MirrorsUsed.targets], |
| 1427 * [MirrorsUsed.metaTargets] and [MirrorsUsed.override] for documentation |
| 1428 * of the parameters. |
| 1429 */ |
1278 const MirrorsUsed( | 1430 const MirrorsUsed( |
1279 {this.symbols, this.targets, this.metaTargets, this.override}); | 1431 {this.symbols, this.targets, this.metaTargets, this.override}); |
1280 } | 1432 } |
OLD | NEW |