blob: edb8c7e6893a7d0e89c7a747191dec9fd68f0e01 [file] [log] [blame]
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// 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:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/test_utilities/find_node.dart';
import 'package:linter/src/rules/use_build_context_synchronously.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../rule_test_support.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(AsyncStateTest);
defineReflectiveTests(UseBuildContextSynchronouslyTest);
});
}
@reflectiveTest
class AsyncStateTest extends PubPackageResolutionTest {
@override
bool get addFlutterPackageDep => true;
Element get contextElement =>
findNode.simple('context /* ref */').staticElement!;
FindNode get findNode => FindNode(result.content, result.unit);
Future<void> resolveCode(String code) async {
addTestFile(code);
await resolveTestFile();
}
test_adjacentStrings_referenceAfter_awaitInString() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
'' '${await Future.value()}';
context /* ref */;
}
''');
var block = findNode.block('await');
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_adjacentStrings_referenceInSecondString_awaitInFirstString() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
'${await Future.value()}' '${context /* ref */}';
}
''');
var adjacentStrings = findNode.adjacentStrings('await');
var reference = findNode.stringInterpolation('context /* ref */');
expect(adjacentStrings.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_awaitExpression_referenceInExpression() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
await Future.value(context /* ref */);
}
''');
var await_ = findNode.awaitExpression('await');
var reference = findNode.instanceCreation('context /* ref */');
expect(await_.asyncStateFor(reference, contextElement), isNull);
}
test_block_referenceThenAwait() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
await Future.value();
context /* ref */;
}
''');
var block = findNode.block('context /* ref */');
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_cascade_referenceAfter_awaitInTarget() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
(await Future.value())..toString();
context /* ref */;
}
''');
var block = findNode.block('await');
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_cascade_referenceAfterTarget_awaitAfterTarget() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
[]..add(await Future.value())..add(context /* ref */);
}
''');
var cascade = findNode.cascade('await');
var reference = findNode.methodInvocation('context /* ref */');
expect(cascade.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_cascade_referenceAfterTarget_awaitInTarget() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
(await Future.value())..add(context /* ref */);
}
''');
var cascade = findNode.cascade('await');
var reference = findNode.methodInvocation('context /* ref */');
expect(cascade.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_cascade_referenceAfterTarget_awaitInTarget2() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
(await Future.value())..add(1)..add(context /* ref */);
}
''');
var cascade = findNode.cascade('await');
var reference = findNode.methodInvocation('context /* ref */');
expect(cascade.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_conditional_referenceAfter_awaitInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
await Future.value(true) ? null : null;
context /* ref */;
}
''');
var block = findNode.block('await');
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_conditional_referenceAfter_awaitInThen() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
false ? await Future.value() : null;
context /* ref */;
}
''');
var block = findNode.block('false');
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_conditional_referenceInElse_mountedCheckInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
context.mounted ? null : context /* ref */;
}
''');
var conditional = findNode.conditionalExpression('context /* ref */');
var reference = findNode.simple('context /* ref */');
expect(conditional.asyncStateFor(reference, contextElement), isNull);
}
test_conditional_referenceInElse_notMountedCheckInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
!context.mounted ? null : context /* ref */;
}
''');
var conditional = findNode.conditionalExpression('context /* ref */');
var reference = findNode.simple('context /* ref */');
expect(conditional.asyncStateFor(reference, contextElement),
equals(AsyncState.mountedCheck));
}
test_conditional_referenceInThen_mountedCheckInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
context.mounted ? context /* ref */ : null;
}
''');
var conditional = findNode.conditionalExpression('context /* ref */');
var reference = findNode.simple('context /* ref */');
expect(conditional.asyncStateFor(reference, contextElement),
equals(AsyncState.mountedCheck));
}
test_conditional_referenceInThen_notMountedCheckInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
!context.mounted ? context /* ref */ : null;
}
''');
var conditional = findNode.conditionalExpression('context /* ref */');
var reference = findNode.simple('context /* ref */');
expect(conditional.asyncStateFor(reference, contextElement), isNull);
}
test_doWhileStatement_referenceInBody_asyncInBody() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
do {
await Future.value();
context /* ref */;
} while (true);
}
''');
var block = findNode.block('context /* ref */');
var reference = findNode.statement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_doWhileStatement_referenceInBody_asyncInBody2() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
do {
context /* ref */;
await Future.value();
} while (true);
}
''');
var block = findNode.block('context /* ref */');
var reference = findNode.statement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_extensionOverride_referenceAfter_awaitInArgument() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
E(await Future.value(false)).f();
context /* ref */;
}
extension E on int {
void f() {}
}
''');
var block = findNode.block('await');
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_forElementWithDeclaration_referenceAfter_awaitInPartCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
[
for (var i = 0; i < await Future.value(1); i++) null,
];
context /* ref */;
}
''');
var block = findNode.block('await');
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_forElementWithDeclaration_referenceAfter_awaitInPartInitialization() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
[
for (var i = await Future.value(1); i < 7; i++) null,
];
context /* ref */;
}
''');
var block = findNode.block('await');
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_forElementWithDeclaration_referenceAfter_awaitInPartUpdaters() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
[
for (var i = 0; i < 5; i += await Future.value()) null,
];
context /* ref */;
}
''');
var block = findNode.block('await');
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_forElementWithDeclaration_referenceInExpression_mountedCheckInPartCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
[
for (var i = 0; context.mounted; i++) context /* ref */,
];
}
''');
var forElement = findNode.forElement('for ');
var reference = findNode.expression('context /* ref */');
expect(forElement.asyncStateFor(reference, contextElement),
AsyncState.mountedCheck);
}
test_forElementWithEach_referenceAfter_awaitInExpression() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
[
for (var e in []) await Future.value(),
];
context /* ref */;
}
''');
var block = findNode.block('await');
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_forElementWithEach_referenceAfter_awaitInPartExpression() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
[
for (var e in await Future.value([])) null,
];
context /* ref */;
}
''');
var block = findNode.block('await');
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_forElementWithExpression_referenceAfter_awaitInPartCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context, int i) async {
[
for (i = 0; i < await Future.value(1); i++) null,
];
context /* ref */;
}
''');
var block = findNode.block('await');
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_forElementWithExpression_referenceAfter_awaitInPartInitialization() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context, int i) async {
[
for (i = await Future.value(1); i < 7; i++) null,
];
context /* ref */;
}
''');
var block = findNode.block('await');
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_forElementWithExpression_referenceAfter_awaitInPartUpdaters() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context, int i) async {
[
for (i = 0; i < 5; i += await Future.value()) null,
];
context /* ref */;
}
''');
var block = findNode.block('await');
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_forElementWithExpression_referenceAfter_mountedCheckInPartCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context, int i) async {
[
for (i = 0; context.mounted; i++) context /* ref */,
];
}
''');
var forElement = findNode.forElement('for ');
var reference = findNode.expression('context /* ref */');
expect(forElement.asyncStateFor(reference, contextElement),
AsyncState.mountedCheck);
}
test_forStatement_referenceInBody_asyncInBody() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
for (var a in []) {
await Future.value();
context /* ref */;
}
}
''');
var block = findNode.block('context /* ref */');
var reference = findNode.statement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_forStatement_referenceInBody_asyncInBody2() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
for (var a in []) {
context /* ref */;
await Future.value();
}
}
''');
var block = findNode.block('context /* ref */');
var reference = findNode.statement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_forStatementWithDeclaration_referenceAfter_awaitInPartCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
for (var i = 0; i < await Future.value(1); i++) null;
context /* ref */;
}
''');
var block = findNode.forStatement('await').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_forStatementWithDeclaration_referenceAfter_awaitInPartInitialization() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
for (var i = await Future.value(1); i < 7; i++) null;
context /* ref */;
}
''');
var block = findNode.forStatement('await').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_forStatementWithDeclaration_referenceAfter_awaitInPartUpdaters() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
for (var i = 0; i < 5; i += await Future.value()) null;
context /* ref */;
}
''');
var block = findNode.forStatement('await').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_forStatementWithDeclaration_referenceInBody_mountedCheckInPartCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
for (var i = 0; context.mounted; i++) context /* ref */;
}
''');
var forStatement = findNode.forStatement('for ');
var reference = findNode.expressionStatement('context /* ref */');
expect(forStatement.asyncStateFor(reference, contextElement),
AsyncState.mountedCheck);
}
test_forStatementWithEach_referenceAfter_awaitInPartExpression() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
for (var e in await Future.value([])) null;
context /* ref */;
}
''');
var block = findNode.forStatement('await').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_forStatementWithExpression_referenceAfter_awaitInPartCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context, int i) async {
for (i = 0; i < await Future.value(1); i++) null;
context /* ref */;
}
''');
var block = findNode.forStatement('await').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_forStatementWithExpression_referenceAfter_awaitInPartInitialization() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context, int i) async {
for (i = await Future.value(1); i < 7; i++) null;
context /* ref */;
}
''');
var block = findNode.forStatement('await').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_forStatementWithExpression_referenceAfter_awaitInPartUpdaters() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context, int i) async {
for (i = 0; i < 5; i += await Future.value()) null;
context /* ref */;
}
''');
var block = findNode.forStatement('await').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_forStatementWithExpression_referenceAfter_mountedCheckInPartCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context, int i) async {
for (i = 0; context.mounted; i++) context /* ref */;
}
''');
var forStatement = findNode.forStatement('for ');
var reference = findNode.expressionStatement('context /* ref */');
expect(forStatement.asyncStateFor(reference, contextElement),
AsyncState.mountedCheck);
}
test_functionExpressionInvocation_referenceAfter_awaitInTarget() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
((await Future.value()).add)(1);
context /* ref */;
}
''');
var block = findNode.block('await');
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_ifElement_referenceAfter_asyncInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
[
if (await Future.value(true)) null,
context /* ref */,
];
}
''');
var ifElement = findNode.listLiteral('if (');
var reference = findNode.expression('context /* ref */,');
expect(ifElement.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_ifElement_referenceInElse_asyncInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
[
if (await Future.value(true)) null else context /* ref */,
];
}
''');
var ifElement = findNode.ifElement('if (');
var reference = findNode.expression('context /* ref */');
expect(ifElement.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_ifElement_referenceInElse_mountedGuardInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
[
if (context.mounted) null else context /* ref */,
];
}
''');
var ifElement = findNode.ifElement('if (');
var reference = findNode.expression('context /* ref */');
expect(ifElement.asyncStateFor(reference, contextElement), isNull);
}
test_ifElement_referenceInElse_notMountedGuardInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
[
if (!context.mounted) null else context /* ref */,
];
}
''');
var ifElement = findNode.ifElement('if (');
var reference = findNode.expression('context /* ref */');
expect(ifElement.asyncStateFor(reference, contextElement),
AsyncState.mountedCheck);
}
test_ifElement_referenceInThen_asyncInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
[
if (await Future.value(true)) context /* ref */,
];
}
''');
var ifElement = findNode.ifElement('if (');
var reference = findNode.expression('context /* ref */');
expect(ifElement.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_ifStatement_referenceAfter_asyncInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (await Future.value(true)) {
return;
}
context /* ref */;
}
''');
var block = findNode.ifStatement('if (').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_ifStatement_referenceAfter_asyncInThen_notMountedGuardInElse() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (1 == 2) {
await Future.value();
} else {
if (!context.mounted) return;
}
context /* ref */;
}
''');
var block = findNode.ifStatement('if (1').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_ifStatement_referenceAfter_awaitThenExitInElse() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (1 == 2) {
} else {
await Future.value();
return;
}
context /* ref */;
}
''');
var block = findNode.ifStatement('if ').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement), isNull);
}
test_ifStatement_referenceAfter_awaitThenExitInThen() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (1 == 2) {
await Future.value();
return;
}
context /* ref */;
}
''');
var block = findNode.ifStatement('if ').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement), isNull);
}
test_ifStatement_referenceAfter_conditionHasMountedEqEqFalse_exit() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (context.mounted == false) return;
context /* ref */;
}
''');
var block = findNode.ifStatement('if ').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.notMountedCheck);
}
test_ifStatement_referenceAfter_conditionHasMountedEqEqNonConstant_exit() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context, bool b) async {
if (context.mounted == b) return;
context /* ref */;
}
''');
var block = findNode.ifStatement('if ').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement), null);
}
test_ifStatement_referenceAfter_conditionHasMountedEqEqTrue_exit() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (context.mounted == true) return;
context /* ref */;
}
''');
var block = findNode.ifStatement('if ').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement), null);
}
test_ifStatement_referenceAfter_conditionHasMountedNotEqFalse_exit() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (context.mounted != false) return;
context /* ref */;
}
''');
var block = findNode.ifStatement('if ').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement), null);
}
test_ifStatement_referenceAfter_conditionHasMountedNotEqTrue_exit() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (context.mounted != true) return;
context /* ref */;
}
''');
var block = findNode.ifStatement('if ').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.notMountedCheck);
}
test_ifStatement_referenceAfter_conditionHasNotMountedEqEqFalse_exit() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (!context.mounted == false) return;
context /* ref */;
}
''');
var block = findNode.ifStatement('if ').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement), null);
}
test_ifStatement_referenceAfter_conditionHasNotMountedEqEqTrue_exit() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (!context.mounted == true) return;
context /* ref */;
}
''');
var block = findNode.ifStatement('if ').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.notMountedCheck);
}
test_ifStatement_referenceAfter_conditionHasNotMountedNotEqTrue_exit() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (!context.mounted != true) return;
context /* ref */;
}
''');
var block = findNode.ifStatement('if ').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement), null);
}
test_ifStatement_referenceAfter_notMountedCheckInCondition_break() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
switch (1) {
case (1):
if (!context.mounted) break;
context /* ref */;
}
}
''');
var block = findNode.ifStatement('if ').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.notMountedCheck);
}
test_ifStatement_referenceAfter_notMountedCheckInCondition_exit() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (!context.mounted) return;
context /* ref */;
}
''');
var block = findNode.ifStatement('if ').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.notMountedCheck);
}
test_ifStatement_referenceAfter_notMountedGuardInCondition_exitInThen_awaitInElse() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (!context.mounted) {
return;
} else {
await f();
}
context /* ref */;
}
''');
var block = findNode.ifStatement('if (').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_ifStatement_referenceAfter_notMountedGuardsInThenAndElse() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (1 == 2) {
if (!context.mounted) return;
} else {
if (!context.mounted) return;
}
context /* ref */;
}
''');
var block = findNode.ifStatement('if (1').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.notMountedCheck);
}
test_ifStatement_referenceAfter_notStateMountedCheckInCondition_exit() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
abstract class C extends State<StatefulWidget> {
void foo() async {
if (!this.mounted) return;
context /* ref */;
}
''');
var block = findNode.ifStatement('if ').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.notMountedCheck);
}
test_ifStatement_referenceInCaseWhen_asyncInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context, Future<num> value) async {
if (await value case int() when f(context)) {
context /* ref */;
}
}
bool f(BuildContext context) => true;
''');
var ifStatement = findNode.ifStatement('if (');
var reference = findNode.block('context /* ref */');
expect(ifStatement.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_ifStatement_referenceInElse_asyncInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (await Future.value(true)) {
} else {
context /* ref */;
}
}
''');
var ifStatement = findNode.ifStatement('if (');
var reference = findNode.block('context /* ref */');
expect(ifStatement.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_ifStatement_referenceInElse_mountedGuardInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (context.mounted) {
} else {
context /* ref */;
}
}
''');
var ifStatement = findNode.ifStatement('if (');
var reference = findNode.block('context /* ref */');
expect(ifStatement.asyncStateFor(reference, contextElement), isNull);
}
test_ifStatement_referenceInElse_notMounted() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (!context.mounted) {
} else {
context /* ref */;
}
}
''');
var ifStatement = findNode.ifStatement('if ');
var reference = findNode.block('context /* ref */');
expect(ifStatement.asyncStateFor(reference, contextElement),
AsyncState.mountedCheck);
}
test_ifStatement_referenceInElse_notMountedOrUninterestingInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (!context.mounted || 1 == 2) {
} else {
context /* ref */;
}
}
''');
var ifStatement = findNode.ifStatement('if ');
var reference = findNode.block('context /* ref */');
expect(ifStatement.asyncStateFor(reference, contextElement),
AsyncState.mountedCheck);
}
test_ifStatement_referenceInElse_uninterestingAndNotMountedInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (1 == 2 && !context.mounted) {
} else {
context /* ref */;
}
}
''');
var ifStatement = findNode.ifStatement('if ');
var reference = findNode.block('context /* ref */');
expect(ifStatement.asyncStateFor(reference, contextElement),
AsyncState.mountedCheck);
}
test_ifStatement_referenceInElse_uninterestingOrNotMountedInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (1 == 2 || !context.mounted) {
} else {
context /* ref */;
}
}
''');
var ifStatement = findNode.ifStatement('if ');
var reference = findNode.block('context /* ref */');
expect(ifStatement.asyncStateFor(reference, contextElement),
AsyncState.mountedCheck);
}
test_ifStatement_referenceInThen_asyncInAssignmentInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context, bool m) async {
if (m = context.mounted) {
context /* ref */;
}
}
''');
var ifStatement = findNode.ifStatement('if (');
var reference = findNode.block('context /* ref */');
expect(ifStatement.asyncStateFor(reference, contextElement),
AsyncState.mountedCheck);
}
test_ifStatement_referenceInThen_asyncInCaseWhen() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context, Object value) async {
if (value case int() when await Future.value(true)) {
context /* ref */;
}
}
''');
var ifStatement = findNode.ifStatement('if (');
var reference = findNode.block('context /* ref */');
expect(ifStatement.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_ifStatement_referenceInThen_asyncInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (await Future.value(true)) {
context /* ref */;
}
}
''');
var ifStatement = findNode.ifStatement('if (');
var reference = findNode.block('context /* ref */');
expect(ifStatement.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_ifStatement_referenceInThen_awaitAndMountedInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (await Future.value(true) && context.mounted) {
context /* ref */;
}
}
''');
var ifStatement = findNode.ifStatement('if ');
var reference = findNode.block('context /* ref */');
expect(ifStatement.asyncStateFor(reference, contextElement),
AsyncState.mountedCheck);
}
test_ifStatement_referenceInThen_awaitOrMountedInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (await Future.value(true) || context.mounted) {
context /* ref */;
}
}
''');
var ifStatement = findNode.ifStatement('if ');
var reference = findNode.block('context /* ref */');
expect(ifStatement.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_ifStatement_referenceInThen_conditionAndMountedInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (1 == 2 && context.mounted) {
context /* ref */;
}
}
''');
var ifStatement = findNode.ifStatement('if ');
var reference = findNode.block('context /* ref */');
expect(ifStatement.asyncStateFor(reference, contextElement),
AsyncState.mountedCheck);
}
test_ifStatement_referenceInThen_mountedAndAwaitInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (context.mounted && await Future.value(true)) {
context /* ref */;
}
}
''');
var ifStatement = findNode.ifStatement('if ');
var reference = findNode.block('context /* ref */');
expect(ifStatement.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_ifStatement_referenceInThen_mountedGuardInCaseWhen() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context, Object value) async {
if (value case int() when context.mounted) {
context /* ref */;
}
}
''');
var ifStatement = findNode.ifStatement('if (');
var reference = findNode.block('context /* ref */');
expect(ifStatement.asyncStateFor(reference, contextElement),
AsyncState.mountedCheck);
}
test_ifStatement_referenceInThen_mountedInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (context.mounted) {
context /* ref */;
}
}
''');
var ifStatement = findNode.ifStatement('if ');
var reference = findNode.block('context /* ref */');
expect(ifStatement.asyncStateFor(reference, contextElement),
AsyncState.mountedCheck);
}
test_ifStatement_referenceInThen_mountedOrAwaitInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (context.mounted || await Future.value(true)) {
context /* ref */;
}
}
''');
var ifStatement = findNode.ifStatement('if ');
var reference = findNode.block('context /* ref */');
expect(ifStatement.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_ifStatement_referenceInThen_uninterestingOrMountedInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (1 == 2 || context.mounted) {
context /* ref */;
}
}
''');
var ifStatement = findNode.ifStatement('if ');
var reference = findNode.block('context /* ref */');
expect(ifStatement.asyncStateFor(reference, contextElement), isNull);
}
test_indexExpression_referenceInRhs_asyncInIndex() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context, List<Object> list) async {
list[await c()] = context /* ref */;
}
''');
var indexExpression = findNode.assignment('[');
var reference = findNode.expression('context /* ref */');
expect(indexExpression.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_instanceCreationExpression_referenceInParameters_awaitInParameters() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
new List.filled(await Future.value(1), context /* ref */);
}
''');
var instanceCreation = findNode.instanceCreation('await');
var reference = findNode.argumentList('context /* ref */');
expect(instanceCreation.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_isExpression_referenceAfter_awaitInExpression() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
await Future.value() is int;
context /* ref */;
}
Future<void> c() async {}
''');
var block = findNode.expressionStatement('await').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_methodInvocation_referenceAfter_asyncInTarget() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
(await Future.value([])).add(1);
context /* ref */;
}
''');
var block = findNode.expressionStatement('await').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_methodInvocation_referenceAfter_awaitInParameters() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
[].indexOf(1, await Future.value());
context /* ref */;
}
''');
var block = findNode.expressionStatement('await').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_methodInvocation_referenceAfter_awaitInTarget() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
(await Future.value()).add(1);
context /* ref */;
}
''');
var block = findNode.expressionStatement('await').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_methodInvocation_referenceInParameters_awaitInParameters() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
f(await Future.value(), context /* ref */);
}
void f(_, _) {}
''');
var methodInvocation = findNode.methodInvocation('await');
var reference = findNode.argumentList('context /* ref */');
expect(methodInvocation.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_postfix_referenceAfter_awaitInExpression() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
(await Future.value())!;
context /* ref */;
}
''');
var block = findNode.expressionStatement('await').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_propertyAccess_referenceAfter_awaitInTarget() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
(await Future.value(true)).isEven;
context /* ref */;
}
''');
var block = findNode.expressionStatement('await').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_recordLiteral_referenceAfter_awaitInField() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
(await Future.value(), );
context /* ref */;
}
''');
var block = findNode.expressionStatement('await').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_recordLiteral_referenceAfter_awaitInNamedField() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
(f: await Future.value(), );
context /* ref */;
}
''');
var block = findNode.expressionStatement('await').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_spread_referenceAfter_awaitInSpread() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
[...(await Future.value())];
context /* ref */;
}
''');
var block = findNode.expressionStatement('await').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_stringInterpolation_referenceAfter_awaitInStringInterpolation() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
'${await Future.value()}';
context /* ref */;
}
''');
var block = findNode.stringInterpolation('await').parent!.parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_switchExpression_referenceAfter_awaitInCaseBody() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
(switch (1) {
_ => await c(),
});
context /* ref */;
}
''');
var block = findNode.expressionStatement('switch').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_switchExpression_referenceAfter_awaitInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
(switch (await Future.value()) {
_ => null,
});
context /* ref */;
}
''');
var block = findNode.expressionStatement('switch').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_switchExpression_referenceInExpression_awaitInCondition() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
(switch (await Future.value()) {
_ => context /* ref */,
});
}
''');
var switchExpression = findNode.switchExpression('switch');
var reference = findNode.switchExpressionCase('context /* ref */');
expect(switchExpression.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_switchExpression_referenceInExpression_awaitInWhenClause() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
(switch (1) {
_ when await Future.value(true) => context /* ref */,
_ => null,
});
}
''');
var switchExpression = findNode.switchExpressionCase('await');
var reference = findNode.simple('context /* ref */');
expect(switchExpression.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_switchExpression_referenceInExpression_mountedGuardInWhenClause() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
(switch (1) {
_ when context.mounted => context /* ref */,
_ => null,
});
}
''');
var switchExpression = findNode.switchExpressionCase('when');
var reference = findNode.simple('context /* ref */');
expect(switchExpression.asyncStateFor(reference, contextElement),
AsyncState.mountedCheck);
}
test_switchExpression_referenceInWhenClause_awaitInExpression() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context, bool Function(BuildContext) condition) async {
(switch (1) {
_ when condition(context /* ref */) => await Future.value(),
_ => null,
});
}
''');
var switchExpression = findNode.switchExpressionCase('await');
var reference = findNode.whenClause('context /* ref */').parent!;
expect(switchExpression.asyncStateFor(reference, contextElement), isNull);
}
test_switchStatement_referenceAfter_awaitInCaseBody() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
switch (1) {
case 1:
await Future.value();
}
context /* ref */;
}
''');
var block = findNode.switchStatement('switch').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_switchStatement_referenceAfter_awaitInCaseWhen() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
switch (1) {
case 1 when await Future.value():
}
context /* ref */;
}
''');
var block = findNode.switchStatement('case').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_switchStatement_referenceAfter_awaitInDefault() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
switch (1) {
default:
await Future.value();
}
context /* ref */;
}
''');
var block = findNode.switchStatement('switch').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_switchStatement_referenceAfter_mountedCheckInCaseWhen() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
switch (1) {
case 1 when context.mounted:
}
context /* ref */;
}
''');
var block = findNode.switchStatement('case').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement), isNull);
}
test_switchStatement_referenceInCaseBody_awaitInCaseWhen() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
switch (1) {
case 1 when await Future.value():
context /* ref */;
}
}
''');
var switchStatement = findNode.switchStatement('switch');
var reference = findNode.switchPatternCase('context /* ref */');
expect(switchStatement.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_switchStatement_referenceInCaseBody_awaitInOtherCase() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
switch (1) {
case 1:
await Future.value();
case 2:
context /* ref */;
}
}
''');
var switchCase = findNode.switchStatement('switch');
var reference = findNode.switchPatternCase('context /* ref */');
expect(switchCase.asyncStateFor(reference, contextElement), isNull);
}
test_switchStatement_referenceInCaseBody_mountedCheckInCaseWhen() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
switch (1) {
case 1 when context.mounted:
context /* ref */;
}
}
''');
var switchStatement = findNode.switchStatement('switch');
var reference = findNode.switchPatternCase('context /* ref */');
expect(switchStatement.asyncStateFor(reference, contextElement),
AsyncState.mountedCheck);
}
test_switchStatement_referenceInCaseBody_mountedCheckInCaseWhen2() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
switch (1) {
case 1 when true:
case 2 when context.mounted:
context /* ref */;
}
}
''');
var switchCase = findNode.switchPatternCase('case 2');
var reference = findNode.expressionStatement('context /* ref */');
expect(switchCase.asyncStateFor(reference, contextElement), isNull);
}
test_switchStatement_referenceInCaseBody_mountedCheckInCaseWhen3() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
switch (1) {
case 1 when await Future.value(true):
case 2 when context.mounted:
context /* ref */;
}
}
''');
var switchStatement = findNode.switchStatement('switch');
var reference = findNode.switchPatternCase('context /* ref */');
expect(switchStatement.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_switchStatement_referenceInCaseBody_mountedCheckInCaseWhen4() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
switch (1) {
case 1 when context.mounted:
print(1);
case 2:
context /* ref */;
}
}
''');
var switchCase = findNode.switchPatternCase('case 2');
var reference = findNode.expressionStatement('context /* ref */');
expect(switchCase.asyncStateFor(reference, contextElement), isNull);
}
test_switchStatement_referenceInCaseWhen() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
switch (1) {
case 1 when context /* ref */:
await Future.value();
}
}
''');
var switchCase = findNode.switchPatternCase('case');
var reference = findNode.whenClause('context /* ref */').parent!;
expect(switchCase.asyncStateFor(reference, contextElement), isNull);
}
test_switchStatement_referenceInDefault_awaitInDefault() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
switch (1) {
default:
await Future.value();
context /* ref */;
}
}
''');
var switchStatement = findNode.switchDefault('await');
var reference = findNode.expressionStatement('context /* ref */');
expect(switchStatement.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_switchStatement_referenceInDefault_mountedGuardInDefault() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
switch (1) {
default:
if (!context.mounted) return;
context /* ref */;
}
}
''');
var switchStatement = findNode.switchDefault('context.mounted');
var reference = findNode.expressionStatement('context /* ref */');
expect(switchStatement.asyncStateFor(reference, contextElement),
AsyncState.notMountedCheck);
}
test_tryStatement_referenceAfter_awaitInBody() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
try {
await Future.value();
}
context /* ref */;
}
Future<void> c() async {}
''');
var block = findNode.tryStatement('try').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_tryStatement_referenceAfter_awaitInCatch() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
try {
} on Exception {
await Future.value();
}
context /* ref */;
}
Future<void> c() async {}
''');
var block = findNode.tryStatement('try').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_tryStatement_referenceAfter_awaitInFinally() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
try {
} finally {
await Future.value();
}
context /* ref */;
}
Future<void> c() async {}
''');
var block = findNode.tryStatement('try').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_tryStatement_referenceAfter_notMountedCheckInCatch() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
try {
} on Exception {
if (!context.mounted) return;
}
context /* ref */;
}
Future<void> c() async {}
''');
var block = findNode.tryStatement('try').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement), isNull);
}
test_tryStatement_referenceAfter_notMountedCheckInTry() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
try {
if (!context.mounted) return;
}
context /* ref */;
}
Future<void> c() async {}
''');
var block = findNode.tryStatement('try').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement), isNull);
}
test_tryStatement_referenceAfter_notMountedGuardInFinally() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
try {
} finally {
if (!context.mounted) return;
}
context /* ref */;
}
Future<void> c() async {}
''');
var block = findNode.tryStatement('try').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.notMountedCheck);
}
test_tryStatement_referenceInCatch_awaitInBody() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
try {
await Future.value();
} on Exception {
context /* ref */;
}
}
Future<void> c() async {}
''');
var tryStatement = findNode.tryStatement('try');
var reference = findNode.catchClause('context /* ref */');
expect(tryStatement.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_tryStatement_referenceInFinally_awaitInCatch() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
try {
} on Exception {
await Future.value();
} finally {
context /* ref */;
}
}
Future<void> c() async {}
''');
var tryStatement = findNode.tryStatement('try');
var reference = findNode.block('context /* ref */');
expect(tryStatement.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_whileStatement_referenceAfter_asyncInBody() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
while (true) {
await Future.value();
break;
}
context /* ref */;
}
''');
var block = findNode.whileStatement('while (').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_whileStatement_referenceInBody_asyncInBody() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
while (true) {
await Future.value();
context /* ref */;
}
}
''');
var whileStatement = findNode.whileStatement('while (');
var reference = findNode.block('context /* ref */');
expect(whileStatement.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_whileStatement_referenceInBody_asyncInBody2() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
while (true) {
context /* ref */;
await Future.value();
}
}
''');
var whileStatement = findNode.whileStatement('while (');
var reference = findNode.block('context /* ref */');
expect(whileStatement.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
test_yield_referenceAfter_asyncInExpression() async {
await resolveCode(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
yield (await Future.value());
context /* ref */;
}
''');
var block = findNode.yieldStatement('await').parent!;
var reference = findNode.expressionStatement('context /* ref */');
expect(block.asyncStateFor(reference, contextElement),
AsyncState.asynchronous);
}
}
@reflectiveTest
class UseBuildContextSynchronouslyTest extends LintRuleTest {
@override
bool get addFlutterPackageDep => true;
@override
String get lintRule => 'use_build_context_synchronously';
/// Ensure we're not run in the test dir.
@override
String get testPackageRootPath => '$workspaceRootPath/lib';
test_assignmentExpressionContainsMountedCheck_thenReferenceToContext() async {
// Assignment statement-expression with mounted check, then use of
// BuildContext in if-then statement, is REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
await c();
var m = context.mounted;
Navigator.of(context);
}
Future<void> c() async {}
''', [
lint(134, 7),
]);
}
test_async_thenMountedCheck_thenSwitchWithReferenceToContext() async {
// Assignment statement-expression with mounted check, then use of
// BuildContext in if-then statement, is REPORTED.
await assertNoDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
await c();
if (!context.mounted) return;
switch (1) {
case 1:
Navigator.of(context);
break;
}
}
Future<void> c() async {}
''');
}
test_async_thenSwitchWithReferenceToContext() async {
// Assignment statement-expression with mounted check, then use of
// BuildContext in if-then statement, is REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
await c();
switch (1) {
case 1:
Navigator.of(context);
break;
}
}
Future<void> c() async {}
''', [
lint(138, 7),
]);
}
test_await_afterReferenceToContext() async {
// Use of BuildContext, then await, in statement block is OK.
await assertNoDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
Navigator.of(context);
await f();
}
Future<void> f() async {}
''');
}
test_await_beforeReferenceToContext() async {
// Await, then use of BuildContext, in statement block is REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
await f();
Navigator.of(context);
}
Future<void> f() async {}
''', [
lint(107, 7),
]);
}
test_await_beforeReferenceToContext_inParens() async {
// Await, then use of BuildContext in parentheses, in statement block is
// REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
await f();
Navigator.of((context));
}
Future<void> f() async {}
''', [
lint(107, 9),
]);
}
test_await_beforeReferenceToContext_nullAsserted() async {
// Await, then use of null-asserted BuildContext, in statement block is
// REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext? context) async {
await f();
Navigator.of(context!);
}
Future<void> f() async {}
''', [
lint(108, 8),
]);
}
test_await_thenMountedGuard_thenReferenceToStateBuildContext() async {
// Await, then mounted guard, then reference to State.context, is REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
abstract class C extends State<StatefulWidget> {
void foo(BuildContext context) async {
await f();
if (context.mounted) return;
Navigator.of(this.context);
}
}
Future<void> f() async {}
''', [
lint(195, 12, messageContains: "an unrelated 'mounted' check"),
]);
}
test_await_thenNotMountedCheck_thenReferenceToContext() async {
// Await, then a `BuildContext.mounted` check, then use a local
// BuildContext, is OK.
await assertNoDiagnostics(r'''
import 'package:flutter/widgets.dart';
abstract class C extends State<StatefulWidget> {
void foo(BuildContext context) async {
await f();
if (!context.mounted) return;
Navigator.of(context);
}
}
Future<void> f() async {}
''');
}
test_await_thenNotMountedCheck_thenReferenceToStateContext() async {
// Await, then a `BuildContext.mounted` check, then use `State.context`, is
// REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
abstract class C extends State<StatefulWidget> {
void foo() async {
await f();
if (!context.mounted) return;
Navigator.of(context);
}
}
Future<void> f() async {}
''', [
lint(176, 7),
]);
}
test_await_thenNotMountedCheckInBinaryOr_thenReferenceToContext() async {
// Await, then a mounted check via early return with a binary or condition,
// then use of BuildContext, is OK.
await assertNoDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
await f();
if (1 == 2 || !context.mounted) return;
Navigator.of(context);
}
Future<void> f() async {}
''');
}
test_await_thenNotStateMountedCheck_thenReferenceToContext() async {
// Await, then a `State.mounted` check, then use a local BuildContext, is
// REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
abstract class C extends State<StatefulWidget> {
void foo(BuildContext context) async {
await f();
if (!mounted) return;
Navigator.of(context);
}
}
Future<void> f() async {}
''', [
lint(188, 7, messageContains: "an unrelated 'mounted' check"),
]);
}
test_await_thenNotStateMountedCheck_thenReferenceToStateContext() async {
// Await, then a `State.mounted` check, then use a local BuildContext, is
// OK.
await assertNoDiagnostics(r'''
import 'package:flutter/widgets.dart';
abstract class C extends State<StatefulWidget> {
void foo() async {
await f();
if (!mounted) return;
Navigator.of(context);
}
}
Future<void> f() async {}
''');
}
test_await_thenStateMountedGuard_thenReferenceToBuildContext() async {
// Await, then State.mounted guard, then reference to BuildContext, is
// REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
abstract class C extends State<StatefulWidget> {
void foo(BuildContext context) async {
await f();
if (this.mounted) return;
Navigator.of(context);
}
}
Future<void> f() async {}
''', [
lint(192, 7, messageContains: "an unrelated 'mounted' check"),
]);
}
test_awaitBeforeForBody_referenceToContext_thenMountedGuard() async {
// Await, then for-each statement, and inside the for-body: use of
// BuildContext, then mounted guard, is REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
await f();
for (var e in []) {
Navigator.of(context);
if (context.mounted) return;
}
}
Future<void> f() async {}
''', [
lint(131, 7),
]);
}
test_awaitBeforeIfStatement_withReferenceToContext() async {
// Await, then use of BuildContext in an unrelated if-body, is REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
var b = await c();
if (b) {
Navigator.of(context);
}
}
Future<bool> c() async => true;
''', [
lint(128, 7),
]);
}
test_awaitBeforeReferenceToContext_inClosure() async {
// Await, then use of BuildContext in a closure, is REPORTED.
// TODO(pq): what about closures?
await assertNoDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
await c();
f1(() {
f2(context);
});
}
void f1(Function f) {}
void f2(BuildContext c) {}
Future<bool> c() async => true;
''');
}
test_awaitBeforeWhileBody_referenceToContext_thenMountedGuard() async {
// Await, then While-true statement, and inside the while-body: use of
// BuildContext, then mounted guard, is REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
await f();
while (true) {
Navigator.of(context);
if (context.mounted) return;
}
}
Future<void> f() async {}
''', [
lint(126, 7),
]);
}
test_awaitInIfCondition_expressionContainsReferenceToContext() async {
// Await expression contains use of BuildContext, is OK.
await assertNoDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(
BuildContext context, Future<bool> Function(BuildContext) condition) async {
if (await condition(context)) {
return;
}
}
''');
}
test_awaitInIfThenAndExitInElse_beforeReferenceToContext() async {
// Await in an if-body and await-and-exit in the associated else, then use
// of BuildContext, is REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
if (1 == 2) {
await c();
} else {
await c();
return;
}
Navigator.of(context);
}
Future<bool> c() async => true;
''', [
lint(167, 7),
]);
}
/// https://github.com/dart-lang/linter/issues/3818
test_context_propertyAccess() async {
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
class W {
final BuildContext context;
W(this.context);
Future<void> f() async {
await Future.value();
g(this.context);
}
Future<void> g(BuildContext context) async {}
}
''', [
lint(159, 12),
]);
}
/// https://github.com/dart-lang/linter/issues/3676
test_contextPassedAsNamedParam() async {
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
Future<void> foo(BuildContext context) async {
await Future.value();
bar(context: context);
}
Future<void> bar({required BuildContext context}) async {}
''', [
lint(121, 16),
]);
}
test_future_catchError_referenceToContextInNamedArgument() async {
// `Future.catchError` call, with use of BuildContext inside, is REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context, Future<void> f) async {
f.catchError((_) {}, test: (_) {
Navigator.of(context);
return false;
});
}
''', [
lint(146, 7),
]);
}
test_future_catchError_referenceToContextInPositionalArgument() async {
// `Future.catchError` call, with use of BuildContext inside, is REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context, Future<void> f) async {
f.catchError((_) {
Navigator.of(context);
});
}
''', [
lint(132, 7),
]);
}
test_future_catchError_referenceToContextInPositionalArgument_precedingNamedArgument() async {
// `Future.catchError` call, with use of BuildContext inside, is REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context, Future<void> f) async {
f.catchError(test: (_) => false, (_) {
Navigator.of(context);
});
}
''', [
lint(152, 7),
]);
}
test_future_delayed_referenceToContextInWrongArgument() async {
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
Future.delayed((_) {
Navigator.of(context);
});
}
''', [
// Just don't crash when one argument references BuildContext, and not all
// positional arguments are given.
error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 95, 36),
]);
}
test_future_new_referenceToContextInArgument() async {
// `Future.new()` call, with use of BuildContext inside, is REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
Future.new(() {
Navigator.of(context);
});
}
''', [
lint(113, 7),
]);
}
test_future_then_noReferenceToContext() async {
// `Future.then` call, with no use of BuildContext inside, is OK.
await assertNoDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context, Future<void> f) async {
f.then((_) {});
}
''');
}
test_future_then_referenceToContextInCallback() async {
// `Future.then` call, with use of BuildContext inside, is REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context, Future<void> f) async {
f.then((_) {
Navigator.of(context);
});
}
''', [
lint(126, 7),
]);
}
test_future_then_referenceToContextInCallback_expressionBody() async {
// `Future.then` call, with use of BuildContext inside, is REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context, Future<void> f) async {
f.then((_) => Navigator.of(context));
}
''', [
lint(123, 7),
]);
}
test_future_then_referenceToContextInCallback_mountedGuard() async {
// `Future.then` call, with guarded use of BuildContext inside, is OK.
await assertNoDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context, Future<void> f) async {
f.then((_) {
if (!context.mounted) return;
Navigator.of(context);
});
}
''');
}
test_future_unnamed_referenceToContextInArgument() async {
// `Future()` call, with use of BuildContext inside, is REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
Future(() {
Navigator.of(context);
});
}
''', [
lint(109, 7),
]);
}
test_future_wait_referenceToContextInArgument() async {
// `Future.wait` call, with use of BuildContext inside, is REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
Future.wait([], cleanUp: (_) {
Navigator.of(context);
});
}
''', [
lint(128, 7),
]);
}
test_ifConditionContainsMountedAndReferenceToContext() async {
// Binary expression contains mounted check AND use of BuildContext, is
// OK.
await assertNoDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(
BuildContext context, bool Function(BuildContext) condition) async {
await c();
if (context.mounted && condition(context)) {
return;
}
}
Future<void> c() async {}
''');
}
test_ifConditionContainsMountedCheckInAssignmentLhs_thenReferenceToContext() async {
// If-condition contains assignment with mounted check on LHS, then use of
// BuildContext in if-then statement, is REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
await c();
if (A(context.mounted).b = false) {
Navigator.of(context);
}
}
class A {
bool b;
A(this.b);
}
Future<void> c() async {}
''', [
lint(147, 7),
]);
}
test_ifConditionContainsMountedOrReferenceToContext() async {
// Binary expression contains mounted check OR use of BuildContext, is
// REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(
BuildContext context, bool Function(BuildContext) condition) async {
await c();
if (context.mounted || condition(context)) {
return;
}
}
Future<void> c() async {}
''', [
lint(171, 7),
]);
}
test_ifConditionContainsNotMountedAndReferenceToContext() async {
// Binary expression contains not-mounted check AND use of BuildContext, is
// REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(
BuildContext context, bool Function(BuildContext) condition) async {
await c();
if (!context.mounted && condition(context)) {
return;
}
}
Future<void> c() async {}
''', [
lint(172, 7),
]);
}
test_noAwaitBefore_ifEmptyThen_methodInvocation() async {
await assertNoDiagnostics(r'''
import 'package:flutter/widgets.dart';
void f(BuildContext context) async {
if (true) {}
context.foo();
}
extension on BuildContext {
void foo() {}
}
''');
}
/// https://github.com/dart-lang/linter/issues/3700
test_propertyAccess_getter() async {
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
extension on BuildContext {
BuildContext get foo => this;
}
Future<void> f(BuildContext context) async {
await Future.value();
context.foo;
}
''', [
lint(174, 7),
]);
}
test_propertyAccess_setter() async {
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
extension on BuildContext {
set foo(int x){ }
}
Future<void> f(BuildContext context) async {
await Future.value();
context.foo = 1;
}
''', [
lint(162, 7),
]);
}
test_referenceToContextInAwait() async {
// An assignment expression, with an await, and use of BuildContext inside
// the await expression, is OK.
await assertNoDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
final x = await Future.value(context);
}
''');
}
test_referenceToContextInDoWhileBody_thenAwait() async {
// Do-while statement, and inside the do-while-body: use of BuildContext,
// then await, is REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
do {
Navigator.of(context);
await f();
} while (true);
}
Future<void> f() async {}
''', [
lint(103, 7),
]);
}
test_referenceToContextInForBody_thenAwait() async {
// For-each statement, and inside the for-body: use of BuildContext, then
// await, is REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
for (var e in []) {
Navigator.of(context);
await f();
}
}
Future<void> f() async {}
''', [
lint(118, 7),
]);
}
test_referenceToContextInFunctionExpression() async {
// Inside a function expression, await then use of BuildContext is REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
() async {
await f();
Navigator.of(context);
}();
}
Future<void> f() async {}
''', [
lint(124, 7),
]);
}
test_referenceToContextInWhileBody_thenAwait() async {
// While statement, and inside the while-body: use of BuildContext, then
// await, is REPORTED.
await assertDiagnostics(r'''
import 'package:flutter/widgets.dart';
void foo(BuildContext context) async {
while (true) {
Navigator.of(context);
await f();
}
}
Future<void> f() async {}
''', [
lint(113, 7),
]);
}
}
extension on AstNode {
AsyncState? asyncStateFor(AstNode reference, Element expressionElement) {
assert(
() {
if (reference.parent == this) return true;
return false;
}(),
"'reference' ($reference) (a ${reference.runtimeType}) (parent: "
'${reference.parent.runtimeType}) must be a '
"direct child of 'this' ($this) (a $runtimeType), or a sibling in a "
'list of AstNodes',
);
var mountedGetter = expressionElement.associatedMountedGetter!;
var asyncStateTracker = AsyncStateTracker();
return asyncStateTracker.asyncStateFor(reference, mountedGetter);
}
}