Skip to content

Commit

Permalink
[parser] Support nullable record types in patterns
Browse files Browse the repository at this point in the history
Not fixed for nullable record types in
https://dart-review.googlesource.com/c/sdk/+/280106.

Fixes: https://dartbug.com/52439
Closes: https://dartbug.com/52462

Change-Id: I52f42406f2e1c6b7c874a9828ef7f1de397b3c83
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/304642
Reviewed-by: Paul Berry <[email protected]>
Reviewed-by: Johnni Winther <[email protected]>
Commit-Queue: Jens Johansen <[email protected]>
  • Loading branch information
jensjoha authored and Commit Queue committed May 25, 2023
1 parent f86f412 commit 284296f
Show file tree
Hide file tree
Showing 17 changed files with 1,989 additions and 7 deletions.
9 changes: 6 additions & 3 deletions pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7948,7 +7948,6 @@ class Parser {
typeInfo.isNullable &&
typeInfo.couldBeExpression) {
assert(optional('?', token));
assert(next.isKeywordOrIdentifier);
if (!looksLikeName(next)) {
reportRecoverableError(
next, codes.templateExpectedIdentifier.withArguments(next));
Expand Down Expand Up @@ -9808,8 +9807,12 @@ class Parser {
return parseVariablePattern(token, patternContext);
case '(':
// "(" could start a record type (which has to be followed by an
// identifier though), e.g. `(int, int) foo`.
if (next.endGroup!.next!.isIdentifier) {
// identifier (or ? identifier) though), e.g. `(int, int) foo`
// or `(int, int)? bar`.
Token afterEndGroup = next.endGroup!.next!;
if (afterEndGroup.isIdentifier ||
(optional("?", afterEndGroup) &&
afterEndGroup.next!.isIdentifier)) {
TypeInfo typeInfo = computeVariablePatternType(token);
if (typeInfo is ComplexTypeInfo &&
typeInfo.isRecordType &&
Expand Down
9 changes: 9 additions & 0 deletions pkg/front_end/parser_testcases/patterns/issue_51169.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,12 @@ test(a) {
print(b);
}
}

testNullable(a) {
switch (a) {
case (foo: (int, int)? b) when b != (2, 3):
print(b);
case Class(field: (int, int)? b) when b != (2, 3):
print(b);
}
}
138 changes: 137 additions & 1 deletion pkg/front_end/parser_testcases/patterns/issue_51169.dart.expect
Original file line number Diff line number Diff line change
Expand Up @@ -251,5 +251,141 @@ beginCompilationUnit(class)
endSwitchStatement(switch, })
endBlockFunctionBody(1, {, })
endTopLevelMethod(test, null, })
endTopLevelDeclaration(testNullable)
beginMetadataStar(testNullable)
endMetadataStar(0)
beginTopLevelMember(testNullable)
beginTopLevelMethod(}, null, null)
handleNoType(})
handleIdentifier(testNullable, topLevelFunctionDeclaration)
handleNoTypeVariables(()
beginFormalParameters((, MemberKind.TopLevelMethod)
beginMetadataStar(a)
endMetadataStar(0)
beginFormalParameter(a, MemberKind.TopLevelMethod, null, null, null)
handleNoType(()
handleIdentifier(a, formalParameterDeclaration)
handleFormalParameterWithoutValue())
endFormalParameter(null, null, null, a, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
handleAsyncModifier(null, null)
beginBlockFunctionBody({)
beginSwitchStatement(switch)
handleIdentifier(a, expression)
handleNoTypeArguments())
handleNoArguments())
handleSend(a, ))
handleParenthesizedCondition((, null, null)
beginSwitchBlock({)
beginCaseExpression(case)
beginPattern(case)
handleIdentifier(foo, namedRecordFieldReference)
beginPattern(:)
beginRecordType(()
beginRecordTypeEntry()
beginMetadataStar(int)
endMetadataStar(0)
handleIdentifier(int, typeReference)
handleNoTypeArguments(,)
handleType(int, null)
handleNoName(,)
endRecordTypeEntry()
beginRecordTypeEntry()
beginMetadataStar(int)
endMetadataStar(0)
handleIdentifier(int, typeReference)
handleNoTypeArguments())
handleType(int, null)
handleNoName())
endRecordTypeEntry()
endRecordType((, ?, 2, false)
handleDeclaredVariablePattern(null, b, false)
endPattern(b)
handlePatternField(:)
handleRecordPattern((, 1)
endPattern())
beginSwitchCaseWhenClause(when)
handleIdentifier(b, expression)
handleNoTypeArguments(!=)
handleNoArguments(!=)
handleSend(b, !=)
beginBinaryExpression(!=)
beginParenthesizedExpressionOrRecordLiteral(()
handleLiteralInt(2)
handleLiteralInt(3)
endRecordLiteral((, 2, null)
endBinaryExpression(!=)
endSwitchCaseWhenClause())
endCaseExpression(case, when, :)
beginSwitchCase(0, 1, case)
handleIdentifier(print, expression)
handleNoTypeArguments(()
beginArguments(()
handleIdentifier(b, expression)
handleNoTypeArguments())
handleNoArguments())
handleSend(b, ))
endArguments(1, (, ))
handleSend(print, ;)
handleExpressionStatement(;)
endSwitchCase(0, 1, null, null, 1, case, case)
beginCaseExpression(case)
beginPattern(case)
handleNoTypeArguments(()
handleIdentifier(field, namedArgumentReference)
beginPattern(:)
beginRecordType(()
beginRecordTypeEntry()
beginMetadataStar(int)
endMetadataStar(0)
handleIdentifier(int, typeReference)
handleNoTypeArguments(,)
handleType(int, null)
handleNoName(,)
endRecordTypeEntry()
beginRecordTypeEntry()
beginMetadataStar(int)
endMetadataStar(0)
handleIdentifier(int, typeReference)
handleNoTypeArguments())
handleType(int, null)
handleNoName())
endRecordTypeEntry()
endRecordType((, ?, 2, false)
handleDeclaredVariablePattern(null, b, false)
endPattern(b)
handlePatternField(:)
handleObjectPatternFields(1, (, ))
handleObjectPattern(Class, null, null)
endPattern())
beginSwitchCaseWhenClause(when)
handleIdentifier(b, expression)
handleNoTypeArguments(!=)
handleNoArguments(!=)
handleSend(b, !=)
beginBinaryExpression(!=)
beginParenthesizedExpressionOrRecordLiteral(()
handleLiteralInt(2)
handleLiteralInt(3)
endRecordLiteral((, 2, null)
endBinaryExpression(!=)
endSwitchCaseWhenClause())
endCaseExpression(case, when, :)
beginSwitchCase(0, 1, case)
handleIdentifier(print, expression)
handleNoTypeArguments(()
beginArguments(()
handleIdentifier(b, expression)
handleNoTypeArguments())
handleNoArguments())
handleSend(b, ))
endArguments(1, (, ))
handleSend(print, ;)
handleExpressionStatement(;)
endSwitchCase(0, 1, null, null, 1, case, })
endSwitchBlock(2, {, })
endSwitchStatement(switch, })
endBlockFunctionBody(1, {, })
endTopLevelMethod(testNullable, null, })
endTopLevelDeclaration()
endCompilationUnit(2, )
endCompilationUnit(3, )
Loading

0 comments on commit 284296f

Please sign in to comment.