mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 11:42:11 +00:00
Resolve invalid return statements in async/sync generators.
R=brianwilkerson@google.com, paulberry@google.com Change-Id: Ic0aa6ffbffc23b10814ab369ce041bde32da1388 Reviewed-on: https://dart-review.googlesource.com/65602 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Reviewed-by: Paul Berry <paulberry@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
863c79a5fa
commit
9c13c9dafc
|
@ -2432,20 +2432,6 @@ class CompileTimeErrorCodeTest_Kernel extends CompileTimeErrorCodeTest_Driver {
|
|||
await super.test_returnInGenerativeConstructor_expressionFunctionBody();
|
||||
}
|
||||
|
||||
@override
|
||||
@failingTest
|
||||
test_returnInGenerator_asyncStar() async {
|
||||
// AnalysisException: Element mismatch in /test.dart at /test.dart
|
||||
await super.test_returnInGenerator_asyncStar();
|
||||
}
|
||||
|
||||
@override
|
||||
@failingTest
|
||||
test_returnInGenerator_syncStar() async {
|
||||
// AnalysisException: Element mismatch in /test.dart at /test.dart
|
||||
await super.test_returnInGenerator_syncStar();
|
||||
}
|
||||
|
||||
@override
|
||||
@failingTest
|
||||
test_superInInvalidContext_binaryExpression() async {
|
||||
|
|
|
@ -3496,6 +3496,62 @@ class C {
|
|||
assertType(thisRef, 'C');
|
||||
}
|
||||
|
||||
test_invalid_generator_async_return_blockBody() async {
|
||||
addTestFile(r'''
|
||||
int a = 0;
|
||||
f() async* {
|
||||
return a;
|
||||
}
|
||||
''');
|
||||
await resolveTestFile();
|
||||
expect(result.errors, isNotEmpty);
|
||||
|
||||
var aRef = findNode.simple('a;');
|
||||
assertElement(aRef, findElement.topGet('a'));
|
||||
assertType(aRef, 'int');
|
||||
}
|
||||
|
||||
test_invalid_generator_async_return_expressionBody() async {
|
||||
addTestFile(r'''
|
||||
int a = 0;
|
||||
f() async* => a;
|
||||
''');
|
||||
await resolveTestFile();
|
||||
expect(result.errors, isNotEmpty);
|
||||
|
||||
var aRef = findNode.simple('a;');
|
||||
assertElement(aRef, findElement.topGet('a'));
|
||||
assertType(aRef, 'int');
|
||||
}
|
||||
|
||||
test_invalid_generator_sync_return_blockBody() async {
|
||||
addTestFile(r'''
|
||||
int a = 0;
|
||||
f() sync* {
|
||||
return a;
|
||||
}
|
||||
''');
|
||||
await resolveTestFile();
|
||||
expect(result.errors, isNotEmpty);
|
||||
|
||||
var aRef = findNode.simple('a;');
|
||||
assertElement(aRef, findElement.topGet('a'));
|
||||
assertType(aRef, 'int');
|
||||
}
|
||||
|
||||
test_invalid_generator_sync_return_expressionBody() async {
|
||||
addTestFile(r'''
|
||||
int a = 0;
|
||||
f() sync* => a;
|
||||
''');
|
||||
await resolveTestFile();
|
||||
expect(result.errors, isNotEmpty);
|
||||
|
||||
var aRef = findNode.simple('a;');
|
||||
assertElement(aRef, findElement.topGet('a'));
|
||||
assertType(aRef, 'int');
|
||||
}
|
||||
|
||||
test_invalid_instanceCreation_abstract() async {
|
||||
addTestFile(r'''
|
||||
abstract class C<T> {
|
||||
|
|
|
@ -703,6 +703,13 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
|
|||
|
||||
_typeInferrer.inferFunctionBody(
|
||||
this, factory, _computeReturnTypeContext(member), asyncModifier, body);
|
||||
|
||||
// We finished the invalid body inference, desugar it into its error.
|
||||
if (body is InvalidStatementJudgment) {
|
||||
InvalidStatementJudgment judgment = body;
|
||||
body = new ExpressionStatement(judgment.desugaredError);
|
||||
}
|
||||
|
||||
if (builder.kind == ProcedureKind.Setter) {
|
||||
bool oneParameter = formals != null &&
|
||||
formals.required.length == 1 &&
|
||||
|
@ -3933,7 +3940,8 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
|
|||
@override
|
||||
void handleInvalidStatement(Token token, Message message) {
|
||||
Statement statement = pop();
|
||||
push(wrapInCompileTimeErrorStatement(statement, message));
|
||||
var error = buildCompileTimeError(message, statement.fileOffset, noLength);
|
||||
push(new InvalidStatementJudgment(error, statement));
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -93,6 +93,7 @@ export 'kernel_shadow_ast.dart'
|
|||
IndexAssignmentJudgment,
|
||||
InvalidConstructorInvocationJudgment,
|
||||
InvalidPropertyGetJudgment,
|
||||
InvalidStatementJudgment,
|
||||
InvalidVariableWriteJudgment,
|
||||
InvalidWriteJudgment,
|
||||
ShadowInvalidFieldInitializer,
|
||||
|
|
|
@ -3101,6 +3101,31 @@ class ThrowJudgment extends Throw implements ExpressionJudgment {
|
|||
}
|
||||
}
|
||||
|
||||
/// Synthetic judgment class representing a statement that is not allowed at
|
||||
/// the location it was found, and should be replaced with an error.
|
||||
class InvalidStatementJudgment extends ExpressionStatement
|
||||
implements StatementJudgment {
|
||||
final kernel.Expression desugaredError;
|
||||
final StatementJudgment statement;
|
||||
|
||||
InvalidStatementJudgment(this.desugaredError, this.statement)
|
||||
: super(new NullLiteral());
|
||||
|
||||
@override
|
||||
void infer<Expression, Statement, Initializer, Type>(
|
||||
ShadowTypeInferrer inferrer,
|
||||
Factory<Expression, Statement, Initializer, Type> factory) {
|
||||
inferrer.inferStatement(factory, statement);
|
||||
|
||||
// If this judgment is a part of a Block, replace it there.
|
||||
// Otherwise, the parent would be a FunctionNode, but not yet.
|
||||
if (parent is Block) {
|
||||
parent.replaceChild(this, new ExpressionStatement(desugaredError));
|
||||
parent = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Concrete shadow object representing a catch clause.
|
||||
class CatchJudgment extends Catch {
|
||||
final Token onKeyword;
|
||||
|
|
Loading…
Reference in a new issue