mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 14:07:57 +00:00
[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 <danrubel@google.com> Reviewed-by: Jens Johansen <jensj@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
parent
0272c1d863
commit
b8a8cfdcda
|
@ -21,6 +21,7 @@ import 'package:front_end/src/fasta/messages.dart'
|
|||
show
|
||||
LocatedMessage,
|
||||
Message,
|
||||
MessageCode,
|
||||
messageConstConstructorWithBody,
|
||||
messageConstMethod,
|
||||
messageConstructorWithReturnType,
|
||||
|
@ -562,6 +563,12 @@ class AstBuilder extends StackListener {
|
|||
push(ast.awaitExpression(awaitKeyword, pop()));
|
||||
}
|
||||
|
||||
void endInvalidAwaitExpression(
|
||||
Token awaitKeyword, Token endToken, MessageCode errorCode) {
|
||||
debugEvent("InvalidAwaitExpression");
|
||||
endAwaitExpression(awaitKeyword, endToken);
|
||||
}
|
||||
|
||||
@override
|
||||
void endBinaryExpression(Token operatorToken) {
|
||||
assert(operatorToken.isOperator ||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:front_end/src/fasta/messages.dart' show MessageCode;
|
||||
import 'package:front_end/src/fasta/parser.dart';
|
||||
import 'package:front_end/src/fasta/parser/forwarding_listener.dart';
|
||||
import 'package:front_end/src/scanner/token.dart';
|
||||
|
@ -577,6 +578,13 @@ class ForwardingTestListener extends ForwardingListener {
|
|||
super.endAwaitExpression(beginToken, endToken);
|
||||
}
|
||||
|
||||
@override
|
||||
void endInvalidAwaitExpression(
|
||||
Token beginToken, Token endToken, MessageCode errorCode) {
|
||||
end('InvalidAwaitExpression');
|
||||
super.endInvalidAwaitExpression(beginToken, endToken, errorCode);
|
||||
}
|
||||
|
||||
@override
|
||||
void endBlock(int count, Token beginToken, Token endToken) {
|
||||
end('Block');
|
||||
|
|
|
@ -2411,6 +2411,14 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
|
|||
push(forest.awaitExpression(popForValue(), keyword));
|
||||
}
|
||||
|
||||
@override
|
||||
void endInvalidAwaitExpression(
|
||||
Token keyword, Token endToken, fasta.MessageCode errorCode) {
|
||||
debugEvent("AwaitExpression");
|
||||
popForValue();
|
||||
push(buildProblem(errorCode, keyword.offset, keyword.length));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleAsyncModifier(Token asyncToken, Token starToken) {
|
||||
debugEvent("AsyncModifier");
|
||||
|
|
|
@ -479,6 +479,12 @@ class ForwardingListener implements Listener {
|
|||
listener?.endAwaitExpression(beginToken, endToken);
|
||||
}
|
||||
|
||||
@override
|
||||
void endInvalidAwaitExpression(
|
||||
Token beginToken, Token endToken, MessageCode errorCode) {
|
||||
listener?.endInvalidAwaitExpression(beginToken, endToken, errorCode);
|
||||
}
|
||||
|
||||
@override
|
||||
void endBinaryExpression(Token token) {
|
||||
listener?.endBinaryExpression(token);
|
||||
|
|
|
@ -6,7 +6,8 @@ library fasta.parser.listener;
|
|||
|
||||
import '../../scanner/token.dart' show Token;
|
||||
|
||||
import '../fasta_codes.dart' show Message, templateExperimentNotEnabled;
|
||||
import '../fasta_codes.dart'
|
||||
show Message, MessageCode, templateExperimentNotEnabled;
|
||||
|
||||
import '../quote.dart' show UnescapeErrorListener;
|
||||
|
||||
|
@ -57,6 +58,11 @@ class Listener implements UnescapeErrorListener {
|
|||
logEvent("AwaitExpression");
|
||||
}
|
||||
|
||||
void endInvalidAwaitExpression(
|
||||
Token beginToken, Token endToken, MessageCode errorCode) {
|
||||
logEvent("InvalidAwaitExpression");
|
||||
}
|
||||
|
||||
void beginBlock(Token token) {}
|
||||
|
||||
void endBlock(int count, Token beginToken, Token endToken) {
|
||||
|
|
|
@ -5744,12 +5744,15 @@ class Parser {
|
|||
Token awaitToken = token.next;
|
||||
assert(optional('await', awaitToken));
|
||||
listener.beginAwaitExpression(awaitToken);
|
||||
if (!inAsync) {
|
||||
reportRecoverableError(awaitToken, fasta.messageAwaitNotAsync);
|
||||
}
|
||||
token = parsePrecedenceExpression(
|
||||
awaitToken, POSTFIX_PRECEDENCE, allowCascades);
|
||||
listener.endAwaitExpression(awaitToken, token.next);
|
||||
if (inAsync) {
|
||||
listener.endAwaitExpression(awaitToken, token.next);
|
||||
} else {
|
||||
fasta.MessageCode errorCode = fasta.messageAwaitNotAsync;
|
||||
reportRecoverableError(awaitToken, errorCode);
|
||||
listener.endInvalidAwaitExpression(awaitToken, token.next, errorCode);
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ library fasta.type_promotion_look_ahead_listener;
|
|||
|
||||
import '../builder/builder.dart' show Declaration;
|
||||
|
||||
import '../messages.dart' show LocatedMessage, Message;
|
||||
import '../messages.dart' show LocatedMessage, Message, MessageCode;
|
||||
|
||||
import '../parser.dart'
|
||||
show Assert, IdentifierContext, FormalParameterKind, Listener, MemberKind;
|
||||
|
@ -209,6 +209,13 @@ class TypePromotionLookAheadListener extends Listener {
|
|||
state.popPushNull(beginToken.lexeme, beginToken); // Expression.
|
||||
}
|
||||
|
||||
@override
|
||||
void endInvalidAwaitExpression(
|
||||
Token beginToken, Token endToken, MessageCode errorCode) {
|
||||
debugEvent("InvalidAwaitExpression", beginToken);
|
||||
state.popPushNull(beginToken.lexeme, beginToken); // Expression.
|
||||
}
|
||||
|
||||
@override
|
||||
void endBinaryExpression(Token token) {
|
||||
debugEvent("BinaryExpression", token);
|
||||
|
|
|
@ -111,6 +111,10 @@ const String EXPECTATIONS = '''
|
|||
"name": "VerificationError",
|
||||
"group": "Fail"
|
||||
},
|
||||
{
|
||||
"name": "TransformVerificationError",
|
||||
"group": "Fail"
|
||||
},
|
||||
{
|
||||
"name": "TextSerializationFailure",
|
||||
"group": "Fail"
|
||||
|
@ -425,7 +429,11 @@ class Transform extends Step<Component, Component, FastaContext> {
|
|||
}
|
||||
List<String> errors = VerifyTransformed.verify(component);
|
||||
if (errors.isNotEmpty) {
|
||||
return fail(component, errors.join('\n'));
|
||||
return new Result<Component>(
|
||||
component,
|
||||
context.expectationSet["TransformVerificationError"],
|
||||
errors.join('\n'),
|
||||
null);
|
||||
}
|
||||
return pass(component);
|
||||
}
|
||||
|
|
|
@ -12,5 +12,7 @@ static method main() → dynamic {
|
|||
self::foo();
|
||||
}
|
||||
static method foo() → dynamic {
|
||||
await self::foo();
|
||||
invalid-expression "pkg/front_end/testcases/await_in_non_async.dart:11:3: Error: 'await' can only be used in 'async' or 'async*' methods.
|
||||
await foo();
|
||||
^^^^^";
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
library;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/await_in_non_async.dart:11:3: Error: 'await' can only be used in 'async' or 'async*' methods.
|
||||
// await foo();
|
||||
// ^^^^^
|
||||
//
|
||||
import self as self;
|
||||
|
||||
static method main() → dynamic {
|
||||
self::foo();
|
||||
}
|
||||
static method foo() → dynamic {
|
||||
invalid-expression "pkg/front_end/testcases/await_in_non_async.dart:11:3: Error: 'await' can only be used in 'async' or 'async*' methods.
|
||||
await foo();
|
||||
^^^^^";
|
||||
}
|
|
@ -12,5 +12,7 @@ static method main() → dynamic {
|
|||
self::foo();
|
||||
}
|
||||
static method foo() → dynamic {
|
||||
await self::foo();
|
||||
invalid-expression "pkg/front_end/testcases/await_in_non_async.dart:11:3: Error: 'await' can only be used in 'async' or 'async*' methods.
|
||||
await foo();
|
||||
^^^^^";
|
||||
}
|
||||
|
|
|
@ -12,5 +12,7 @@ static method main() → dynamic {
|
|||
self::foo();
|
||||
}
|
||||
static method foo() → dynamic {
|
||||
await self::foo();
|
||||
invalid-expression "pkg/front_end/testcases/await_in_non_async.dart:11:3: Error: 'await' can only be used in 'async' or 'async*' methods.
|
||||
await foo();
|
||||
^^^^^";
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
DeltaBlue: Fail # Fasta and dartk disagree on static initializers
|
||||
ambiguous_exports: RuntimeError # Expected, this file exports two main methods.
|
||||
await_in_non_async: Fail # Issue 37108.
|
||||
await_in_non_async: RuntimeError # Expected.
|
||||
bug31124: RuntimeError # Test has no main method (and we shouldn't add one).
|
||||
call: Fail # Test can't run.
|
||||
constructor_const_inference: RuntimeError # Test exercises strong mode semantics. See also Issue #33813.
|
||||
|
|
|
@ -10,7 +10,7 @@ abstract_members: TypeCheckError
|
|||
accessors: RuntimeError
|
||||
ambiguous_exports: RuntimeError # Expected, this file exports two main methods.
|
||||
argument_mismatch: InstrumentationMismatch # Test assumes Dart 1.0 semantics
|
||||
await_in_non_async: Fail # Issue 37108.
|
||||
await_in_non_async: RuntimeError # Expected.
|
||||
bug21938: TypeCheckError
|
||||
bug30695: TypeCheckError
|
||||
bug31124: RuntimeError # Test has no main method (and we shouldn't add one).
|
||||
|
|
Loading…
Reference in a new issue