@@ -106,11 +106,25 @@ from changing the constructor to a factory.
106
106
107
107
## Syntax
108
108
109
- There are a handful of grammar changes mostly around allowing ` augment ` before
110
- the various declarations that can be augmented allowing declarations to be less
111
- "complete" than they were required to be before this proposal since an
112
- augmentation can fill them in. For example, non-instance functions without
113
- bodies and enums without values.
109
+ The syntax changes are simple but fairly extensive and touch several parts of
110
+ the grammar so are broken out into separate sections.
111
+
112
+ ### Top-level augmentations and incomplete top-level members
113
+
114
+ We allow an ` augment ` modifier before most top-level declarations.
115
+
116
+ Also, we allow incomplete declarations at the top level. This reuses the same
117
+ syntax used inside a class to declare abstract variables, methods, getters,
118
+ setters, and operators. For callable members, that means the body is ` ; ` . For
119
+ variable declarations, that means using ` abstract ` . * Example:*
120
+
121
+ ``` dart
122
+ abstract int x; // Incomplete top-level variable.
123
+ int get y; // Incomplete top-level getter.
124
+ set z(int value); // Incomplete top-level setter.
125
+ ```
126
+
127
+ The new top-level grammar is:
114
128
115
129
```
116
130
topLevelDeclaration ::= classDeclaration
@@ -123,13 +137,21 @@ topLevelDeclaration ::= classDeclaration
123
137
| 'augment'? 'external' getterSignature ';'
124
138
| 'augment'? 'external' setterSignature ';'
125
139
| 'augment'? 'external' finalVarOrType identifierList ';'
126
- | 'augment'? functionSignature (functionBody | ';')
140
+ | 'augment'? 'abstract' finalVarOrType identifierList ';'
127
141
| 'augment'? getterSignature (functionBody | ';')
128
142
| 'augment'? setterSignature (functionBody | ';')
143
+ | 'augment'? functionSignature (functionBody | ';')
129
144
| 'augment'? ('final' | 'const') type? initializedIdentifierList ';'
130
145
| 'augment'? 'late' 'final' type? initializedIdentifierList ';'
131
146
| 'augment'? 'late'? varOrType initializedIdentifierList ';'
147
+ ```
132
148
149
+ ### Class-like declarations
150
+
151
+ We allow ` augment ` before class, extension type, and mixin declarations. * (Enums
152
+ and extensions are discussed in subsequent sections.)*
153
+
154
+ ```
133
155
classDeclaration ::=
134
156
'augment'? (classModifiers | mixinClassModifiers)
135
157
'class' typeWithParameters superclass? interfaces?
@@ -164,8 +186,8 @@ declaration ::=
164
186
| 'augment'? 'external'? 'static'? getterSignature ';'
165
187
| 'augment'? 'external'? 'static'? setterSignature ';'
166
188
| 'augment'? 'external'? 'static'? functionSignature ';'
167
- | 'external' ('static'? finalVarOrType | 'covariant' varOrType) identifierList ';'
168
189
| 'augment'? 'external'? operatorSignature ';'
190
+ | 'external' ('static'? finalVarOrType | 'covariant' varOrType) identifierList ';'
169
191
| 'augment'? 'abstract' (finalVarOrType | 'covariant' varOrType) identifierList ';'
170
192
| 'static' 'const' type? initializedIdentifierList ';'
171
193
| 'static' 'final' type? initializedIdentifierList ';'
@@ -180,14 +202,26 @@ declaration ::=
180
202
| 'augment'? constructorSignature (redirection | initializers)? ';'
181
203
```
182
204
183
- * Note that the grammar for putting ` augment ` before an extension type
184
- declaration doesn't allow also specifying a representation field. This is by
185
- design. An extension type augmentation always inherits the representation field
186
- of the introductory declaration and can't specify it.*
205
+ As with top-level declarations, we also reuse the abstract member syntax with a
206
+ ` static ` modifier to allow declaring incomplete static fields, methods, getters,
207
+ setters, and operators. * Example:*
208
+
209
+ ``` dart
210
+ class C {
211
+ static abstract int x; // Incomplete static variable (getter and setter).
212
+ static int get y; // Incomplete static getter.
213
+ static set z(int value); // Incomplete static setter.
214
+ }
215
+ ```
216
+
217
+ Note that the grammar for putting ` augment ` before an extension type declaration
218
+ doesn't allow also specifying a representation field. This is by design. An
219
+ extension type augmentation always inherits the representation field of the
220
+ introductory declaration and can't specify it.
187
221
188
- * Likewise, the grammar for an augmenting ` mixin ` declaration does not allow
222
+ Likewise, the grammar for an augmenting ` mixin ` declaration does not allow
189
223
specifying an ` on ` clause. Only the introductory declaration permits that. We
190
- could relax this restriction if compelling use cases arise.*
224
+ could relax this restriction if compelling use cases arise.
191
225
192
226
### Enums
193
227
@@ -605,6 +639,16 @@ subsections.
605
639
606
640
It's a ** compile-time** error if:
607
641
642
+ * An augmentation declaration is applied to a declaration of a different kind.
643
+ For example, augmenting a ` class ` with a ` mixin ` , an ` enum ` with a function,
644
+ a method with a getter, a constructor with a static method, etc.
645
+
646
+ The exception is that a variable declaration (introductory or augmenting) is
647
+ treated as a getter declaration (and a setter declaration if non-final) for
648
+ purposes of augmentation. These implicit declarations can augment and be
649
+ augmented by other explicit getter and setter declarations. (See "Augmenting
650
+ variables, getters, and setters" for more details.)
651
+
608
652
* A library contains two top-level declarations with the same name, and one of
609
653
the declarations is a class-like declaration and the other is not of the
610
654
same kind, meaning that either one is a class, mixin, enum, extension or
@@ -732,91 +776,55 @@ It's a **compile-time** error if:
732
776
* The augmenting function specifies any default values. * Default values are
733
777
defined solely by the introductory function.*
734
778
735
- * A function is not complete after all augmentations are applied, unless it
736
- is in a context where it can be abstract. * Every function declaration
737
- eventually needs to have a body filled in unless it's an instance method
738
- that can be abstract. In that case, if no declaration provides a body, it
739
- is considered abstract.*
779
+ * A function is not complete after all augmentations are applied, unless it's
780
+ an instance member and the surrounding class is abstract. * Every function
781
+ declaration eventually needs to have a body filled in unless it's an
782
+ instance method that can be abstract. In that case, if no declaration
783
+ provides a body, it is considered abstract.*
740
784
741
- ### Augmenting variables
785
+ ### Augmenting variables, getters, and setters
742
786
743
- A class-like augmentation can add * new* variables (that is instance or static
744
- fields) to the type being augmented:
787
+ For purposes of augmentation, a variable declaration is treated as implicitly
788
+ defining a getter whose return type is the type of the variable. If the variable
789
+ is not ` final ` , or is ` late ` without an initializer, then the variable
790
+ declaration also implicitly defines a setter with a parameter named ` _ ` whose
791
+ type is the type of the variable.
745
792
746
- ``` dart
747
- class C {}
793
+ If the variable is ` abstract ` , then the getter and setter are incomplete,
794
+ otherwise they are complete. * For non-abstract variables, the compiler
795
+ synthesizes a getter that accesses the backing storage and a setter that updates
796
+ it, so these members have bodies.*
748
797
749
- augment class C {
750
- int x = 3;
798
+ A getter can be augmented by another getter, and likewise a setter can be
799
+ augmented by a setter. This is true whether the getter or setter is explicitly
800
+ declared or implicitly declared using a variable declaration.
751
801
752
- static int y = 4;
753
- }
754
- ```
755
-
756
- Variable declarations themselves can't be augmented (by variables, getters, or
757
- setters, even if the getter or setter is incomplete), with the exception of
758
- abstract instance variable declarations.
759
-
760
- * A variable declaration implicitly has code for the synthesized getter and
761
- setter that access and modify the underlying backing storage. Since we don't
762
- allow augmentations to replace code, that implies that augmentations can't
763
- change variables. So we don't allow them to be augmented.*
764
-
765
- #### Abstract instance variables
766
-
767
- Dart supports ` abstract ` field declarations. They are syntactic sugar for
768
- declaring an abstract getter and, if not ` final ` , an abstract setter. They don't
769
- actually declare a variable with any backing storage.
770
-
771
- Because abstract variables are effectively abstract getter and setter
772
- declarations, they can be augmented and used in augmentations just like function
773
- declarations:
774
-
775
- * Examples:*
776
-
777
- ``` dart
778
- class C {
779
- // Augment an abstract variable with a getter:
780
- abstract final int a;
781
- augment int get a => 1; // OK.
802
+ * Since non-abstract variables are complete, that implies that it is an error to
803
+ augment a non-abstract variable declaration with a complete getter, setter, or
804
+ variable declaration. Likewise, it is an error to augment a complete getter or
805
+ setter with a non-abstract variable declaration.*
782
806
783
- // Augment an abstract variable with a getter and setter:
784
- abstract int b;
785
- augment int get b => 1; // OK.
786
- augment set b(int value) {} // OK.
787
-
788
- // Augment a getter with an abstract variable:
789
- int get c;
790
-
791
- @someMetadata
792
- augment abstract final int c; // (Not very useful, but valid.)
793
- }
794
- ```
807
+ It's a ** compile-time error** if:
795
808
796
- For purposes of [ signature matching] [ ] , the implicit setter induced by a
797
- non-final abstract variable has a positional parameter named ` _ ` . * This means
798
- you can augment an abstract variable with a setter that uses whatever positional
799
- parameter name you want:*
809
+ * The signature of the augmenting getter or setter does not [ match] [ signature
810
+ matching] the signature of the augmented getter or setter.
800
811
801
- ``` dart
802
- class C {
803
- abstract int x;
804
- }
812
+ * A ` const ` variable declaration is augmented or augmenting.
805
813
806
- augment class C {
807
- augment set x(int anyNameIWant) { // OK.
808
- // ...
809
- }
810
- }
811
- ```
814
+ * A getter or setter (including one implicitly induced by a variable
815
+ declaration) is not complete after all augmentations are applied, unless
816
+ it's an instance member and the surrounding class is abstract. * Every getter
817
+ or setter declaration eventually needs to have a body filled in unless it's
818
+ an instance member that can be abstract. In that case, if no declaration
819
+ provides a body, it is considered abstract. *
812
820
813
821
### Augmenting enums
814
822
815
823
An augmentation of an enum type can add new members to the enum, including new
816
824
enum values. Enum values are appended in augmentation application order.
817
825
818
826
Enum values themselves can't be augmented since they are essentially constant
819
- variables and variables can't be augmented.
827
+ variables and constant variables can't be augmented.
820
828
821
829
It's a ** compile-time error** if:
822
830
@@ -1121,6 +1129,7 @@ and assume the third point is always true.
1121
1129
1122
1130
* Remove ` augment ` from typedef grammar since typedefs can no longer be
1123
1131
augmented (#4388 ).
1132
+ * Allow augmenting variable declarations (#4387 ).
1124
1133
1125
1134
### 1.35
1126
1135
0 commit comments