Skip to content

Commit 79fd3dd

Browse files
jensjohaCommit Queue
authored and
Commit Queue
committed
[parser] 'on' after 'try' is always an on-clause
https://github.com/dart-lang/language/blob/master/accepted/future-releases/records/records-feature-specification.md#ambiguity-with-on-clauses Fixes #49980 Change-Id: I0dadbdd5bf7ac1fef69191e38eaaa705cda60f2e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/275922 Commit-Queue: Jens Johansen <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]> Reviewed-by: Johnni Winther <[email protected]>
1 parent e34600d commit 79fd3dd

File tree

45 files changed

+1047
-315
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1047
-315
lines changed

pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8220,16 +8220,11 @@ class Parser {
82208220
Token? onKeyword = null;
82218221
if (identical(value, 'on')) {
82228222
// 'on' type catchPart?
8223+
// Note https://github.com/dart-lang/language/blob/master/accepted/future-releases/records/records-feature-specification.md#ambiguity-with-on-clauses
8224+
// "Whenever on appears after a try block or after a preceding on clause
8225+
// on a try block, we unconditionally parse it as an on clause".
82238226
onKeyword = token;
82248227
TypeInfo typeInfo = computeType(token, /* required = */ true);
8225-
if (catchCount > 0 && (typeInfo == noType || typeInfo.recovered)) {
8226-
// Not a valid on-clause and we have enough catch counts to be a valid
8227-
// try block already.
8228-
// This could for instance be code like `on([...])` or `on = 42` after
8229-
// some actual catch/on as that could be a valid method call, local
8230-
// function, assignment etc.
8231-
break;
8232-
}
82338228
listener.beginCatchClause(token);
82348229
didBeginCatchClause = true;
82358230
lastConsumed = typeInfo.ensureTypeNotVoid(token, this);

pkg/front_end/parser_testcases/general/call_on_after_try_block.dart

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@ void main() {
77
;
88
}
99

10-
// With records "on()" is no longer a call after a try block, but a on clause
11-
// where the type is the empty record.
10+
// With records everything called on after a try is an on clause.
1211
// See https://github.com/dart-lang/language/blob/master/accepted/future-releases/records/records-feature-specification.md#ambiguity-with-on-clauses
13-
// This is a call though as (x) isn't a valid record type.
1412
on(42);
1513
}
1614

pkg/front_end/parser_testcases/general/call_on_after_try_block.dart.expect

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
Problems reported:
2+
3+
parser/general/call_on_after_try_block:12:6: Expected a type, but got '42'.
4+
on(42);
5+
^^
6+
7+
parser/general/call_on_after_try_block:12:6: Expected ')' before this.
8+
on(42);
9+
^^
10+
11+
parser/general/call_on_after_try_block:12:8: Record type with one entry requires a trailing comma.
12+
on(42);
13+
^
14+
15+
parser/general/call_on_after_try_block:12:8: A catch clause must have a body, even if it is empty.
16+
on(42);
17+
^
18+
119
beginCompilationUnit(void)
220
beginMetadataStar(void)
321
endMetadataStar(0)
@@ -38,14 +56,27 @@ beginCompilationUnit(void)
3856
handleEmptyStatement(;)
3957
endBlock(1, {, }, BlockKind(catch clause))
4058
handleCatchBlock(on, null, null)
41-
endTryStatement(2, try, null)
42-
handleIdentifier(on, expression)
43-
handleNoTypeArguments(()
44-
beginArguments(()
45-
handleLiteralInt(42)
46-
endArguments(1, (, ))
47-
handleSend(on, ;)
48-
handleExpressionStatement(;)
59+
beginCatchClause(on)
60+
beginRecordType(()
61+
beginRecordTypeEntry()
62+
beginMetadataStar(42)
63+
endMetadataStar(0)
64+
handleRecoverableError(Message[ExpectedType, Expected a type, but got '42'., null, {lexeme: 42}], 42, 42)
65+
handleIdentifier(, typeReference)
66+
handleNoTypeArguments(42)
67+
handleType(, null)
68+
handleNoName(42)
69+
endRecordTypeEntry()
70+
handleRecoverableError(Message[ExpectedButGot, Expected ')' before this., null, {string: )}], 42, 42)
71+
handleRecoverableError(RecordTypeOnePositionalFieldNoTrailingComma, ), ))
72+
endRecordType((, null, 1, false)
73+
endCatchClause(;)
74+
handleRecoverableError(Message[ExpectedClassOrMixinBody, A catch clause must have a body, even if it is empty., Try adding an empty body., {string: catch clause}], ), ))
75+
beginBlock({, BlockKind(catch clause))
76+
endBlock(0, {, }, BlockKind(catch clause))
77+
handleCatchBlock(on, null, null)
78+
endTryStatement(3, try, null)
79+
handleEmptyStatement(;)
4980
endBlockFunctionBody(2, {, })
5081
endTopLevelMethod(void, null, })
5182
endTopLevelDeclaration(void)

