@@ -38,6 +38,7 @@ enum PragmaAnnotation {
38
38
noInline,
39
39
tryInline,
40
40
disableFinal,
41
+ noElision,
41
42
noThrows,
42
43
noSideEffects,
43
44
trustTypeAnnotations,
@@ -54,18 +55,13 @@ Set<PragmaAnnotation> processMemberAnnotations(
54
55
bool hasNoInline = false ;
55
56
bool hasTryInline = false ;
56
57
bool disableFinal = false ;
58
+ bool noElision = false ;
57
59
58
60
if (_assumeDynamic (elementEnvironment, commonElements, element)) {
59
61
values.add (PragmaAnnotation .assumeDynamic);
60
62
annotationsDataBuilder.registerAssumeDynamic (element);
61
63
}
62
64
63
- // TODO(sra): Check for inappropriate annotations on fields.
64
- if (element.isField) {
65
- return values;
66
- }
67
-
68
- FunctionEntity method = element;
69
65
LibraryEntity library = element.library;
70
66
bool platformAnnotationsAllowed = library.canonicalUri.scheme == 'dart' ||
71
67
maybeEnableNative (library.canonicalUri);
@@ -74,7 +70,7 @@ Set<PragmaAnnotation> processMemberAnnotations(
74
70
bool hasNoSideEffects = false ;
75
71
76
72
for (ConstantValue constantValue
77
- in elementEnvironment.getMemberMetadata (method )) {
73
+ in elementEnvironment.getMemberMetadata (element )) {
78
74
if (! constantValue.isConstructedObject) continue ;
79
75
ConstructedConstantValue value = constantValue;
80
76
ClassEntity cls = value.type.element;
@@ -83,37 +79,69 @@ Set<PragmaAnnotation> processMemberAnnotations(
83
79
if (platformAnnotationsAllowed) {
84
80
if (cls == commonElements.forceInlineClass) {
85
81
hasTryInline = true ;
82
+ if (element is ! FunctionEntity ) {
83
+ reporter.internalError (element,
84
+ "@TryInline() is only allowed in methods and constructors." );
85
+ }
86
86
} else if (cls == commonElements.noInlineClass) {
87
87
hasNoInline = true ;
88
+ if (element is ! FunctionEntity ) {
89
+ reporter.internalError (element,
90
+ "@NoInline() is only allowed in methods and constructors." );
91
+ }
88
92
} else if (cls == commonElements.noThrowsClass) {
89
93
hasNoThrows = true ;
90
94
bool isValid = true ;
91
- if (method.isTopLevel) {
92
- isValid = true ;
93
- } else if (method.isStatic) {
94
- isValid = true ;
95
- } else if (method is ConstructorEntity && method.isFactoryConstructor) {
96
- isValid = true ;
95
+ if (element is FunctionEntity ) {
96
+ if (element.isTopLevel) {
97
+ isValid = true ;
98
+ } else if (element.isStatic) {
99
+ isValid = true ;
100
+ } else if (element is ConstructorEntity &&
101
+ element.isFactoryConstructor) {
102
+ isValid = true ;
103
+ }
104
+ } else {
105
+ isValid = false ;
97
106
}
98
107
if (! isValid) {
99
108
reporter.internalError (
100
- method ,
109
+ element ,
101
110
"@NoThrows() is currently limited to top-level"
102
111
" or static functions and factory constructors." );
103
112
}
104
- annotationsDataBuilder.registerCannotThrow (method);
113
+ if (element is FunctionEntity ) {
114
+ annotationsDataBuilder.registerCannotThrow (element);
115
+ }
105
116
} else if (cls == commonElements.noSideEffectsClass) {
106
117
hasNoSideEffects = true ;
107
- annotationsDataBuilder.registerSideEffectsFree (method);
118
+ if (element is FunctionEntity ) {
119
+ annotationsDataBuilder.registerSideEffectsFree (element);
120
+ } else {
121
+ reporter.internalError (element,
122
+ "@NoSideEffects() is only allowed in methods and constructors." );
123
+ }
108
124
}
109
125
}
110
126
111
127
if (cls == commonElements.expectNoInlineClass) {
112
128
hasNoInline = true ;
129
+ if (element is ! FunctionEntity ) {
130
+ reporter.internalError (element,
131
+ "@NoInline() is only allowed in methods and constructors." );
132
+ }
113
133
} else if (cls == commonElements.metaNoInlineClass) {
114
134
hasNoInline = true ;
135
+ if (element is ! FunctionEntity ) {
136
+ reporter.internalError (
137
+ element, "@noInline is only allowed in methods and constructors." );
138
+ }
115
139
} else if (cls == commonElements.metaTryInlineClass) {
116
140
hasTryInline = true ;
141
+ if (element is ! FunctionEntity ) {
142
+ reporter.internalError (
143
+ element, "@tryInline is only allowed in methods and constructors." );
144
+ }
117
145
} else if (cls == commonElements.pragmaClass) {
118
146
// Recognize:
119
147
//
@@ -133,12 +161,24 @@ Set<PragmaAnnotation> processMemberAnnotations(
133
161
reporter.reportErrorMessage (element, MessageKind .GENERIC ,
134
162
{'text' : "@pragma('$name ') annotation does not take options" });
135
163
}
164
+ if (element is ! FunctionEntity ) {
165
+ reporter.reportErrorMessage (element, MessageKind .GENERIC , {
166
+ 'text' : "@pragma('$name ') annotation is only supported "
167
+ "for methods and constructors."
168
+ });
169
+ }
136
170
hasNoInline = true ;
137
171
} else if (name == 'dart2js:tryInline' ) {
138
172
if (! optionsValue.isNull) {
139
173
reporter.reportErrorMessage (element, MessageKind .GENERIC ,
140
174
{'text' : "@pragma('$name ') annotation does not take options" });
141
175
}
176
+ if (element is ! FunctionEntity ) {
177
+ reporter.reportErrorMessage (element, MessageKind .GENERIC , {
178
+ 'text' : "@pragma('$name ') annotation is only supported "
179
+ "for methods and constructors."
180
+ });
181
+ }
142
182
hasTryInline = true ;
143
183
} else if (! platformAnnotationsAllowed) {
144
184
reporter.reportErrorMessage (element, MessageKind .GENERIC ,
@@ -150,7 +190,28 @@ Set<PragmaAnnotation> processMemberAnnotations(
150
190
reporter.reportErrorMessage (element, MessageKind .GENERIC ,
151
191
{'text' : "@pragma('$name ') annotation does not take options" });
152
192
}
193
+ if (element is ! FunctionEntity ) {
194
+ reporter.reportErrorMessage (element, MessageKind .GENERIC , {
195
+ 'text' : "@pragma('$name ') annotation is only supported "
196
+ "for methods and constructors."
197
+ });
198
+ }
153
199
disableFinal = true ;
200
+ } else if (name == 'dart2js:noElision' ) {
201
+ if (! optionsValue.isNull) {
202
+ reporter.reportErrorMessage (element, MessageKind .GENERIC ,
203
+ {'text' : "@pragma('$name ') annotation does not take options" });
204
+ }
205
+ if (element is ! FieldEntity ) {
206
+ reporter.reportErrorMessage (element, MessageKind .GENERIC , {
207
+ 'text' : "@pragma('$name ') annotation is only supported "
208
+ "for fields."
209
+ });
210
+ }
211
+ noElision = true ;
212
+ } else {
213
+ reporter.reportErrorMessage (element, MessageKind .GENERIC ,
214
+ {'text' : "Unknown dart2js pragma @pragma('$name ')" });
154
215
}
155
216
}
156
217
}
@@ -163,23 +224,35 @@ Set<PragmaAnnotation> processMemberAnnotations(
163
224
}
164
225
if (hasNoInline) {
165
226
values.add (PragmaAnnotation .noInline);
166
- annotationsDataBuilder.markAsNonInlinable (method);
227
+ if (element is FunctionEntity ) {
228
+ annotationsDataBuilder.markAsNonInlinable (element);
229
+ }
167
230
}
168
231
if (hasTryInline) {
169
232
values.add (PragmaAnnotation .tryInline);
170
- annotationsDataBuilder.markAsTryInline (method);
233
+ if (element is FunctionEntity ) {
234
+ annotationsDataBuilder.markAsTryInline (element);
235
+ }
171
236
}
172
237
if (disableFinal) {
173
238
values.add (PragmaAnnotation .disableFinal);
174
- annotationsDataBuilder.markAsDisableFinal (method);
239
+ if (element is FunctionEntity ) {
240
+ annotationsDataBuilder.markAsDisableFinal (element);
241
+ }
242
+ }
243
+ if (noElision) {
244
+ values.add (PragmaAnnotation .noElision);
245
+ if (element is FieldEntity ) {
246
+ annotationsDataBuilder.markAsNoElision (element);
247
+ }
175
248
}
176
249
if (hasNoThrows && ! hasNoInline) {
177
250
reporter.internalError (
178
- method , "@NoThrows() should always be combined with @noInline." );
251
+ element , "@NoThrows() should always be combined with @noInline." );
179
252
}
180
253
if (hasNoSideEffects && ! hasNoInline) {
181
254
reporter.internalError (
182
- method , "@NoSideEffects() should always be combined with @noInline." );
255
+ element , "@NoSideEffects() should always be combined with @noInline." );
183
256
}
184
257
return values;
185
258
}
@@ -200,9 +273,12 @@ abstract class AnnotationsData {
200
273
/// `@pragma('dart2js:tryInline')` annotation.
201
274
Iterable <FunctionEntity > get tryInlineFunctions;
202
275
203
- /// Functions with a `@pragma('dart2js:disable-final ')` annotation.
276
+ /// Functions with a `@pragma('dart2js:disableFinal ')` annotation.
204
277
Iterable <FunctionEntity > get disableFinalFunctions;
205
278
279
+ /// Fields with a `@pragma('dart2js:noElision')` annotation.
280
+ Iterable <FieldEntity > get noElisionFields;
281
+
206
282
/// Functions with a `@NoThrows()` annotation.
207
283
Iterable <FunctionEntity > get cannotThrowFunctions;
208
284
@@ -221,6 +297,7 @@ class AnnotationsDataImpl implements AnnotationsData {
221
297
final Iterable <FunctionEntity > nonInlinableFunctions;
222
298
final Iterable <FunctionEntity > tryInlineFunctions;
223
299
final Iterable <FunctionEntity > disableFinalFunctions;
300
+ final Iterable <FieldEntity > noElisionFields;
224
301
final Iterable <FunctionEntity > cannotThrowFunctions;
225
302
final Iterable <FunctionEntity > sideEffectFreeFunctions;
226
303
final Iterable <MemberEntity > assumeDynamicMembers;
@@ -229,6 +306,7 @@ class AnnotationsDataImpl implements AnnotationsData {
229
306
this .nonInlinableFunctions,
230
307
this .tryInlineFunctions,
231
308
this .disableFinalFunctions,
309
+ this .noElisionFields,
232
310
this .cannotThrowFunctions,
233
311
this .sideEffectFreeFunctions,
234
312
this .assumeDynamicMembers);
@@ -244,6 +322,9 @@ class AnnotationsDataImpl implements AnnotationsData {
244
322
Iterable <FunctionEntity > disableFinalFunctions =
245
323
source.readMembers <FunctionEntity >(emptyAsNull: true ) ??
246
324
const < FunctionEntity > [];
325
+ Iterable <FieldEntity > noElisionFields =
326
+ source.readMembers <FieldEntity >(emptyAsNull: true ) ??
327
+ const < FieldEntity > [];
247
328
Iterable <FunctionEntity > cannotThrowFunctions =
248
329
source.readMembers <FunctionEntity >(emptyAsNull: true ) ??
249
330
const < FunctionEntity > [];
@@ -258,6 +339,7 @@ class AnnotationsDataImpl implements AnnotationsData {
258
339
nonInlinableFunctions,
259
340
tryInlineFunctions,
260
341
disableFinalFunctions,
342
+ noElisionFields,
261
343
cannotThrowFunctions,
262
344
sideEffectFreeFunctions,
263
345
assumeDynamicMembers);
@@ -268,6 +350,7 @@ class AnnotationsDataImpl implements AnnotationsData {
268
350
sink.writeMembers (nonInlinableFunctions);
269
351
sink.writeMembers (tryInlineFunctions);
270
352
sink.writeMembers (disableFinalFunctions);
353
+ sink.writeMembers (noElisionFields);
271
354
sink.writeMembers (cannotThrowFunctions);
272
355
sink.writeMembers (sideEffectFreeFunctions);
273
356
sink.writeMembers (assumeDynamicMembers);
@@ -279,6 +362,7 @@ class AnnotationsDataBuilder implements AnnotationsData {
279
362
List <FunctionEntity > _nonInlinableFunctions;
280
363
List <FunctionEntity > _tryInlinableFunctions;
281
364
List <FunctionEntity > _disableFinalFunctions;
365
+ List <FieldEntity > _noElisionFields;
282
366
List <FunctionEntity > _cannotThrowFunctions;
283
367
List <FunctionEntity > _sideEffectFreeFunctions;
284
368
List <MemberEntity > _trustTypeAnnotationsMembers;
@@ -299,6 +383,11 @@ class AnnotationsDataBuilder implements AnnotationsData {
299
383
_disableFinalFunctions.add (function);
300
384
}
301
385
386
+ void markAsNoElision (FieldEntity field) {
387
+ _noElisionFields ?? = < FieldEntity > [];
388
+ _noElisionFields.add (field);
389
+ }
390
+
302
391
void registerCannotThrow (FunctionEntity function) {
303
392
_cannotThrowFunctions ?? = < FunctionEntity > [];
304
393
_cannotThrowFunctions.add (function);
@@ -320,6 +409,8 @@ class AnnotationsDataBuilder implements AnnotationsData {
320
409
_tryInlinableFunctions ?? const < FunctionEntity > [];
321
410
Iterable <FunctionEntity > get disableFinalFunctions =>
322
411
_disableFinalFunctions ?? const < FunctionEntity > [];
412
+ Iterable <FieldEntity > get noElisionFields =>
413
+ _noElisionFields ?? const < FieldEntity > [];
323
414
Iterable <FunctionEntity > get cannotThrowFunctions =>
324
415
_cannotThrowFunctions ?? const < FunctionEntity > [];
325
416
Iterable <FunctionEntity > get sideEffectFreeFunctions =>
0 commit comments