@@ -335,6 +335,17 @@ class Parser {
335
335
{this .useImplicitCreationExpression = true , this .allowPatterns = false })
336
336
: assert (listener != null ); // ignore:unnecessary_null_comparison
337
337
338
+ /// Executes [callback] ; however if `this` is the `TestParser` (from
339
+ /// `pkg/front_end/test/parser_test_parser.dart` ) then no output is printed
340
+ /// during its execution.
341
+ ///
342
+ /// This is sometimes necessary inside `assert` statements, to ensure that the
343
+ /// output of `TestParser` is the same regardless of whether assertions are
344
+ /// enabled.
345
+ T inhibitPrinting <T >(T Function () callback) {
346
+ return callback ();
347
+ }
348
+
338
349
bool get inGenerator {
339
350
return asyncState == AsyncModifier .AsyncStar ||
340
351
asyncState == AsyncModifier .SyncStar ;
@@ -9249,7 +9260,7 @@ class Parser {
9249
9260
/// | listPattern
9250
9261
/// | mapPattern
9251
9262
/// | recordPattern
9252
- /// | extractorPattern
9263
+ /// | objectPattern
9253
9264
/// listPattern ::= typeArguments? '[' patterns? '] '
9254
9265
/// mapPattern ::= typeArguments? '{' mapPatternEntries? '}'
9255
9266
/// mapPatternEntries ::= mapPatternEntry ( ',' mapPatternEntry )* ','?
@@ -9269,10 +9280,9 @@ class Parser {
9269
9280
/// | 'const' typeArguments? '[' elements? ']'
9270
9281
/// | 'const' typeArguments? '{' elements? '}'
9271
9282
/// | 'const' '(' expression ')'
9272
- /// extractorPattern ::= extractorName typeArguments?
9273
- /// '(' patternFields? ')'
9274
- /// extractorName ::= typeIdentifier | qualifiedName
9283
+ /// objectPattern ::= typeName typeArguments? '(' patternFields? ')'
9275
9284
Token parsePrimaryPattern (Token token, {required bool isRefutableContext}) {
9285
+ Token start = token;
9276
9286
TypeParamOrArgInfo typeArg =
9277
9287
computeTypeParamOrArg (token, /* inDeclaration = */ true );
9278
9288
Token next = typeArg.skip (token).next! ;
@@ -9281,15 +9291,25 @@ class Parser {
9281
9291
case '[' :
9282
9292
// listPattern ::= typeArguments? '[' patterns? ']'
9283
9293
token = typeArg.parseArguments (token, this );
9284
- return parseListPatternSuffix (token,
9294
+ token = parseListPatternSuffix (token,
9285
9295
isRefutableContext: isRefutableContext);
9296
+ // A list pattern is a valid form of outerPattern, so verify that
9297
+ // skipOuterPattern would have skipped this pattern properly.
9298
+ assert (
9299
+ identical (inhibitPrinting (() => skipOuterPattern (start)), token));
9300
+ return token;
9286
9301
case '{' :
9287
9302
// mapPattern ::= typeArguments? '{' mapPatternEntries? '}'
9288
9303
// mapPatternEntries ::= mapPatternEntry ( ',' mapPatternEntry )* ','?
9289
9304
// mapPatternEntry ::= expression ':' pattern
9290
9305
token = typeArg.parseArguments (token, this );
9291
- return parseMapPatternSuffix (token,
9306
+ token = parseMapPatternSuffix (token,
9292
9307
isRefutableContext: isRefutableContext);
9308
+ // A map pattern is a valid form of outerPattern, so verify that
9309
+ // skipOuterPattern would have skipped this pattern properly.
9310
+ assert (
9311
+ identical (inhibitPrinting (() => skipOuterPattern (start)), token));
9312
+ return token;
9293
9313
}
9294
9314
// Whatever was after the optional type arguments didn't parse as a pattern
9295
9315
// that can start with type arguments, so back up and reparse assuming that
@@ -9308,11 +9328,17 @@ class Parser {
9308
9328
Token nextNext = next.next! ;
9309
9329
if (optional (')' , nextNext)) {
9310
9330
listener.handleRecordPattern (next, /* count = */ 0 );
9311
- return nextNext;
9331
+ token = nextNext;
9312
9332
} else {
9313
- return parseParenthesizedPatternOrRecordPattern (token,
9333
+ token = parseParenthesizedPatternOrRecordPattern (token,
9314
9334
isRefutableContext: isRefutableContext);
9315
9335
}
9336
+ // A record or parenthesized pattern is a valid form of outerPattern, so
9337
+ // verify that skipOuterPattern would have skipped this pattern
9338
+ // properly.
9339
+ assert (
9340
+ identical (inhibitPrinting (() => skipOuterPattern (start)), token));
9341
+ return token;
9316
9342
case 'const' :
9317
9343
// constantPattern ::= booleanLiteral
9318
9344
// | nullLiteral
@@ -9352,9 +9378,7 @@ class Parser {
9352
9378
if (typeInfo != noType) {
9353
9379
return parseVariablePattern (token, typeInfo: typeInfo);
9354
9380
}
9355
- // extractorPattern ::= extractorName typeArguments?
9356
- // '(' patternFields? ')'
9357
- // extractorName ::= typeIdentifier | qualifiedName
9381
+ // objectPattern ::= typeName typeArguments? '(' patternFields? ')'
9358
9382
// TODO(paulberry): Make sure OTHER_IDENTIFIER is handled
9359
9383
// TODO(paulberry): Technically `dynamic` is valid for
9360
9384
// `typeIdentifier`--file an issue
@@ -9381,9 +9405,13 @@ class Parser {
9381
9405
if (optional ('(' , afterToken) && ! potentialTypeArg.recovered) {
9382
9406
TypeParamOrArgInfo typeArg = potentialTypeArg;
9383
9407
token = typeArg.parseArguments (token, this );
9384
- token = parseExtractorPatternRest (token,
9408
+ token = parseObjectPatternRest (token,
9385
9409
isRefutableContext: isRefutableContext);
9386
- listener.handleExtractorPattern (firstIdentifier, dot, secondIdentifier);
9410
+ listener.handleObjectPattern (firstIdentifier, dot, secondIdentifier);
9411
+ // An object pattern is a valid form of outerPattern, so verify that
9412
+ // skipOuterPattern would have skipped this pattern properly.
9413
+ assert (
9414
+ identical (inhibitPrinting (() => skipOuterPattern (start)), token));
9387
9415
return token;
9388
9416
} else if (dot == null ) {
9389
9417
// It's a single identifier. If it's a wildcard pattern or we're in an
@@ -9395,7 +9423,7 @@ class Parser {
9395
9423
typeInfo: typeInfo);
9396
9424
}
9397
9425
}
9398
- // It's not an extractor pattern so parse it as an expression.
9426
+ // It's not an object pattern so parse it as an expression.
9399
9427
token = beforeFirstIdentifier;
9400
9428
}
9401
9429
// TODO(paulberry): report error if this constant is not permitted by the
@@ -9642,12 +9670,11 @@ class Parser {
9642
9670
return token;
9643
9671
}
9644
9672
9645
- /// Parses the rest of an extractorPattern , where [token] is the token before
9646
- /// the `(` .
9673
+ /// Parses the rest of an objectPattern , where [token] is the token before the
9674
+ /// `(` .
9647
9675
///
9648
- /// extractorPattern ::= extractorName typeArguments?
9649
- /// '(' patternFields? ')'
9650
- Token parseExtractorPatternRest (Token token,
9676
+ /// objectPattern ::= typeName typeArguments? '(' patternFields? ')'
9677
+ Token parseObjectPatternRest (Token token,
9651
9678
{required bool isRefutableContext}) {
9652
9679
Token begin = token = token.next! ;
9653
9680
assert (optional ('(' , begin));
@@ -9697,7 +9724,7 @@ class Parser {
9697
9724
}
9698
9725
assert (optional (')' , token));
9699
9726
mayParseFunctionExpressions = old;
9700
- listener.handleExtractorPatternFields (argumentCount, begin, token);
9727
+ listener.handleObjectPatternFields (argumentCount, begin, token);
9701
9728
return token;
9702
9729
}
9703
9730
@@ -9719,19 +9746,19 @@ class Parser {
9719
9746
/// | listPattern
9720
9747
/// | mapPattern
9721
9748
/// | recordPattern
9722
- /// | extractorPattern
9749
+ /// | objectPattern
9723
9750
Token ? skipOuterPattern (Token token) {
9724
9751
Token next = token.next! ;
9725
9752
if (next.isIdentifier) {
9726
9753
token = next;
9727
9754
next = token.next! ;
9728
9755
if (! optional ('.' , next)) {
9729
- return skipExtractorPatternRest (token);
9756
+ return skipObjectPatternRest (token);
9730
9757
}
9731
9758
token = next;
9732
9759
next = token.next! ;
9733
9760
if (next.isIdentifier) {
9734
- return skipExtractorPatternRest (next);
9761
+ return skipObjectPatternRest (next);
9735
9762
} else {
9736
9763
throw new UnimplementedError ('TODO(paulberry)' );
9737
9764
}
@@ -9754,12 +9781,12 @@ class Parser {
9754
9781
throw new UnimplementedError ('TODO(paulberry)' );
9755
9782
}
9756
9783
9757
- /// Tries to advance through an extractor pattern, where [token] is the last
9758
- /// token of the extractor pattern's type name. If the tokens following
9759
- /// [token] don't look like the rest of an extractor pattern, returns `null` .
9784
+ /// Tries to advance through an object pattern, where [token] is the last
9785
+ /// token of the object pattern's type name. If the tokens following
9786
+ /// [token] don't look like the rest of an object pattern, returns `null` .
9760
9787
///
9761
- /// extractorPattern ::= typeName typeArguments? '(' patternFields? ')'
9762
- Token ? skipExtractorPatternRest (Token token) {
9788
+ /// objectPattern ::= typeName typeArguments? '(' patternFields? ')'
9789
+ Token ? skipObjectPatternRest (Token token) {
9763
9790
TypeParamOrArgInfo typeParamOrArg = computeTypeParamOrArg (token);
9764
9791
token = typeParamOrArg.skip (token);
9765
9792
Token ? next = token.next;
0 commit comments