@@ -150,19 +150,22 @@ Macros are applied to declarations using the existing metadata annotation
150
150
syntax. For example:
151
151
152
152
``` dart
153
- @myCoolMacro
153
+ @MyCoolMacro()
154
154
class MyClass {}
155
155
```
156
156
157
- Here, if ` myCoolMacro ` resolves to an instance of a class implementing one or
158
- more of the macro interfaces, then the annotation is treated as an application
159
- of the ` myCoolMacro ` macro to the class MyClass.
157
+ Here, if the ` MyCoolMacro ` type is a ` macro class ` , then the annotation is
158
+ treated as an application of the ` MyCoolMacro() ` macro to the class MyClass.
160
159
161
160
Macro applications can also be passed arguments, either in the form of
162
161
[ Code] [ ] expressions, [ TypeAnnotation] [ ] s, or certain
163
162
types of literal values. See [ Macro Arguments] ( #Macro-arguments ) for more
164
163
information on how these arguments are handled when executing macros.
165
164
165
+ Macro applications must always be constructor invocations. It is an error to
166
+ annotate a declaration with a constant reference to a macro instance. In the
167
+ future we may explore a more concise macro application syntax.
168
+
166
169
### Code Arguments
167
170
168
171
Consider this example macro application:
@@ -257,25 +260,25 @@ order of macros:
257
260
example:
258
261
259
262
``` dart
260
- @third
261
- @second
262
- @first
263
+ @Third()
264
+ @Second()
265
+ @First()
263
266
class C {}
264
267
```
265
268
266
- Here, the macros applied to C are run `first `, `second `, then `third `.
269
+ Here, the macros applied to C are run `First() `, `Second() `, then `Third() `.
267
270
268
271
* **Macros are applied to superclasses, mixins, and interfaces first, in**
269
272
**Phase 2** For example:
270
273
271
274
```dart
272
- @third
275
+ @Third()
273
276
class B extends A with C implements D {}
274
277
275
- @second
278
+ @Second()
276
279
class A implements C {}
277
280
278
- @first
281
+ @First()
279
282
class C {}
280
283
281
284
@first
@@ -415,22 +418,22 @@ ordering problem to discuss. Imagine you have these two classes for tracking
415
418
pets and their humans:
416
419
417
420
``` dart
418
- @jsonSerializable
421
+ @JsonSerializable()
419
422
class Human {
420
423
final String name;
421
424
final Pet? pet; // Optional, might not have a pet.
422
425
}
423
426
424
- @jsonSerializable
427
+ @JsonSerializable()
425
428
class Pet {
426
429
final String name;
427
430
final Owner? owner; // Optional, might be feral.
428
431
}
429
432
```
430
433
431
- You want to be able to save these to the cloud, so you use a ` @jsonSerializable `
432
- macro that generates a ` toJson() ` method on each class the macro is applied to.
433
- You want the methods to look like this:
434
+ You want to be able to save these to the cloud, so you use a
435
+ ` @JsonSerializable() ` macro that generates a ` toJson() ` method on each class the
436
+ macro is applied to. You want the methods to look like this:
434
437
435
438
``` dart
436
439
class Human {
@@ -451,10 +454,10 @@ class Pet {
451
454
```
452
455
453
456
Note that the ` pet ` and ` owner ` fields are serialized by recursively calling
454
- their ` toJson() ` methods. To generate that code, the ` @jsonSerializable ` macro
457
+ their ` toJson() ` methods. To generate that code, the ` @JsonSerializable() ` macro
455
458
needs to look at the type of each field to see if it declares a ` toJson() `
456
459
method. The problem is that there is * no* order of macro application that will
457
- give the right result. If we apply ` @jsonSerializable ` to Human first, then it
460
+ give the right result. If we apply ` @JsonSerializable() ` to Human first, then it
458
461
won't call ` toJson() ` on ` pet ` because Pet doesn't have a ` toJson() ` method yet.
459
462
We get the opposite problem if we apply the macro to Pet first.
460
463
@@ -621,7 +624,7 @@ With macros, many of those metadata annotations would instead either *become*
621
624
macros or be * read* by them. The latter means that macros also need to be able
622
625
to introspect over non-macro metadata annotations applied to declarations.
623
626
624
- For example, a ` @jsonSerialization ` class macro might want to look for an
627
+ For example, a ` @JsonSerialization() ` class macro might want to look for an
625
628
` @unseralized ` annotation on fields to exclude them from serialization.
626
629
627
630
** TODO** : The following subsections read more like a design discussion that a
@@ -788,7 +791,7 @@ user-written code is clear. Consider the following example:
788
791
``` dart
789
792
int get x => 1;
790
793
791
- @generateX
794
+ @GenerateX()
792
795
class Bar {
793
796
// Generated: int get x => 2;
794
797
@@ -912,19 +915,19 @@ Both of these mechanisms allow for normal macro ordering to be circumvented.
912
915
Consider the following example, where all macros run in the Declaration phase:
913
916
914
917
``` dart
915
- @macroA
916
- @macroB
918
+ @MacroA()
919
+ @MacroB()
917
920
class X {
918
- @macroC // Added by `@macroA `, runs after both `@macroB ` and `@macroA `
921
+ @MacroC() // Added by `@MacroA() `, runs after both `@MacroB() ` and `@MacroA() `
919
922
int? a;
920
923
921
- // Generated by `@macroC `, not visible to `@macroB `.
924
+ // Generated by `@MacroC() `, not visible to `@MacroB() `.
922
925
int? b;
923
926
}
924
927
```
925
928
926
- Normally, macros always run "inside-out". But in this case ` @macroC ` runs after
927
- both ` @macroB ` and ` @macroA ` which were applied to the class.
929
+ Normally, macros always run "inside-out". But in this case ` @MacroC() ` runs after
930
+ both ` @MacroB() ` and ` @MacroA() ` which were applied to the class.
928
931
929
932
We still allow this because it doesn't cause any ambiguity in ordering, even
930
933
though it violates the normal rules. We could instead only allow adding macros
@@ -998,23 +1001,24 @@ their libraries. At this point, you have a set of mutually interdependent
998
1001
libraries. They may contain references to declarations that don't exist because
999
1002
macros have yet to produce them.
1000
1003
1001
- Collect all the metadata annotations whose names can be resolved and that
1002
- resolve to macro classes. Report an error if any application refers to a macro
1003
- declared in this cycle.
1004
+ Collect all the metadata annotations which are constructor invocations of
1005
+ macro classes. Report an error if any application refers to a macro declared in
1006
+ this cycle, or if any annotation is a reference to a const instance of a macro
1007
+ class (they must be explicit constructor invocations).
1004
1008
1005
- ** TODO** : The above resolution rules may change based on
1009
+ ** NOTE** : We may in the future allow constant references to macros in
1010
+ annotations, or something similar to that, see discussion in
1006
1011
https://github.com/dart-lang/language/issues/1890 .
1007
1012
1008
1013
#### 3. Apply macros
1009
1014
1010
- In a sandbox environment or isolate, create an instance of the corresponding
1011
- macro class for each macro application. Pass in any macro application arguments
1012
- to the macro's constructor. If a parameter's type is ` Code ` or a subclass,
1013
- convert the argument expression to a ` Code ` object. Any bare identifiers in the
1014
- argument expression are converted to ` Identifier ` (see
1015
- [ Identifier Scope] ( #Identifier-Scope ) for scoping information).
1015
+ In a sandbox environment, likely a separate isolate or process, create an
1016
+ instance of the corresponding macro class for each macro application. See
1017
+ [ Executing macros] ( #Executing-macros ) for more explanation of how macros are
1018
+ constructed and how their arguments are handled.
1016
1019
1017
- Run all of the macros in phase order:
1020
+ Run all of the macros in phase order (see also
1021
+ [ Application order] ( #Application-order ) for ordering within each phase):
1018
1022
1019
1023
1 . Invoke the corresponding visit method for all macros that implement phase 1
1020
1024
APIs.
@@ -1095,14 +1099,14 @@ are ready to be loaded and executed when applied in libraries in later cycles.
1095
1099
## Executing macros
1096
1100
1097
1101
To apply a macro, a Dart compiler constructs an instance of the applied macro's
1098
- class and then invokes methods that implement macro API interfaces. The macro is
1099
- a full-featured Dart program with complete access to the entire Dart language.
1100
- Macros are Turing-complete .
1102
+ class and then invokes methods that implement macro API interfaces. Then it
1103
+ disposes of the macro instance. Typically this is all done in a separate isolate
1104
+ or process from the compiler itself .
1101
1105
1102
- ### Macro arguments
1106
+ Macros are full-featured Dart programs with complete access to the entire Dart
1107
+ language (but limited access to core libraries). Macros are Turing-complete.
1103
1108
1104
- ** TODO** : How are metadata annotations that refer to constant objects handled
1105
- (#1890 )?
1109
+ ### Macro arguments
1106
1110
1107
1111
Each argument in the metadata annotation for the macro application is converted
1108
1112
to a form that the corresponding constructor on the macro class expects, which
0 commit comments