Skip to content

Commit b8a8cfd

Browse files
johnniwinthercommit-bot@chromium.org
authored andcommitted
[cfe] Use InvalidExpression for await on non-async context.
CFE failed to replace an invalid AwaitExpression in a non-async context with an InvalidExpression. The lead to untransformed (and thus unexpected) await expressions crashing the hot reload. Closes #37108 Change-Id: I4457925b20749d231cbf9dac80203ee9b381a312 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/107501 Reviewed-by: Dan Rubel <[email protected]> Reviewed-by: Jens Johansen <[email protected]> Commit-Queue: Johnni Winther <[email protected]>
1 parent 0272c1d commit b8a8cfd

14 files changed

+89
-12
lines changed

pkg/analyzer/lib/src/fasta/ast_builder.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import 'package:front_end/src/fasta/messages.dart'
2121
show
2222
LocatedMessage,
2323
Message,
24+
MessageCode,
2425
messageConstConstructorWithBody,
2526
messageConstMethod,
2627
messageConstructorWithReturnType,
@@ -562,6 +563,12 @@ class AstBuilder extends StackListener {
562563
push(ast.awaitExpression(awaitKeyword, pop()));
563564
}
564565

566+
void endInvalidAwaitExpression(
567+
Token awaitKeyword, Token endToken, MessageCode errorCode) {
568+
debugEvent("InvalidAwaitExpression");
569+
endAwaitExpression(awaitKeyword, endToken);
570+
}
571+
565572
@override
566573
void endBinaryExpression(Token operatorToken) {
567574
assert(operatorToken.isOperator ||

pkg/analyzer/test/generated/parser_fasta_listener.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'package:front_end/src/fasta/messages.dart' show MessageCode;
56
import 'package:front_end/src/fasta/parser.dart';
67
import 'package:front_end/src/fasta/parser/forwarding_listener.dart';
78
import 'package:front_end/src/scanner/token.dart';
@@ -577,6 +578,13 @@ class ForwardingTestListener extends ForwardingListener {
577578
super.endAwaitExpression(beginToken, endToken);
578579
}
579580

581+
@override
582+
void endInvalidAwaitExpression(
583+
Token beginToken, Token endToken, MessageCode errorCode) {
584+
end('InvalidAwaitExpression');
585+
super.endInvalidAwaitExpression(beginToken, endToken, errorCode);
586+
}
587+
580588
@override
581589
void endBlock(int count, Token beginToken, Token endToken) {
582590
end('Block');

pkg/front_end/lib/src/fasta/kernel/body_builder.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2411,6 +2411,14 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
24112411
push(forest.awaitExpression(popForValue(), keyword));
24122412
}
24132413

2414+
@override
2415+
void endInvalidAwaitExpression(
2416+
Token keyword, Token endToken, fasta.MessageCode errorCode) {
2417+
debugEvent("AwaitExpression");
2418+
popForValue();
2419+
push(buildProblem(errorCode, keyword.offset, keyword.length));
2420+
}
2421+
24142422
@override
24152423
void handleAsyncModifier(Token asyncToken, Token starToken) {
24162424
debugEvent("AsyncModifier");

pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,12 @@ class ForwardingListener implements Listener {
479479
listener?.endAwaitExpression(beginToken, endToken);
480480
}
481481

482+
@override
483+
void endInvalidAwaitExpression(
484+
Token beginToken, Token endToken, MessageCode errorCode) {
485+
listener?.endInvalidAwaitExpression(beginToken, endToken, errorCode);
486+
}
487+
482488
@override
483489
void endBinaryExpression(Token token) {
484490
listener?.endBinaryExpression(token);

pkg/front_end/lib/src/fasta/parser/listener.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ library fasta.parser.listener;
66

77
import '../../scanner/token.dart' show Token;
88

9-
import '../fasta_codes.dart' show Message, templateExperimentNotEnabled;
9+
import '../fasta_codes.dart'
10+
show Message, MessageCode, templateExperimentNotEnabled;
1011

1112
import '../quote.dart' show UnescapeErrorListener;
1213

@@ -57,6 +58,11 @@ class Listener implements UnescapeErrorListener {
5758
logEvent("AwaitExpression");
5859
}
5960

61+
void endInvalidAwaitExpression(
62+
Token beginToken, Token endToken, MessageCode errorCode) {
63+
logEvent("InvalidAwaitExpression");
64+
}
65+
6066
void beginBlock(Token token) {}
6167

6268
void endBlock(int count, Token beginToken, Token endToken) {

pkg/front_end/lib/src/fasta/parser/parser.dart

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5744,12 +5744,15 @@ class Parser {
57445744
Token awaitToken = token.next;
57455745
assert(optional('await', awaitToken));
57465746
listener.beginAwaitExpression(awaitToken);
5747-
if (!inAsync) {
5748-
reportRecoverableError(awaitToken, fasta.messageAwaitNotAsync);
5749-
}
57505747
token = parsePrecedenceExpression(
57515748
awaitToken, POSTFIX_PRECEDENCE, allowCascades);
5752-
listener.endAwaitExpression(awaitToken, token.next);
5749+
if (inAsync) {
5750+
listener.endAwaitExpression(awaitToken, token.next);
5751+
} else {
5752+
fasta.MessageCode errorCode = fasta.messageAwaitNotAsync;
5753+
reportRecoverableError(awaitToken, errorCode);
5754+
listener.endInvalidAwaitExpression(awaitToken, token.next, errorCode);
5755+
}
57535756
return token;
57545757
}
57555758

pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ library fasta.type_promotion_look_ahead_listener;
66

77
import '../builder/builder.dart' show Declaration;
88

9-
import '../messages.dart' show LocatedMessage, Message;
9+
import '../messages.dart' show LocatedMessage, Message, MessageCode;
1010

1111
import '../parser.dart'
1212
show Assert, IdentifierContext, FormalParameterKind, Listener, MemberKind;
@@ -209,6 +209,13 @@ class TypePromotionLookAheadListener extends Listener {
209209
state.popPushNull(beginToken.lexeme, beginToken); // Expression.
210210
}
211211

212+
@override
213+
void endInvalidAwaitExpression(
214+
Token beginToken, Token endToken, MessageCode errorCode) {
215+
debugEvent("InvalidAwaitExpression", beginToken);
216+
state.popPushNull(beginToken.lexeme, beginToken); // Expression.
217+
}
218+
212219
@override
213220
void endBinaryExpression(Token token) {
214221
debugEvent("BinaryExpression", token);

pkg/front_end/test/fasta/testing/suite.dart

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ const String EXPECTATIONS = '''
111111
"name": "VerificationError",
112112
"group": "Fail"
113113
},
114+
{
115+
"name": "TransformVerificationError",
116+
"group": "Fail"
117+
},
114118
{
115119
"name": "TextSerializationFailure",
116120
"group": "Fail"
@@ -425,7 +429,11 @@ class Transform extends Step<Component, Component, FastaContext> {
425429
}
426430
List<String> errors = VerifyTransformed.verify(component);
427431
if (errors.isNotEmpty) {
428-
return fail(component, errors.join('\n'));
432+
return new Result<Component>(
433+
component,
434+
context.expectationSet["TransformVerificationError"],
435+
errors.join('\n'),
436+
null);
429437
}
430438
return pass(component);
431439
}

pkg/front_end/testcases/await_in_non_async.dart.legacy.expect

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,7 @@ static method main() → dynamic {
1212
self::foo();
1313
}
1414
static method foo() → dynamic {
15-
await self::foo();
15+
invalid-expression "pkg/front_end/testcases/await_in_non_async.dart:11:3: Error: 'await' can only be used in 'async' or 'async*' methods.
16+
await foo();
17+
^^^^^";
1618
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
library;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/await_in_non_async.dart:11:3: Error: 'await' can only be used in 'async' or 'async*' methods.
6+
// await foo();
7+
// ^^^^^
8+
//
9+
import self as self;
10+
11+
static method main() → dynamic {
12+
self::foo();
13+
}
14+
static method foo() → dynamic {
15+
invalid-expression "pkg/front_end/testcases/await_in_non_async.dart:11:3: Error: 'await' can only be used in 'async' or 'async*' methods.
16+
await foo();
17+
^^^^^";
18+
}

pkg/front_end/testcases/await_in_non_async.dart.strong.expect

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,7 @@ static method main() → dynamic {
1212
self::foo();
1313
}
1414
static method foo() → dynamic {
15-
await self::foo();
15+
invalid-expression "pkg/front_end/testcases/await_in_non_async.dart:11:3: Error: 'await' can only be used in 'async' or 'async*' methods.
16+
await foo();
17+
^^^^^";
1618
}

pkg/front_end/testcases/await_in_non_async.dart.strong.transformed.expect

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,7 @@ static method main() → dynamic {
1212
self::foo();
1313
}
1414
static method foo() → dynamic {
15-
await self::foo();
15+
invalid-expression "pkg/front_end/testcases/await_in_non_async.dart:11:3: Error: 'await' can only be used in 'async' or 'async*' methods.
16+
await foo();
17+
^^^^^";
1618
}

pkg/front_end/testcases/legacy.status

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
DeltaBlue: Fail # Fasta and dartk disagree on static initializers
99
ambiguous_exports: RuntimeError # Expected, this file exports two main methods.
10-
await_in_non_async: Fail # Issue 37108.
10+
await_in_non_async: RuntimeError # Expected.
1111
bug31124: RuntimeError # Test has no main method (and we shouldn't add one).
1212
call: Fail # Test can't run.
1313
constructor_const_inference: RuntimeError # Test exercises strong mode semantics. See also Issue #33813.

pkg/front_end/testcases/strong.status

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ abstract_members: TypeCheckError
1010
accessors: RuntimeError
1111
ambiguous_exports: RuntimeError # Expected, this file exports two main methods.
1212
argument_mismatch: InstrumentationMismatch # Test assumes Dart 1.0 semantics
13-
await_in_non_async: Fail # Issue 37108.
13+
await_in_non_async: RuntimeError # Expected.
1414
bug21938: TypeCheckError
1515
bug30695: TypeCheckError
1616
bug31124: RuntimeError # Test has no main method (and we shouldn't add one).

0 commit comments

Comments
 (0)