pkg/front_end/parser_testcases/general/call_on_after_try_block.dart.intertwined.expect

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -83,41 +83,46 @@ parseUnit(void)
8383
notEofOrValue(}, })
8484
listener: endBlock(1, {, }, BlockKind(catch clause))
8585
listener: handleCatchBlock(on, null, null)
86-
listener: endTryStatement(2, try, null)
87-
notEofOrValue(}, on)
86+
listener: beginCatchClause(on)
87+
parseRecordType((, on, false)
88+
listener: beginRecordType(()
89+
parseRecordTypeField((, identifierIsOptional: true)
90+
listener: beginRecordTypeEntry()
91+
parseMetadataStar(()
92+
listener: beginMetadataStar(42)
93+
listener: endMetadataStar(0)
94+
reportRecoverableErrorWithToken(42, Instance of 'Template<(Token) => Message>')
95+
listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got '42'., null, {lexeme: 42}], 42, 42)
96+
rewriter()
97+
listener: handleIdentifier(, typeReference)
98+
listener: handleNoTypeArguments(42)
99+
listener: handleType(, null)
100+
listener: handleNoName(42)
101+
listener: endRecordTypeEntry()
102+
ensureCloseParen(, ()
103+
reportRecoverableError(42, Message[ExpectedButGot, Expected ')' before this., null, {string: )}])
104+
listener: handleRecoverableError(Message[ExpectedButGot, Expected ')' before this., null, {string: )}], 42, 42)
105+
reportRecoverableError(), RecordTypeOnePositionalFieldNoTrailingComma)
106+
listener: handleRecoverableError(RecordTypeOnePositionalFieldNoTrailingComma, ), ))
107+
listener: endRecordType((, null, 1, false)
108+
listener: endCatchClause(;)
109+
parseBlock(), BlockKind(catch clause))
110+
ensureBlock(), null, catch clause)
111+
reportRecoverableError(), Message[ExpectedClassOrMixinBody, A catch clause must have a body, even if it is empty., Try adding an empty body., {string: catch clause}])
112+
listener: handleRecoverableError(Message[ExpectedClassOrMixinBody, A catch clause must have a body, even if it is empty., Try adding an empty body., {string: catch clause}], ), ))
113+
insertBlock())
114+
rewriter()
115+
rewriter()
116+
listener: beginBlock({, BlockKind(catch clause))
117+
notEofOrValue(}, })
118+
listener: endBlock(0, {, }, BlockKind(catch clause))
119+
listener: handleCatchBlock(on, null, null)
120+
listener: endTryStatement(3, try, null)
121+
notEofOrValue(}, ;)
88122
parseStatement(})
89123
parseStatementX(})
90-
parseExpressionStatementOrDeclaration(}, null)
91-
parseExpressionStatementOrDeclarationAfterModifiers(}, }, null, null, null, null)
92-
looksLikeLocalFunction(on)
93-
parseExpressionStatement(})
94-
parseExpression(})
95-
parsePrecedenceExpression(}, 1, true)
96-
parseUnaryExpression(}, true)
97-
parsePrimary(}, expression)
98-
inPlainSync()
99-
parseSendOrFunctionLiteral(}, expression)
100-
looksLikeFunctionBody(;)
101-
parseSend(}, expression)
102-
isNextIdentifier(})
103-
ensureIdentifier(}, expression)
104-
inPlainSync()
105-
listener: handleIdentifier(on, expression)
106-
listener: handleNoTypeArguments(()
107-
parseArgumentsOpt(on)
108-
parseArguments(on)
109-
parseArgumentsRest(()
110-
listener: beginArguments(()
111-
parseExpression(()
112-
parsePrecedenceExpression((, 1, true)
113-
parseUnaryExpression((, true)
114-
parsePrimary((, expression)
115-
parseLiteralInt(()
116-
listener: handleLiteralInt(42)
117-
listener: endArguments(1, (, ))
118-
listener: handleSend(on, ;)
119-
ensureSemicolon())
120-
listener: handleExpressionStatement(;)
124+
parseEmptyStatement(})
125+
listener: handleEmptyStatement(;)
121126
notEofOrValue(}, })
122127
listener: endBlockFunctionBody(2, {, })
123128
listener: endTopLevelMethod(void, null, })

pkg/front_end/parser_testcases/general/call_on_after_try_block.dart.parser.expect

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
NOTICE: Stream was rewritten by parser!
2+
13
void main() {
24
try {
35
;
@@ -9,9 +11,7 @@ try {
911

1012

1113

12-
13-
14-
on(42);
14+
on(*synthetic*42){};
1515
}
1616

1717
void on(e) {}
@@ -28,9 +28,7 @@ try[KeywordToken] {[BeginToken]
2828

2929

3030

31-
32-
33-
on[KeywordToken]([BeginToken]42[StringToken])[SimpleToken];[SimpleToken]
31+
on[KeywordToken]([BeginToken][SyntheticStringToken]42[StringToken])[SimpleToken]{[SyntheticBeginToken]}[SyntheticToken];[SimpleToken]
3432
}[SimpleToken]
3533

3634
void[KeywordToken] on[KeywordToken]([BeginToken]e[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken]

pkg/front_end/parser_testcases/general/call_on_after_try_block.dart.scanner.expect

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ try {
99

1010

1111

12-
13-
1412
on(42);
1513
}
1614

@@ -28,8 +26,6 @@ try[KeywordToken] {[BeginToken]
2826

2927

3028

31-
32-
3329
on[KeywordToken]([BeginToken]42[StringToken])[SimpleToken];[SimpleToken]
3430
}[SimpleToken]
3531

pkg/front_end/parser_testcases/general/call_on_after_try_block.equivalence_info

Lines changed: 0 additions & 5 deletions
This file was deleted.

pkg/front_end/parser_testcases/general/call_on_after_try_block2.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ void main() {
77
;
88
}
99

10+
// With records everything called on after a try is an on clause.
11+
// See https://github.com/dart-lang/language/blob/master/accepted/future-releases/records/records-feature-specification.md#ambiguity-with-on-clauses
1012
on(e) {
1113
;
1214
}

pkg/front_end/parser_testcases/general/call_on_after_try_block2.dart.expect

Lines changed: 60 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,25 @@
1+
Problems reported:
2+
3+
parser/general/call_on_after_try_block2:12:7: Record type with one entry requires a trailing comma.
4+
on(e) {
5+
^
6+
7+
parser/general/call_on_after_try_block2:15:6: Expected a type, but got '""'.
8+
on("");
9+
^^
10+
11+
parser/general/call_on_after_try_block2:15:6: Expected ')' before this.
12+
on("");
13+
^^
14+
15+
parser/general/call_on_after_try_block2:15:8: Record type with one entry requires a trailing comma.
16+
on("");
17+
^
18+
19+
parser/general/call_on_after_try_block2:15:8: A catch clause must have a body, even if it is empty.
20+
on("");
21+
^
22+
123
beginCompilationUnit(void)
224
beginMetadataStar(void)
325
endMetadataStar(0)
@@ -38,39 +60,45 @@ beginCompilationUnit(void)
3860
handleEmptyStatement(;)
3961
endBlock(1, {, }, BlockKind(catch clause))
4062
handleCatchBlock(on, null, null)
41-
endTryStatement(2, try, null)
42-
beginMetadataStar(on)
43-
endMetadataStar(0)
44-
handleNoTypeVariables(()
45-
beginLocalFunctionDeclaration(on)
46-
handleNoType(})
47-
beginFunctionName(on)
48-
handleIdentifier(on, localFunctionDeclaration)
49-
endFunctionName(on, ()
50-
beginFormalParameters((, MemberKind.Local)
51-
beginMetadataStar(e)
52-
endMetadataStar(0)
53-
beginFormalParameter(e, MemberKind.Local, null, null, null)
54-
handleNoType(()
55-
handleIdentifier(e, formalParameterDeclaration)
56-
handleFormalParameterWithoutValue())
57-
endFormalParameter(null, null, null, e, null, null, FormalParameterKind.requiredPositional, MemberKind.Local)
58-
endFormalParameters(1, (, ), MemberKind.Local)
59-
handleNoInitializers()
60-
handleAsyncModifier(null, null)
61-
beginBlockFunctionBody({)
63+
beginCatchClause(on)
64+
beginRecordType(()
65+
beginRecordTypeEntry()
66+
beginMetadataStar(e)
67+
endMetadataStar(0)
68+
handleIdentifier(e, typeReference)
69+
handleNoTypeArguments())
70+
handleType(e, null)
71+
handleNoName())
72+
endRecordTypeEntry()
73+
handleRecoverableError(RecordTypeOnePositionalFieldNoTrailingComma, ), ))
74+
endRecordType((, null, 1, false)
75+
endCatchClause({)
76+
beginBlock({, BlockKind(catch clause))
6277
handleEmptyStatement(;)
63-
endBlockFunctionBody(1, {, })
64-
endLocalFunctionDeclaration(})
65-
handleIdentifier(on, expression)
66-
handleNoTypeArguments(()
67-
beginArguments(()
68-
beginLiteralString("")
69-
endLiteralString(0, ))
70-
endArguments(1, (, ))
71-
handleSend(on, ;)
72-
handleExpressionStatement(;)
73-
endBlockFunctionBody(3, {, })
78+
endBlock(1, {, }, BlockKind(catch clause))
79+
handleCatchBlock(on, null, null)
80+
beginCatchClause(on)
81+
beginRecordType(()
82+
beginRecordTypeEntry()
83+
beginMetadataStar("")
84+
endMetadataStar(0)
85+
handleRecoverableError(Message[ExpectedType, Expected a type, but got '""'., null, {lexeme: ""}], "", "")
86+
handleIdentifier(, typeReference)
87+
handleNoTypeArguments("")
88+
handleType(, null)
89+
handleNoName("")
90+
endRecordTypeEntry()
91+
handleRecoverableError(Message[ExpectedButGot, Expected ')' before this., null, {string: )}], "", "")
92+
handleRecoverableError(RecordTypeOnePositionalFieldNoTrailingComma, ), ))
93+
endRecordType((, null, 1, false)
94+
endCatchClause(;)
95+
handleRecoverableError(Message[ExpectedClassOrMixinBody, A catch clause must have a body, even if it is empty., Try adding an empty body., {string: catch clause}], ), ))
96+
beginBlock({, BlockKind(catch clause))
97+
endBlock(0, {, }, BlockKind(catch clause))
98+
handleCatchBlock(on, null, null)
99+
endTryStatement(4, try, null)
100+
handleEmptyStatement(;)
101+
endBlockFunctionBody(2, {, })
74102
endTopLevelMethod(void, null, })
75103
endTopLevelDeclaration()
76104
endCompilationUnit(1, )

0 commit comments

Comments
 (0)