From 76f803a41caf6f4c37c0514b5954a77fb869046c Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Tue, 30 May 2023 12:48:26 +0000 Subject: [PATCH] Additional test cases in support of record/variable pattern disambiguation. Two of these tests (`recordPattern_nullable_beforeAs` and `recordPattern_nullable_beforeWhen`) verify that the fix for #52439 (Destructuring with explicit type of nullable record is a parsing error), which causes `(...)? identifier` to be recognized as a variable pattern, doesn't get confused by the pseudo-identifiers `as` and `when`, and so it continues to correctly parse `(...)? as ...` as a cast pattern and `(...)? when ...` as a guarded pattern. The other two tests (`recordPattern_nonNullable_beforeAs` and `recordPattern_nonNullable_beforeWhen`) verify that `(...) as ...` and `(...) when ...` are parsed correctly. These forms were never broken, but they were not well tested either. Bug: https://github.com/dart-lang/sdk/issues/52439 Change-Id: I866e1c7a6a8e47e0cd91a1a77654405f395b50da Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/305844 Reviewed-by: Jens Johansen Commit-Queue: Paul Berry --- .../test/generated/patterns_parser_test.dart | 116 +++++++++++++++++ .../recordPattern_nonNullable_beforeAs.dart | 5 + ...rdPattern_nonNullable_beforeAs.dart.expect | 58 +++++++++ ...nNullable_beforeAs.dart.intertwined.expect | 116 +++++++++++++++++ ...rn_nonNullable_beforeAs.dart.parser.expect | 13 ++ ...n_nonNullable_beforeAs.dart.scanner.expect | 13 ++ .../recordPattern_nonNullable_beforeWhen.dart | 5 + ...Pattern_nonNullable_beforeWhen.dart.expect | 47 +++++++ ...ullable_beforeWhen.dart.intertwined.expect | 108 ++++++++++++++++ ..._nonNullable_beforeWhen.dart.parser.expect | 13 ++ ...nonNullable_beforeWhen.dart.scanner.expect | 13 ++ .../recordPattern_nullable_beforeAs.dart | 5 + ...ecordPattern_nullable_beforeAs.dart.expect | 66 ++++++++++ ..._nullable_beforeAs.dart.intertwined.expect | 119 ++++++++++++++++++ ...ttern_nullable_beforeAs.dart.parser.expect | 13 ++ ...tern_nullable_beforeAs.dart.scanner.expect | 13 ++ .../recordPattern_nullable_beforeWhen.dart | 5 + ...ordPattern_nullable_beforeWhen.dart.expect | 48 +++++++ ...ullable_beforeWhen.dart.intertwined.expect | 109 ++++++++++++++++ ...ern_nullable_beforeWhen.dart.parser.expect | 13 ++ ...rn_nullable_beforeWhen.dart.scanner.expect | 13 ++ 21 files changed, 911 insertions(+) create mode 100644 pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeAs.dart create mode 100644 pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeAs.dart.expect create mode 100644 pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeAs.dart.intertwined.expect create mode 100644 pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeAs.dart.parser.expect create mode 100644 pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeAs.dart.scanner.expect create mode 100644 pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeWhen.dart create mode 100644 pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeWhen.dart.expect create mode 100644 pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeWhen.dart.intertwined.expect create mode 100644 pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeWhen.dart.parser.expect create mode 100644 pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeWhen.dart.scanner.expect create mode 100644 pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeAs.dart create mode 100644 pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeAs.dart.expect create mode 100644 pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeAs.dart.intertwined.expect create mode 100644 pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeAs.dart.parser.expect create mode 100644 pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeAs.dart.scanner.expect create mode 100644 pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeWhen.dart create mode 100644 pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeWhen.dart.expect create mode 100644 pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeWhen.dart.intertwined.expect create mode 100644 pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeWhen.dart.parser.expect create mode 100644 pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeWhen.dart.scanner.expect diff --git a/pkg/analyzer/test/generated/patterns_parser_test.dart b/pkg/analyzer/test/generated/patterns_parser_test.dart index 698db1e7f9fe..57beed6691b9 100644 --- a/pkg/analyzer/test/generated/patterns_parser_test.dart +++ b/pkg/analyzer/test/generated/patterns_parser_test.dart @@ -8509,6 +8509,122 @@ NullCheckPattern '''); } + test_recordPattern_nonNullable_beforeAs() { + _parse(''' +void f(x) { + switch (x) { + case (_,) as (Object,): + } +} +'''); + var node = findNode.singleGuardedPattern; + assertParsedNodeText(node, r''' +GuardedPattern + pattern: CastPattern + pattern: RecordPattern + leftParenthesis: ( + fields + PatternField + pattern: WildcardPattern + name: _ + rightParenthesis: ) + asToken: as + type: RecordTypeAnnotation + leftParenthesis: ( + positionalFields + RecordTypeAnnotationPositionalField + type: NamedType + name: Object + rightParenthesis: ) +'''); + } + + test_recordPattern_nonNullable_beforeWhen() { + _parse(''' +void f(x) { + switch (x) { + case (_,) when true: + } +} +'''); + var node = findNode.singleGuardedPattern; + assertParsedNodeText(node, r''' +GuardedPattern + pattern: RecordPattern + leftParenthesis: ( + fields + PatternField + pattern: WildcardPattern + name: _ + rightParenthesis: ) + whenClause: WhenClause + whenKeyword: when + expression: BooleanLiteral + literal: true +'''); + } + + test_recordPattern_nullable_beforeAs() { + _parse(''' +void f(x) { + switch (x) { + case (_,)? as (Object,): + } +} +''', errors: [ + error(ParserErrorCode.INVALID_INSIDE_UNARY_PATTERN, 36, 5), + ]); + var node = findNode.singleGuardedPattern; + assertParsedNodeText(node, r''' +GuardedPattern + pattern: CastPattern + pattern: NullCheckPattern + pattern: RecordPattern + leftParenthesis: ( + fields + PatternField + pattern: WildcardPattern + name: _ + rightParenthesis: ) + operator: ? + asToken: as + type: RecordTypeAnnotation + leftParenthesis: ( + positionalFields + RecordTypeAnnotationPositionalField + type: NamedType + name: Object + rightParenthesis: ) +'''); + } + + test_recordPattern_nullable_beforeWhen() { + _parse(''' +void f(x) { + switch (x) { + case (_,)? when true: + } +} +'''); + var node = findNode.singleGuardedPattern; + assertParsedNodeText(node, r''' +GuardedPattern + pattern: NullCheckPattern + pattern: RecordPattern + leftParenthesis: ( + fields + PatternField + pattern: WildcardPattern + name: _ + rightParenthesis: ) + operator: ? + whenClause: WhenClause + whenKeyword: when + expression: BooleanLiteral + literal: true +'''); + } + test_recordTypedVariablePattern_nonNullable_beforeAnd() { _parse(''' void f(x) { diff --git a/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeAs.dart b/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeAs.dart new file mode 100644 index 000000000000..2316ec8a54ee --- /dev/null +++ b/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeAs.dart @@ -0,0 +1,5 @@ +void f(x) { + switch (x) { + case (_,) as (Object,): + } +} diff --git a/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeAs.dart.expect b/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeAs.dart.expect new file mode 100644 index 000000000000..20a37875b708 --- /dev/null +++ b/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeAs.dart.expect @@ -0,0 +1,58 @@ +beginCompilationUnit(void) + beginMetadataStar(void) + endMetadataStar(0) + beginTopLevelMember(void) + beginTopLevelMethod(, null, null) + handleVoidKeyword(void) + handleIdentifier(f, topLevelFunctionDeclaration) + handleNoTypeVariables(() + beginFormalParameters((, MemberKind.TopLevelMethod) + beginMetadataStar(x) + endMetadataStar(0) + beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null) + handleNoType(() + handleIdentifier(x, formalParameterDeclaration) + handleFormalParameterWithoutValue()) + endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod) + endFormalParameters(1, (, ), MemberKind.TopLevelMethod) + handleAsyncModifier(null, null) + beginBlockFunctionBody({) + beginSwitchStatement(switch) + handleIdentifier(x, expression) + handleNoTypeArguments()) + handleNoArguments()) + handleSend(x, )) + handleParenthesizedCondition((, null, null) + beginSwitchBlock({) + beginCaseExpression(case) + beginPattern(case) + beginPattern(() + handleNoType(_) + handleWildcardPattern(null, _) + endPattern(_) + handlePatternField(null) + handleRecordPattern((, 1) + beginAsOperatorType(as) + beginRecordType(() + beginRecordTypeEntry() + beginMetadataStar(Object) + endMetadataStar(0) + handleIdentifier(Object, typeReference) + handleNoTypeArguments(,) + handleType(Object, null) + handleNoName(,) + endRecordTypeEntry() + endRecordType((, null, 1, false) + endAsOperatorType(as) + handleCastPattern(as) + endPattern()) + handleSwitchCaseNoWhenClause()) + endCaseExpression(case, null, :) + beginSwitchCase(0, 1, case) + endSwitchCase(0, 1, null, null, 0, case, }) + endSwitchBlock(1, {, }) + endSwitchStatement(switch, }) + endBlockFunctionBody(1, {, }) + endTopLevelMethod(void, null, }) + endTopLevelDeclaration() +endCompilationUnit(1, ) diff --git a/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeAs.dart.intertwined.expect b/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeAs.dart.intertwined.expect new file mode 100644 index 000000000000..7c0837fd293f --- /dev/null +++ b/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeAs.dart.intertwined.expect @@ -0,0 +1,116 @@ +parseUnit(void) + skipErrorTokens(void) + listener: beginCompilationUnit(void) + syntheticPreviousToken(void) + parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext') + parseMetadataStar() + listener: beginMetadataStar(void) + listener: endMetadataStar(0) + parseTopLevelMemberImpl() + listener: beginTopLevelMember(void) + parseTopLevelMethod(, null, null, , Instance of 'VoidType', null, f, false) + listener: beginTopLevelMethod(, null, null) + listener: handleVoidKeyword(void) + ensureIdentifierPotentiallyRecovered(void, topLevelFunctionDeclaration, false) + listener: handleIdentifier(f, topLevelFunctionDeclaration) + parseMethodTypeVar(f) + listener: handleNoTypeVariables(() + parseGetterOrFormalParameters(f, f, false, MemberKind.TopLevelMethod) + parseFormalParameters(f, MemberKind.TopLevelMethod) + parseFormalParametersRest((, MemberKind.TopLevelMethod) + listener: beginFormalParameters((, MemberKind.TopLevelMethod) + parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod) + parseMetadataStar(() + listener: beginMetadataStar(x) + listener: endMetadataStar(0) + listener: beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null) + listener: handleNoType(() + ensureIdentifier((, formalParameterDeclaration) + listener: handleIdentifier(x, formalParameterDeclaration) + listener: handleFormalParameterWithoutValue()) + listener: endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod) + listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod) + parseAsyncModifierOpt()) + listener: handleAsyncModifier(null, null) + inPlainSync() + parseFunctionBody(), false, false) + listener: beginBlockFunctionBody({) + notEofOrValue(}, switch) + parseStatement({) + parseStatementX({) + parseSwitchStatement({) + listener: beginSwitchStatement(switch) + ensureParenthesizedCondition(switch, allowCase: false) + parseExpressionInParenthesisRest((, allowCase: false) + parseExpression(() + looksLikeOuterPatternEquals(() + skipOuterPattern(() + skipObjectPatternRest(x) + parsePrecedenceExpression((, 1, true, ConstantPatternContext.none) + parseUnaryExpression((, true, ConstantPatternContext.none) + parsePrimary((, expression, ConstantPatternContext.none) + parseSendOrFunctionLiteral((, expression, ConstantPatternContext.none) + parseSend((, expression, ConstantPatternContext.none) + isNextIdentifier(() + ensureIdentifier((, expression) + listener: handleIdentifier(x, expression) + listener: handleNoTypeArguments()) + parseArgumentsOpt(x) + listener: handleNoArguments()) + listener: handleSend(x, )) + ensureCloseParen(x, () + listener: handleParenthesizedCondition((, null, null) + parseSwitchBlock()) + ensureBlock(), null, switch statement) + listener: beginSwitchBlock({) + notEofOrValue(}, case) + peekPastLabels(case) + listener: beginCaseExpression(case) + parsePattern(case, PatternContext.matching, precedence: 1) + listener: beginPattern(case) + parsePrimaryPattern(case, PatternContext.matching) + parseParenthesizedPatternOrRecordPattern(case, PatternContext.matching) + parsePattern((, PatternContext.matching, precedence: 1) + listener: beginPattern(() + parsePrimaryPattern((, PatternContext.matching) + parseVariablePattern((, PatternContext.matching, typeInfo: Instance of 'NoType') + listener: handleNoType(_) + listener: handleWildcardPattern(null, _) + listener: endPattern(_) + listener: handlePatternField(null) + ensureCloseParen(,, () + listener: handleRecordPattern((, 1) + listener: beginAsOperatorType(as) + computeTypeAfterIsOrAs(as) + parseRecordType((, as, false) + listener: beginRecordType(() + parseRecordTypeField((, identifierIsOptional: true) + listener: beginRecordTypeEntry() + parseMetadataStar(() + listener: beginMetadataStar(Object) + listener: endMetadataStar(0) + listener: handleIdentifier(Object, typeReference) + listener: handleNoTypeArguments(,) + listener: handleType(Object, null) + listener: handleNoName(,) + listener: endRecordTypeEntry() + listener: endRecordType((, null, 1, false) + listener: endAsOperatorType(as) + listener: handleCastPattern(as) + listener: endPattern()) + listener: handleSwitchCaseNoWhenClause()) + ensureColon()) + listener: endCaseExpression(case, null, :) + peekPastLabels(}) + parseStatementsInSwitchCase(:, }, case, 0, 1, null, null) + listener: beginSwitchCase(0, 1, case) + listener: endSwitchCase(0, 1, null, null, 0, case, }) + notEofOrValue(}, }) + listener: endSwitchBlock(1, {, }) + listener: endSwitchStatement(switch, }) + notEofOrValue(}, }) + listener: endBlockFunctionBody(1, {, }) + listener: endTopLevelMethod(void, null, }) + listener: endTopLevelDeclaration() + reportAllErrorTokens(void) + listener: endCompilationUnit(1, ) diff --git a/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeAs.dart.parser.expect b/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeAs.dart.parser.expect new file mode 100644 index 000000000000..e2b5c4b247be --- /dev/null +++ b/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeAs.dart.parser.expect @@ -0,0 +1,13 @@ +void f(x) { +switch (x) { +case (_,) as (Object,): +} +} + + +void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken] +switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken] +case[KeywordToken] ([BeginToken]_[StringToken],[SimpleToken])[SimpleToken] as[KeywordToken] ([BeginToken]Object[StringToken],[SimpleToken])[SimpleToken]:[SimpleToken] +}[SimpleToken] +}[SimpleToken] +[SimpleToken] diff --git a/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeAs.dart.scanner.expect b/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeAs.dart.scanner.expect new file mode 100644 index 000000000000..e2b5c4b247be --- /dev/null +++ b/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeAs.dart.scanner.expect @@ -0,0 +1,13 @@ +void f(x) { +switch (x) { +case (_,) as (Object,): +} +} + + +void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken] +switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken] +case[KeywordToken] ([BeginToken]_[StringToken],[SimpleToken])[SimpleToken] as[KeywordToken] ([BeginToken]Object[StringToken],[SimpleToken])[SimpleToken]:[SimpleToken] +}[SimpleToken] +}[SimpleToken] +[SimpleToken] diff --git a/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeWhen.dart b/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeWhen.dart new file mode 100644 index 000000000000..d7ce2bf873b0 --- /dev/null +++ b/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeWhen.dart @@ -0,0 +1,5 @@ +void f(x) { + switch (x) { + case (_,) when true: + } +} diff --git a/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeWhen.dart.expect b/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeWhen.dart.expect new file mode 100644 index 000000000000..cfee3921f167 --- /dev/null +++ b/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeWhen.dart.expect @@ -0,0 +1,47 @@ +beginCompilationUnit(void) + beginMetadataStar(void) + endMetadataStar(0) + beginTopLevelMember(void) + beginTopLevelMethod(, null, null) + handleVoidKeyword(void) + handleIdentifier(f, topLevelFunctionDeclaration) + handleNoTypeVariables(() + beginFormalParameters((, MemberKind.TopLevelMethod) + beginMetadataStar(x) + endMetadataStar(0) + beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null) + handleNoType(() + handleIdentifier(x, formalParameterDeclaration) + handleFormalParameterWithoutValue()) + endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod) + endFormalParameters(1, (, ), MemberKind.TopLevelMethod) + handleAsyncModifier(null, null) + beginBlockFunctionBody({) + beginSwitchStatement(switch) + handleIdentifier(x, expression) + handleNoTypeArguments()) + handleNoArguments()) + handleSend(x, )) + handleParenthesizedCondition((, null, null) + beginSwitchBlock({) + beginCaseExpression(case) + beginPattern(case) + beginPattern(() + handleNoType(_) + handleWildcardPattern(null, _) + endPattern(_) + handlePatternField(null) + handleRecordPattern((, 1) + endPattern()) + beginSwitchCaseWhenClause(when) + handleLiteralBool(true) + endSwitchCaseWhenClause(true) + endCaseExpression(case, when, :) + beginSwitchCase(0, 1, case) + endSwitchCase(0, 1, null, null, 0, case, }) + endSwitchBlock(1, {, }) + endSwitchStatement(switch, }) + endBlockFunctionBody(1, {, }) + endTopLevelMethod(void, null, }) + endTopLevelDeclaration() +endCompilationUnit(1, ) diff --git a/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeWhen.dart.intertwined.expect b/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeWhen.dart.intertwined.expect new file mode 100644 index 000000000000..cb280c43feeb --- /dev/null +++ b/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeWhen.dart.intertwined.expect @@ -0,0 +1,108 @@ +parseUnit(void) + skipErrorTokens(void) + listener: beginCompilationUnit(void) + syntheticPreviousToken(void) + parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext') + parseMetadataStar() + listener: beginMetadataStar(void) + listener: endMetadataStar(0) + parseTopLevelMemberImpl() + listener: beginTopLevelMember(void) + parseTopLevelMethod(, null, null, , Instance of 'VoidType', null, f, false) + listener: beginTopLevelMethod(, null, null) + listener: handleVoidKeyword(void) + ensureIdentifierPotentiallyRecovered(void, topLevelFunctionDeclaration, false) + listener: handleIdentifier(f, topLevelFunctionDeclaration) + parseMethodTypeVar(f) + listener: handleNoTypeVariables(() + parseGetterOrFormalParameters(f, f, false, MemberKind.TopLevelMethod) + parseFormalParameters(f, MemberKind.TopLevelMethod) + parseFormalParametersRest((, MemberKind.TopLevelMethod) + listener: beginFormalParameters((, MemberKind.TopLevelMethod) + parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod) + parseMetadataStar(() + listener: beginMetadataStar(x) + listener: endMetadataStar(0) + listener: beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null) + listener: handleNoType(() + ensureIdentifier((, formalParameterDeclaration) + listener: handleIdentifier(x, formalParameterDeclaration) + listener: handleFormalParameterWithoutValue()) + listener: endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod) + listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod) + parseAsyncModifierOpt()) + listener: handleAsyncModifier(null, null) + inPlainSync() + parseFunctionBody(), false, false) + listener: beginBlockFunctionBody({) + notEofOrValue(}, switch) + parseStatement({) + parseStatementX({) + parseSwitchStatement({) + listener: beginSwitchStatement(switch) + ensureParenthesizedCondition(switch, allowCase: false) + parseExpressionInParenthesisRest((, allowCase: false) + parseExpression(() + looksLikeOuterPatternEquals(() + skipOuterPattern(() + skipObjectPatternRest(x) + parsePrecedenceExpression((, 1, true, ConstantPatternContext.none) + parseUnaryExpression((, true, ConstantPatternContext.none) + parsePrimary((, expression, ConstantPatternContext.none) + parseSendOrFunctionLiteral((, expression, ConstantPatternContext.none) + parseSend((, expression, ConstantPatternContext.none) + isNextIdentifier(() + ensureIdentifier((, expression) + listener: handleIdentifier(x, expression) + listener: handleNoTypeArguments()) + parseArgumentsOpt(x) + listener: handleNoArguments()) + listener: handleSend(x, )) + ensureCloseParen(x, () + listener: handleParenthesizedCondition((, null, null) + parseSwitchBlock()) + ensureBlock(), null, switch statement) + listener: beginSwitchBlock({) + notEofOrValue(}, case) + peekPastLabels(case) + listener: beginCaseExpression(case) + parsePattern(case, PatternContext.matching, precedence: 1) + listener: beginPattern(case) + parsePrimaryPattern(case, PatternContext.matching) + parseParenthesizedPatternOrRecordPattern(case, PatternContext.matching) + parsePattern((, PatternContext.matching, precedence: 1) + listener: beginPattern(() + parsePrimaryPattern((, PatternContext.matching) + parseVariablePattern((, PatternContext.matching, typeInfo: Instance of 'NoType') + listener: handleNoType(_) + listener: handleWildcardPattern(null, _) + listener: endPattern(_) + listener: handlePatternField(null) + ensureCloseParen(,, () + listener: handleRecordPattern((, 1) + listener: endPattern()) + listener: beginSwitchCaseWhenClause(when) + parseExpression(when) + looksLikeOuterPatternEquals(when) + skipOuterPattern(when) + parsePrecedenceExpression(when, 1, true, ConstantPatternContext.none) + parseUnaryExpression(when, true, ConstantPatternContext.none) + parsePrimary(when, expression, ConstantPatternContext.none) + parseLiteralBool(when) + listener: handleLiteralBool(true) + listener: endSwitchCaseWhenClause(true) + ensureColon(true) + listener: endCaseExpression(case, when, :) + peekPastLabels(}) + parseStatementsInSwitchCase(:, }, case, 0, 1, null, null) + listener: beginSwitchCase(0, 1, case) + listener: endSwitchCase(0, 1, null, null, 0, case, }) + notEofOrValue(}, }) + listener: endSwitchBlock(1, {, }) + listener: endSwitchStatement(switch, }) + notEofOrValue(}, }) + listener: endBlockFunctionBody(1, {, }) + listener: endTopLevelMethod(void, null, }) + listener: endTopLevelDeclaration() + reportAllErrorTokens(void) + listener: endCompilationUnit(1, ) diff --git a/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeWhen.dart.parser.expect b/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeWhen.dart.parser.expect new file mode 100644 index 000000000000..c545bfaec132 --- /dev/null +++ b/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeWhen.dart.parser.expect @@ -0,0 +1,13 @@ +void f(x) { +switch (x) { +case (_,) when true: +} +} + + +void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken] +switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken] +case[KeywordToken] ([BeginToken]_[StringToken],[SimpleToken])[SimpleToken] when[KeywordToken] true[KeywordToken]:[SimpleToken] +}[SimpleToken] +}[SimpleToken] +[SimpleToken] diff --git a/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeWhen.dart.scanner.expect b/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeWhen.dart.scanner.expect new file mode 100644 index 000000000000..c545bfaec132 --- /dev/null +++ b/pkg/front_end/parser_testcases/patterns/recordPattern_nonNullable_beforeWhen.dart.scanner.expect @@ -0,0 +1,13 @@ +void f(x) { +switch (x) { +case (_,) when true: +} +} + + +void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken] +switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken] +case[KeywordToken] ([BeginToken]_[StringToken],[SimpleToken])[SimpleToken] when[KeywordToken] true[KeywordToken]:[SimpleToken] +}[SimpleToken] +}[SimpleToken] +[SimpleToken] diff --git a/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeAs.dart b/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeAs.dart new file mode 100644 index 000000000000..073f67fa2c82 --- /dev/null +++ b/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeAs.dart @@ -0,0 +1,5 @@ +void f(x) { + switch (x) { + case (_,)? as (Object,): + } +} diff --git a/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeAs.dart.expect b/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeAs.dart.expect new file mode 100644 index 000000000000..9f7cad1d1c7d --- /dev/null +++ b/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeAs.dart.expect @@ -0,0 +1,66 @@ +Problems reported: + +parser/patterns/recordPattern_nullable_beforeAs:3:10: This pattern cannot appear inside a unary pattern (cast pattern, null check pattern, or null assert pattern) without parentheses. + case (_,)? as (Object,): + ^^^^^ + +beginCompilationUnit(void) + beginMetadataStar(void) + endMetadataStar(0) + beginTopLevelMember(void) + beginTopLevelMethod(, null, null) + handleVoidKeyword(void) + handleIdentifier(f, topLevelFunctionDeclaration) + handleNoTypeVariables(() + beginFormalParameters((, MemberKind.TopLevelMethod) + beginMetadataStar(x) + endMetadataStar(0) + beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null) + handleNoType(() + handleIdentifier(x, formalParameterDeclaration) + handleFormalParameterWithoutValue()) + endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod) + endFormalParameters(1, (, ), MemberKind.TopLevelMethod) + handleAsyncModifier(null, null) + beginBlockFunctionBody({) + beginSwitchStatement(switch) + handleIdentifier(x, expression) + handleNoTypeArguments()) + handleNoArguments()) + handleSend(x, )) + handleParenthesizedCondition((, null, null) + beginSwitchBlock({) + beginCaseExpression(case) + beginPattern(case) + beginPattern(() + handleNoType(_) + handleWildcardPattern(null, _) + endPattern(_) + handlePatternField(null) + handleRecordPattern((, 1) + handleNullCheckPattern(?) + handleRecoverableError(InvalidInsideUnaryPattern, (, ?) + beginAsOperatorType(as) + beginRecordType(() + beginRecordTypeEntry() + beginMetadataStar(Object) + endMetadataStar(0) + handleIdentifier(Object, typeReference) + handleNoTypeArguments(,) + handleType(Object, null) + handleNoName(,) + endRecordTypeEntry() + endRecordType((, null, 1, false) + endAsOperatorType(as) + handleCastPattern(as) + endPattern()) + handleSwitchCaseNoWhenClause()) + endCaseExpression(case, null, :) + beginSwitchCase(0, 1, case) + endSwitchCase(0, 1, null, null, 0, case, }) + endSwitchBlock(1, {, }) + endSwitchStatement(switch, }) + endBlockFunctionBody(1, {, }) + endTopLevelMethod(void, null, }) + endTopLevelDeclaration() +endCompilationUnit(1, ) diff --git a/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeAs.dart.intertwined.expect b/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeAs.dart.intertwined.expect new file mode 100644 index 000000000000..b520b8a5467a --- /dev/null +++ b/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeAs.dart.intertwined.expect @@ -0,0 +1,119 @@ +parseUnit(void) + skipErrorTokens(void) + listener: beginCompilationUnit(void) + syntheticPreviousToken(void) + parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext') + parseMetadataStar() + listener: beginMetadataStar(void) + listener: endMetadataStar(0) + parseTopLevelMemberImpl() + listener: beginTopLevelMember(void) + parseTopLevelMethod(, null, null, , Instance of 'VoidType', null, f, false) + listener: beginTopLevelMethod(, null, null) + listener: handleVoidKeyword(void) + ensureIdentifierPotentiallyRecovered(void, topLevelFunctionDeclaration, false) + listener: handleIdentifier(f, topLevelFunctionDeclaration) + parseMethodTypeVar(f) + listener: handleNoTypeVariables(() + parseGetterOrFormalParameters(f, f, false, MemberKind.TopLevelMethod) + parseFormalParameters(f, MemberKind.TopLevelMethod) + parseFormalParametersRest((, MemberKind.TopLevelMethod) + listener: beginFormalParameters((, MemberKind.TopLevelMethod) + parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod) + parseMetadataStar(() + listener: beginMetadataStar(x) + listener: endMetadataStar(0) + listener: beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null) + listener: handleNoType(() + ensureIdentifier((, formalParameterDeclaration) + listener: handleIdentifier(x, formalParameterDeclaration) + listener: handleFormalParameterWithoutValue()) + listener: endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod) + listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod) + parseAsyncModifierOpt()) + listener: handleAsyncModifier(null, null) + inPlainSync() + parseFunctionBody(), false, false) + listener: beginBlockFunctionBody({) + notEofOrValue(}, switch) + parseStatement({) + parseStatementX({) + parseSwitchStatement({) + listener: beginSwitchStatement(switch) + ensureParenthesizedCondition(switch, allowCase: false) + parseExpressionInParenthesisRest((, allowCase: false) + parseExpression(() + looksLikeOuterPatternEquals(() + skipOuterPattern(() + skipObjectPatternRest(x) + parsePrecedenceExpression((, 1, true, ConstantPatternContext.none) + parseUnaryExpression((, true, ConstantPatternContext.none) + parsePrimary((, expression, ConstantPatternContext.none) + parseSendOrFunctionLiteral((, expression, ConstantPatternContext.none) + parseSend((, expression, ConstantPatternContext.none) + isNextIdentifier(() + ensureIdentifier((, expression) + listener: handleIdentifier(x, expression) + listener: handleNoTypeArguments()) + parseArgumentsOpt(x) + listener: handleNoArguments()) + listener: handleSend(x, )) + ensureCloseParen(x, () + listener: handleParenthesizedCondition((, null, null) + parseSwitchBlock()) + ensureBlock(), null, switch statement) + listener: beginSwitchBlock({) + notEofOrValue(}, case) + peekPastLabels(case) + listener: beginCaseExpression(case) + parsePattern(case, PatternContext.matching, precedence: 1) + listener: beginPattern(case) + parsePrimaryPattern(case, PatternContext.matching) + parseParenthesizedPatternOrRecordPattern(case, PatternContext.matching) + parsePattern((, PatternContext.matching, precedence: 1) + listener: beginPattern(() + parsePrimaryPattern((, PatternContext.matching) + parseVariablePattern((, PatternContext.matching, typeInfo: Instance of 'NoType') + listener: handleNoType(_) + listener: handleWildcardPattern(null, _) + listener: endPattern(_) + listener: handlePatternField(null) + ensureCloseParen(,, () + listener: handleRecordPattern((, 1) + listener: handleNullCheckPattern(?) + reportRecoverableErrorWithEnd((, ?, InvalidInsideUnaryPattern) + listener: handleRecoverableError(InvalidInsideUnaryPattern, (, ?) + listener: beginAsOperatorType(as) + computeTypeAfterIsOrAs(as) + parseRecordType((, as, false) + listener: beginRecordType(() + parseRecordTypeField((, identifierIsOptional: true) + listener: beginRecordTypeEntry() + parseMetadataStar(() + listener: beginMetadataStar(Object) + listener: endMetadataStar(0) + listener: handleIdentifier(Object, typeReference) + listener: handleNoTypeArguments(,) + listener: handleType(Object, null) + listener: handleNoName(,) + listener: endRecordTypeEntry() + listener: endRecordType((, null, 1, false) + listener: endAsOperatorType(as) + listener: handleCastPattern(as) + listener: endPattern()) + listener: handleSwitchCaseNoWhenClause()) + ensureColon()) + listener: endCaseExpression(case, null, :) + peekPastLabels(}) + parseStatementsInSwitchCase(:, }, case, 0, 1, null, null) + listener: beginSwitchCase(0, 1, case) + listener: endSwitchCase(0, 1, null, null, 0, case, }) + notEofOrValue(}, }) + listener: endSwitchBlock(1, {, }) + listener: endSwitchStatement(switch, }) + notEofOrValue(}, }) + listener: endBlockFunctionBody(1, {, }) + listener: endTopLevelMethod(void, null, }) + listener: endTopLevelDeclaration() + reportAllErrorTokens(void) + listener: endCompilationUnit(1, ) diff --git a/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeAs.dart.parser.expect b/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeAs.dart.parser.expect new file mode 100644 index 000000000000..9dcc471d8485 --- /dev/null +++ b/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeAs.dart.parser.expect @@ -0,0 +1,13 @@ +void f(x) { +switch (x) { +case (_,)? as (Object,): +} +} + + +void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken] +switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken] +case[KeywordToken] ([BeginToken]_[StringToken],[SimpleToken])[SimpleToken]?[SimpleToken] as[KeywordToken] ([BeginToken]Object[StringToken],[SimpleToken])[SimpleToken]:[SimpleToken] +}[SimpleToken] +}[SimpleToken] +[SimpleToken] diff --git a/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeAs.dart.scanner.expect b/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeAs.dart.scanner.expect new file mode 100644 index 000000000000..9dcc471d8485 --- /dev/null +++ b/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeAs.dart.scanner.expect @@ -0,0 +1,13 @@ +void f(x) { +switch (x) { +case (_,)? as (Object,): +} +} + + +void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken] +switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken] +case[KeywordToken] ([BeginToken]_[StringToken],[SimpleToken])[SimpleToken]?[SimpleToken] as[KeywordToken] ([BeginToken]Object[StringToken],[SimpleToken])[SimpleToken]:[SimpleToken] +}[SimpleToken] +}[SimpleToken] +[SimpleToken] diff --git a/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeWhen.dart b/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeWhen.dart new file mode 100644 index 000000000000..baf820ad1947 --- /dev/null +++ b/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeWhen.dart @@ -0,0 +1,5 @@ +void f(x) { + switch (x) { + case (_,)? when true: + } +} diff --git a/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeWhen.dart.expect b/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeWhen.dart.expect new file mode 100644 index 000000000000..a662527f7571 --- /dev/null +++ b/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeWhen.dart.expect @@ -0,0 +1,48 @@ +beginCompilationUnit(void) + beginMetadataStar(void) + endMetadataStar(0) + beginTopLevelMember(void) + beginTopLevelMethod(, null, null) + handleVoidKeyword(void) + handleIdentifier(f, topLevelFunctionDeclaration) + handleNoTypeVariables(() + beginFormalParameters((, MemberKind.TopLevelMethod) + beginMetadataStar(x) + endMetadataStar(0) + beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null) + handleNoType(() + handleIdentifier(x, formalParameterDeclaration) + handleFormalParameterWithoutValue()) + endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod) + endFormalParameters(1, (, ), MemberKind.TopLevelMethod) + handleAsyncModifier(null, null) + beginBlockFunctionBody({) + beginSwitchStatement(switch) + handleIdentifier(x, expression) + handleNoTypeArguments()) + handleNoArguments()) + handleSend(x, )) + handleParenthesizedCondition((, null, null) + beginSwitchBlock({) + beginCaseExpression(case) + beginPattern(case) + beginPattern(() + handleNoType(_) + handleWildcardPattern(null, _) + endPattern(_) + handlePatternField(null) + handleRecordPattern((, 1) + handleNullCheckPattern(?) + endPattern(?) + beginSwitchCaseWhenClause(when) + handleLiteralBool(true) + endSwitchCaseWhenClause(true) + endCaseExpression(case, when, :) + beginSwitchCase(0, 1, case) + endSwitchCase(0, 1, null, null, 0, case, }) + endSwitchBlock(1, {, }) + endSwitchStatement(switch, }) + endBlockFunctionBody(1, {, }) + endTopLevelMethod(void, null, }) + endTopLevelDeclaration() +endCompilationUnit(1, ) diff --git a/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeWhen.dart.intertwined.expect b/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeWhen.dart.intertwined.expect new file mode 100644 index 000000000000..82f428716bf3 --- /dev/null +++ b/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeWhen.dart.intertwined.expect @@ -0,0 +1,109 @@ +parseUnit(void) + skipErrorTokens(void) + listener: beginCompilationUnit(void) + syntheticPreviousToken(void) + parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext') + parseMetadataStar() + listener: beginMetadataStar(void) + listener: endMetadataStar(0) + parseTopLevelMemberImpl() + listener: beginTopLevelMember(void) + parseTopLevelMethod(, null, null, , Instance of 'VoidType', null, f, false) + listener: beginTopLevelMethod(, null, null) + listener: handleVoidKeyword(void) + ensureIdentifierPotentiallyRecovered(void, topLevelFunctionDeclaration, false) + listener: handleIdentifier(f, topLevelFunctionDeclaration) + parseMethodTypeVar(f) + listener: handleNoTypeVariables(() + parseGetterOrFormalParameters(f, f, false, MemberKind.TopLevelMethod) + parseFormalParameters(f, MemberKind.TopLevelMethod) + parseFormalParametersRest((, MemberKind.TopLevelMethod) + listener: beginFormalParameters((, MemberKind.TopLevelMethod) + parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod) + parseMetadataStar(() + listener: beginMetadataStar(x) + listener: endMetadataStar(0) + listener: beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null) + listener: handleNoType(() + ensureIdentifier((, formalParameterDeclaration) + listener: handleIdentifier(x, formalParameterDeclaration) + listener: handleFormalParameterWithoutValue()) + listener: endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod) + listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod) + parseAsyncModifierOpt()) + listener: handleAsyncModifier(null, null) + inPlainSync() + parseFunctionBody(), false, false) + listener: beginBlockFunctionBody({) + notEofOrValue(}, switch) + parseStatement({) + parseStatementX({) + parseSwitchStatement({) + listener: beginSwitchStatement(switch) + ensureParenthesizedCondition(switch, allowCase: false) + parseExpressionInParenthesisRest((, allowCase: false) + parseExpression(() + looksLikeOuterPatternEquals(() + skipOuterPattern(() + skipObjectPatternRest(x) + parsePrecedenceExpression((, 1, true, ConstantPatternContext.none) + parseUnaryExpression((, true, ConstantPatternContext.none) + parsePrimary((, expression, ConstantPatternContext.none) + parseSendOrFunctionLiteral((, expression, ConstantPatternContext.none) + parseSend((, expression, ConstantPatternContext.none) + isNextIdentifier(() + ensureIdentifier((, expression) + listener: handleIdentifier(x, expression) + listener: handleNoTypeArguments()) + parseArgumentsOpt(x) + listener: handleNoArguments()) + listener: handleSend(x, )) + ensureCloseParen(x, () + listener: handleParenthesizedCondition((, null, null) + parseSwitchBlock()) + ensureBlock(), null, switch statement) + listener: beginSwitchBlock({) + notEofOrValue(}, case) + peekPastLabels(case) + listener: beginCaseExpression(case) + parsePattern(case, PatternContext.matching, precedence: 1) + listener: beginPattern(case) + parsePrimaryPattern(case, PatternContext.matching) + parseParenthesizedPatternOrRecordPattern(case, PatternContext.matching) + parsePattern((, PatternContext.matching, precedence: 1) + listener: beginPattern(() + parsePrimaryPattern((, PatternContext.matching) + parseVariablePattern((, PatternContext.matching, typeInfo: Instance of 'NoType') + listener: handleNoType(_) + listener: handleWildcardPattern(null, _) + listener: endPattern(_) + listener: handlePatternField(null) + ensureCloseParen(,, () + listener: handleRecordPattern((, 1) + listener: handleNullCheckPattern(?) + listener: endPattern(?) + listener: beginSwitchCaseWhenClause(when) + parseExpression(when) + looksLikeOuterPatternEquals(when) + skipOuterPattern(when) + parsePrecedenceExpression(when, 1, true, ConstantPatternContext.none) + parseUnaryExpression(when, true, ConstantPatternContext.none) + parsePrimary(when, expression, ConstantPatternContext.none) + parseLiteralBool(when) + listener: handleLiteralBool(true) + listener: endSwitchCaseWhenClause(true) + ensureColon(true) + listener: endCaseExpression(case, when, :) + peekPastLabels(}) + parseStatementsInSwitchCase(:, }, case, 0, 1, null, null) + listener: beginSwitchCase(0, 1, case) + listener: endSwitchCase(0, 1, null, null, 0, case, }) + notEofOrValue(}, }) + listener: endSwitchBlock(1, {, }) + listener: endSwitchStatement(switch, }) + notEofOrValue(}, }) + listener: endBlockFunctionBody(1, {, }) + listener: endTopLevelMethod(void, null, }) + listener: endTopLevelDeclaration() + reportAllErrorTokens(void) + listener: endCompilationUnit(1, ) diff --git a/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeWhen.dart.parser.expect b/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeWhen.dart.parser.expect new file mode 100644 index 000000000000..9667bbf7696e --- /dev/null +++ b/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeWhen.dart.parser.expect @@ -0,0 +1,13 @@ +void f(x) { +switch (x) { +case (_,)? when true: +} +} + + +void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken] +switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken] +case[KeywordToken] ([BeginToken]_[StringToken],[SimpleToken])[SimpleToken]?[SimpleToken] when[KeywordToken] true[KeywordToken]:[SimpleToken] +}[SimpleToken] +}[SimpleToken] +[SimpleToken] diff --git a/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeWhen.dart.scanner.expect b/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeWhen.dart.scanner.expect new file mode 100644 index 000000000000..9667bbf7696e --- /dev/null +++ b/pkg/front_end/parser_testcases/patterns/recordPattern_nullable_beforeWhen.dart.scanner.expect @@ -0,0 +1,13 @@ +void f(x) { +switch (x) { +case (_,)? when true: +} +} + + +void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken] +switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken] +case[KeywordToken] ([BeginToken]_[StringToken],[SimpleToken])[SimpleToken]?[SimpleToken] when[KeywordToken] true[KeywordToken]:[SimpleToken] +}[SimpleToken] +}[SimpleToken] +[SimpleToken]