@@ -218,6 +218,271 @@ class ModifierContext {
218
218
}
219
219
}
220
220
221
+ /// This class parses modifiers in recovery situations,
222
+ /// but does not call handleModifier or handleModifiers.
223
+ class ModifierRecoveryContext2 {
224
+ final Parser parser;
225
+ TypeContinuation typeContinuation;
226
+ int modifierCount = 0 ;
227
+ Token abstractToken;
228
+ Token constToken;
229
+ Token covariantToken;
230
+ Token externalToken;
231
+ Token finalToken;
232
+ Token staticOrCovariant;
233
+ Token staticToken;
234
+ Token varFinalOrConst;
235
+ Token varToken;
236
+
237
+ // TODO(danrubel): Replace [ModifierRecoveryContext] and [ModifierContext]
238
+ // with this class.
239
+
240
+ ModifierRecoveryContext2 (this .parser);
241
+
242
+ /// Parse modifiers for top level functions and fields.
243
+ Token parseTopLevelModifiers (Token token, TypeContinuation typeContinuation,
244
+ {Token externalToken, Token varFinalOrConst}) {
245
+ token = parseModifiers (token, typeContinuation,
246
+ externalToken: externalToken, varFinalOrConst: varFinalOrConst);
247
+
248
+ if (abstractToken != null ) {
249
+ parser.reportRecoverableErrorWithToken (
250
+ abstractToken, fasta.templateExtraneousModifier);
251
+ }
252
+ if (staticOrCovariant != null ) {
253
+ parser.reportRecoverableErrorWithToken (
254
+ staticOrCovariant, fasta.templateExtraneousModifier);
255
+ covariantToken = null ;
256
+ staticOrCovariant = null ;
257
+ staticToken = null ;
258
+ -- modifierCount;
259
+ }
260
+ return token;
261
+ }
262
+
263
+ Token parseModifiers (Token token, TypeContinuation typeContinuation,
264
+ {Token externalToken, Token staticOrCovariant, Token varFinalOrConst}) {
265
+ this .typeContinuation = typeContinuation;
266
+ if (externalToken != null ) {
267
+ this .externalToken = externalToken;
268
+ ++ modifierCount;
269
+ }
270
+ if (staticOrCovariant != null ) {
271
+ this .staticOrCovariant = staticOrCovariant;
272
+ ++ modifierCount;
273
+ if (optional ('static' , staticOrCovariant)) {
274
+ staticToken = staticOrCovariant;
275
+ } else if (optional ('covariant' , staticOrCovariant)) {
276
+ covariantToken = staticOrCovariant;
277
+ } else {
278
+ throw "Internal error: Unexpected staticOrCovariant"
279
+ " '$staticOrCovariant '." ;
280
+ }
281
+ }
282
+ if (varFinalOrConst != null ) {
283
+ this .varFinalOrConst = varFinalOrConst;
284
+ ++ modifierCount;
285
+ if (optional ('var' , varFinalOrConst)) {
286
+ varToken = varFinalOrConst;
287
+ } else if (optional ('final' , varFinalOrConst)) {
288
+ finalToken = varFinalOrConst;
289
+ } else if (optional ('const' , varFinalOrConst)) {
290
+ constToken = varFinalOrConst;
291
+ } else {
292
+ throw "Internal error: Unexpected varFinalOrConst '$varFinalOrConst '." ;
293
+ }
294
+ }
295
+
296
+ // Process invalid and out-of-order modifiers
297
+ Token next = token.next;
298
+ while (isModifier (next)) {
299
+ final value = next.stringValue;
300
+ if (identical ('abstract' , value)) {
301
+ token = parseAbstract (token);
302
+ } else if (identical ('const' , value)) {
303
+ token = parseConst (token);
304
+ } else if (identical ('covariant' , value)) {
305
+ token = parseCovariant (token);
306
+ } else if (identical ('external' , value)) {
307
+ token = parseExternal (token);
308
+ } else if (identical ('final' , value)) {
309
+ token = parseFinal (token);
310
+ } else if (identical ('static' , value)) {
311
+ token = parseStatic (token);
312
+ } else if (identical ('var' , value)) {
313
+ token = parseVar (token);
314
+ } else {
315
+ throw 'Internal Error: Unhandled modifier: $value ' ;
316
+ }
317
+ next = token.next;
318
+ }
319
+
320
+ return token;
321
+ }
322
+
323
+ Token parseAbstract (Token token) {
324
+ Token next = token.next;
325
+ assert (optional ('abstract' , next));
326
+ if (abstractToken == null ) {
327
+ abstractToken = next;
328
+ ++ modifierCount;
329
+ return next;
330
+ }
331
+
332
+ // Recovery
333
+ parser.reportRecoverableErrorWithToken (
334
+ next, fasta.templateDuplicatedModifier);
335
+ return next;
336
+ }
337
+
338
+ Token parseConst (Token token) {
339
+ Token next = token.next;
340
+ assert (optional ('const' , next));
341
+ if (varFinalOrConst == null && covariantToken == null ) {
342
+ typeContinuation ?? = TypeContinuation .Optional ;
343
+ varFinalOrConst = constToken = next;
344
+ ++ modifierCount;
345
+ return next;
346
+ }
347
+
348
+ // Recovery
349
+ if (constToken != null ) {
350
+ parser.reportRecoverableErrorWithToken (
351
+ next, fasta.templateDuplicatedModifier);
352
+ } else if (covariantToken != null ) {
353
+ parser.reportRecoverableError (next, fasta.messageConstAndCovariant);
354
+ } else if (finalToken != null ) {
355
+ parser.reportRecoverableError (next, fasta.messageConstAndFinal);
356
+ } else if (varToken != null ) {
357
+ parser.reportRecoverableError (next, fasta.messageConstAndVar);
358
+ } else {
359
+ throw 'Internal Error: Unexpected varFinalOrConst: $varFinalOrConst ' ;
360
+ }
361
+ return next;
362
+ }
363
+
364
+ Token parseCovariant (Token token) {
365
+ Token next = token.next;
366
+ assert (optional ('covariant' , next));
367
+ if (staticOrCovariant == null && constToken == null ) {
368
+ staticOrCovariant = covariantToken = next;
369
+ ++ modifierCount;
370
+
371
+ if (varToken != null ) {
372
+ parser.reportRecoverableError (next, fasta.messageCovariantAfterVar);
373
+ } else if (finalToken != null ) {
374
+ parser.reportRecoverableError (next, fasta.messageCovariantAfterFinal);
375
+ }
376
+ return next;
377
+ }
378
+
379
+ // Recovery
380
+ if (constToken != null ) {
381
+ parser.reportRecoverableError (next, fasta.messageConstAndCovariant);
382
+ } else if (covariantToken != null ) {
383
+ parser.reportRecoverableErrorWithToken (
384
+ next, fasta.templateDuplicatedModifier);
385
+ } else if (staticToken != null ) {
386
+ parser.reportRecoverableError (next, fasta.messageCovariantAndStatic);
387
+ } else {
388
+ throw 'Internal Error: Unexpected staticOrCovariant: $staticOrCovariant ' ;
389
+ }
390
+ return next;
391
+ }
392
+
393
+ Token parseExternal (Token token) {
394
+ Token next = token.next;
395
+ assert (optional ('external' , next));
396
+ if (externalToken == null ) {
397
+ externalToken = next;
398
+ ++ modifierCount;
399
+ return next;
400
+ }
401
+
402
+ // Recovery
403
+ parser.reportRecoverableErrorWithToken (
404
+ next, fasta.templateExtraneousModifier);
405
+ return next;
406
+ }
407
+
408
+ Token parseFinal (Token token) {
409
+ Token next = token.next;
410
+ assert (optional ('final' , next));
411
+ if (varFinalOrConst == null ) {
412
+ typeContinuation ?? = TypeContinuation .Optional ;
413
+ varFinalOrConst = finalToken = next;
414
+ ++ modifierCount;
415
+ return next;
416
+ }
417
+
418
+ // Recovery
419
+ if (constToken != null ) {
420
+ parser.reportRecoverableError (next, fasta.messageConstAndFinal);
421
+ } else if (finalToken != null ) {
422
+ parser.reportRecoverableErrorWithToken (
423
+ next, fasta.templateDuplicatedModifier);
424
+ } else if (varToken != null ) {
425
+ parser.reportRecoverableError (next, fasta.messageFinalAndVar);
426
+ } else {
427
+ throw 'Internal Error: Unexpected varFinalOrConst: $varFinalOrConst ' ;
428
+ }
429
+ return next;
430
+ }
431
+
432
+ Token parseStatic (Token token) {
433
+ Token next = token.next;
434
+ assert (optional ('static' , next));
435
+ if (staticOrCovariant == null ) {
436
+ staticOrCovariant = staticToken = next;
437
+ ++ modifierCount;
438
+
439
+ if (constToken != null ) {
440
+ parser.reportRecoverableError (next, fasta.messageStaticAfterConst);
441
+ } else if (finalToken != null ) {
442
+ parser.reportRecoverableError (next, fasta.messageStaticAfterFinal);
443
+ } else if (varToken != null ) {
444
+ parser.reportRecoverableError (next, fasta.messageStaticAfterVar);
445
+ }
446
+ return next;
447
+ }
448
+
449
+ // Recovery
450
+ if (covariantToken != null ) {
451
+ parser.reportRecoverableError (next, fasta.messageCovariantAndStatic);
452
+ } else if (staticToken != null ) {
453
+ parser.reportRecoverableErrorWithToken (
454
+ next, fasta.templateDuplicatedModifier);
455
+ } else {
456
+ throw 'Internal Error: Unexpected staticOrCovariant: $staticOrCovariant ' ;
457
+ }
458
+ return next;
459
+ }
460
+
461
+ Token parseVar (Token token) {
462
+ Token next = token.next;
463
+ assert (optional ('var' , next));
464
+ if (varFinalOrConst == null ) {
465
+ typeContinuation = typeContinuationAfterVar (typeContinuation);
466
+ varFinalOrConst = varToken = next;
467
+ ++ modifierCount;
468
+ return next;
469
+ }
470
+
471
+ // Recovery
472
+ if (constToken != null ) {
473
+ parser.reportRecoverableError (next, fasta.messageConstAndVar);
474
+ } else if (finalToken != null ) {
475
+ parser.reportRecoverableError (next, fasta.messageFinalAndVar);
476
+ } else if (varToken != null ) {
477
+ parser.reportRecoverableErrorWithToken (
478
+ next, fasta.templateDuplicatedModifier);
479
+ } else {
480
+ throw 'Internal Error: Unexpected varFinalOrConst: $varFinalOrConst ' ;
481
+ }
482
+ return next;
483
+ }
484
+ }
485
+
221
486
class ModifierRecoveryContext extends ModifierContext {
222
487
Token constToken;
223
488
Token covariantToken;
@@ -685,32 +950,3 @@ class FactoryModifierContext {
685
950
}
686
951
}
687
952
}
688
-
689
- class TopLevelMethodModifierContext {
690
- final Parser parser;
691
- Token externalToken;
692
-
693
- TopLevelMethodModifierContext (this .parser);
694
-
695
- /// Parse modifiers from the tokens following [token] .
696
- Token parseRecovery (Token token) {
697
- Token beforeToken = token;
698
- while (isModifier (token.next)) {
699
- beforeToken = token;
700
- token = token.next;
701
- if (optional ('external' , token)) {
702
- if (externalToken == null ) {
703
- externalToken = token;
704
- } else {
705
- parser.reportRecoverableErrorWithToken (
706
- token, fasta.templateDuplicatedModifier);
707
- }
708
- } else {
709
- // TODO(danrubel): report more specific analyzer error codes
710
- parser.reportRecoverableErrorWithToken (
711
- token, fasta.templateExtraneousModifier);
712
- }
713
- }
714
- return beforeToken;
715
- }
716
- }
0 commit comments