@@ -38,6 +38,10 @@ import 'util.dart'
38
38
/// when there is a single identifier as the type reference.
39
39
const TypeInfo simpleType = const SimpleType ();
40
40
41
+ /// [SimpleNullableType] is a specialized [TypeInfo] returned by [computeType]
42
+ /// when there is a single identifier followed by `?` as the type reference.
43
+ const TypeInfo simpleNullableType = const SimpleNullableType ();
44
+
41
45
/// [PrefixedType] is a specialized [TypeInfo] returned by [computeType]
42
46
/// when the type reference is of the form: identifier `.` identifier.
43
47
const TypeInfo prefixedType = const PrefixedType ();
@@ -60,6 +64,12 @@ const TypeInfo simpleTypeWith1ArgumentGtEq =
60
64
const TypeInfo simpleTypeWith1ArgumentGtGt =
61
65
const SimpleTypeWith1Argument (simpleTypeArgument1GtGt);
62
66
67
+ /// [SimpleNullableTypeWith1Argument] is a specialized [TypeInfo] returned by
68
+ /// [computeType] when the type reference is of the form:
69
+ /// identifier `<` identifier `>` `?` .
70
+ const TypeInfo simpleNullableTypeWith1Argument =
71
+ const SimpleNullableTypeWith1Argument ();
72
+
63
73
/// [SimpleTypeArgument1] is a specialized [TypeParamOrArgInfo] returned by
64
74
/// [computeTypeParamOrArg] when the type reference is of the form:
65
75
/// `<` identifier `>` .
@@ -82,10 +92,10 @@ class NoType implements TypeInfo {
82
92
const NoType ();
83
93
84
94
@override
85
- bool get couldBeExpression => false ;
95
+ TypeInfo get asNonNullable => this ;
86
96
87
97
@override
88
- TypeInfo asNonNullableType () => this ;
98
+ bool get couldBeExpression => false ;
89
99
90
100
@override
91
101
Token ensureTypeNotVoid (Token token, Parser parser) {
@@ -99,6 +109,9 @@ class NoType implements TypeInfo {
99
109
Token ensureTypeOrVoid (Token token, Parser parser) =>
100
110
ensureTypeNotVoid (token, parser);
101
111
112
+ @override
113
+ bool isConditionalExpressionStart (Token token, Parser parser) => false ;
114
+
102
115
@override
103
116
Token parseTypeNotVoid (Token token, Parser parser) =>
104
117
parseType (token, parser);
@@ -120,10 +133,10 @@ class PrefixedType implements TypeInfo {
120
133
const PrefixedType ();
121
134
122
135
@override
123
- bool get couldBeExpression => true ;
136
+ TypeInfo get asNonNullable => this ;
124
137
125
138
@override
126
- TypeInfo asNonNullableType () => this ;
139
+ bool get couldBeExpression => true ;
127
140
128
141
@override
129
142
Token ensureTypeNotVoid (Token token, Parser parser) =>
@@ -133,6 +146,9 @@ class PrefixedType implements TypeInfo {
133
146
Token ensureTypeOrVoid (Token token, Parser parser) =>
134
147
parseType (token, parser);
135
148
149
+ @override
150
+ bool isConditionalExpressionStart (Token token, Parser parser) => false ;
151
+
136
152
@override
137
153
Token parseTypeNotVoid (Token token, Parser parser) =>
138
154
parseType (token, parser);
@@ -164,17 +180,44 @@ class PrefixedType implements TypeInfo {
164
180
}
165
181
}
166
182
183
+ /// See documentation on the [simpleNullableTypeWith1Argument] const.
184
+ class SimpleNullableTypeWith1Argument extends SimpleTypeWith1Argument {
185
+ const SimpleNullableTypeWith1Argument () : super (simpleTypeArgument1);
186
+
187
+ @override
188
+ TypeInfo get asNonNullable => simpleTypeWith1Argument;
189
+
190
+ @override
191
+ bool isConditionalExpressionStart (Token token, Parser parser) =>
192
+ isConditionalThenExpression (skipType (token), parser);
193
+
194
+ @override
195
+ Token parseTypeRest (Token start, Token token, Parser parser) {
196
+ token = token.next;
197
+ assert (optional ('?' , token));
198
+ parser.listener.handleType (start, token);
199
+ return token;
200
+ }
201
+
202
+ @override
203
+ Token skipType (Token token) {
204
+ token = super .skipType (token).next;
205
+ assert (optional ('?' , token));
206
+ return token;
207
+ }
208
+ }
209
+
167
210
/// See documentation on the [simpleTypeWith1Argument] const.
168
211
class SimpleTypeWith1Argument implements TypeInfo {
169
212
final TypeParamOrArgInfo typeArg;
170
213
171
214
const SimpleTypeWith1Argument (this .typeArg);
172
215
173
216
@override
174
- bool get couldBeExpression => false ;
217
+ TypeInfo get asNonNullable => this ;
175
218
176
219
@override
177
- TypeInfo asNonNullableType () => this ;
220
+ bool get couldBeExpression => false ;
178
221
179
222
@override
180
223
Token ensureTypeNotVoid (Token token, Parser parser) =>
@@ -184,6 +227,9 @@ class SimpleTypeWith1Argument implements TypeInfo {
184
227
Token ensureTypeOrVoid (Token token, Parser parser) =>
185
228
parseType (token, parser);
186
229
230
+ @override
231
+ bool isConditionalExpressionStart (Token token, Parser parser) => false ;
232
+
187
233
@override
188
234
Token parseTypeNotVoid (Token token, Parser parser) =>
189
235
parseType (token, parser);
@@ -210,15 +256,40 @@ class SimpleTypeWith1Argument implements TypeInfo {
210
256
}
211
257
}
212
258
259
+ /// See documentation on the [simpleNullableType] const.
260
+ class SimpleNullableType extends SimpleType {
261
+ const SimpleNullableType ();
262
+
263
+ @override
264
+ TypeInfo get asNonNullable => simpleType;
265
+
266
+ @override
267
+ bool isConditionalExpressionStart (Token token, Parser parser) =>
268
+ isConditionalThenExpression (skipType (token), parser);
269
+
270
+ @override
271
+ Token parseTypeRest (Token start, Parser parser) {
272
+ Token token = start.next;
273
+ assert (optional ('?' , token));
274
+ parser.listener.handleType (start, token);
275
+ return token;
276
+ }
277
+
278
+ @override
279
+ Token skipType (Token token) {
280
+ return token.next.next;
281
+ }
282
+ }
283
+
213
284
/// See documentation on the [simpleType] const.
214
285
class SimpleType implements TypeInfo {
215
286
const SimpleType ();
216
287
217
288
@override
218
- bool get couldBeExpression => true ;
289
+ TypeInfo get asNonNullable => this ;
219
290
220
291
@override
221
- TypeInfo asNonNullableType () => this ;
292
+ bool get couldBeExpression => true ;
222
293
223
294
@override
224
295
Token ensureTypeNotVoid (Token token, Parser parser) =>
@@ -228,6 +299,9 @@ class SimpleType implements TypeInfo {
228
299
Token ensureTypeOrVoid (Token token, Parser parser) =>
229
300
parseType (token, parser);
230
301
302
+ @override
303
+ bool isConditionalExpressionStart (Token token, Parser parser) => false ;
304
+
231
305
@override
232
306
Token parseTypeNotVoid (Token token, Parser parser) =>
233
307
parseType (token, parser);
@@ -257,10 +331,10 @@ class VoidType implements TypeInfo {
257
331
const VoidType ();
258
332
259
333
@override
260
- bool get couldBeExpression => false ;
334
+ TypeInfo get asNonNullable => this ;
261
335
262
336
@override
263
- TypeInfo asNonNullableType () => this ;
337
+ bool get couldBeExpression => false ;
264
338
265
339
@override
266
340
Token ensureTypeNotVoid (Token token, Parser parser) {
@@ -273,6 +347,9 @@ class VoidType implements TypeInfo {
273
347
Token ensureTypeOrVoid (Token token, Parser parser) =>
274
348
parseType (token, parser);
275
349
350
+ @override
351
+ bool isConditionalExpressionStart (Token token, Parser parser) => false ;
352
+
276
353
@override
277
354
Token parseTypeNotVoid (Token token, Parser parser) =>
278
355
ensureTypeNotVoid (token, parser);
@@ -337,13 +414,13 @@ class ComplexTypeInfo implements TypeInfo {
337
414
: this .start = beforeStart.next;
338
415
339
416
@override
340
- bool get couldBeExpression => false ;
341
-
342
- @override
343
- TypeInfo asNonNullableType () {
417
+ TypeInfo get asNonNullable {
344
418
return this ;
345
419
}
346
420
421
+ @override
422
+ bool get couldBeExpression => false ;
423
+
347
424
@override
348
425
Token ensureTypeNotVoid (Token token, Parser parser) =>
349
426
parseType (token, parser);
@@ -352,6 +429,12 @@ class ComplexTypeInfo implements TypeInfo {
352
429
Token ensureTypeOrVoid (Token token, Parser parser) =>
353
430
parseType (token, parser);
354
431
432
+ @override
433
+ bool isConditionalExpressionStart (Token token, Parser parser) {
434
+ //return isConditionalThenExpression(token.next.next, parser);
435
+ return false ;
436
+ }
437
+
355
438
@override
356
439
Token parseTypeNotVoid (Token token, Parser parser) =>
357
440
parseType (token, parser);
@@ -1061,3 +1144,16 @@ Token splitCloser(Token closer) {
1061
1144
}
1062
1145
return null ;
1063
1146
}
1147
+
1148
+ /// Return `true` if the tokens after [token]
1149
+ /// represent a valid expression followed by a `:` .
1150
+ bool isConditionalThenExpression (Token token, Parser parser) {
1151
+ // TODO(danrubel): Consider adding checks for simple situations
1152
+ // before resorting to heavy weight lookahead.
1153
+
1154
+ final originalListener = parser.listener;
1155
+ parser.listener = new ForwardingListener ();
1156
+ token = parser.parseExpression (token);
1157
+ parser.listener = originalListener;
1158
+ return optional (':' , token.next);
1159
+ }
0 commit comments