From 0b41ef13e55f882d9743f090e3fe937de404649b Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Mon, 11 Nov 2024 22:29:00 +0000 Subject: [PATCH] lint rules: Migrate tests for two rules: * unawaited_futures * void_checks Change-Id: I7746c3f66d178a84fc8996dac09d53efc664d14a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/394560 Reviewed-by: Phil Quitslund Commit-Queue: Phil Quitslund Auto-Submit: Samuel Rawlins --- .../test/rules/unawaited_futures_test.dart | 122 +++++++++++++ pkg/linter/test/rules/void_checks_test.dart | 161 ++++++++++++++++++ .../test_data/rules/unawaited_futures.dart | 100 ----------- pkg/linter/test_data/rules/void_checks.dart | 158 ----------------- 4 files changed, 283 insertions(+), 258 deletions(-) delete mode 100644 pkg/linter/test_data/rules/unawaited_futures.dart delete mode 100644 pkg/linter/test_data/rules/void_checks.dart diff --git a/pkg/linter/test/rules/unawaited_futures_test.dart b/pkg/linter/test/rules/unawaited_futures_test.dart index a5020e94a228..46c07ca095ae 100644 --- a/pkg/linter/test/rules/unawaited_futures_test.dart +++ b/pkg/linter/test/rules/unawaited_futures_test.dart @@ -17,6 +17,128 @@ class UnawaitedFuturesTest extends LintRuleTest { @override String get lintRule => LintNames.unawaited_futures; + test_classImplementsFuture() async { + // https://github.com/dart-lang/linter/issues/2211 + await assertDiagnostics(r''' +void f(Future2 p) async { + g(p); +} +Future2 g(Future2 p) => p; +abstract class Future2 implements Future {} +''', [ + lint(28, 5), + ]); + } + + test_functionCall_assigned() async { + await assertNoDiagnostics(r''' +Future f() async { + var x = g(); + return x; +} +Future g() => Future.value(0); +'''); + } + + test_functionCall_awaited() async { + await assertNoDiagnostics(r''' +void f() async { + await g(); +} +Future g() => Future.value(0); +'''); + } + + test_functionCall_inListContext() async { + await assertNoDiagnostics(r''' +void f() async { + var x = [g()]; + x..[0] = g(); +} +Future g() => Future.value(0); +'''); + } + + test_functionCall_interpolated_unawaited() async { + await assertDiagnostics(r''' +void f() async { + '${g()}'; +} +Future g() => Future.value(0); +''', [ + lint(22, 3), + ]); + } + + test_functionCall_returnedWithFutureType() async { + await assertNoDiagnostics(r''' +void f() async { + {}.putIfAbsent('foo', () => g()); +} +Future g() => Future.value(0); +'''); + } + + test_functionCall_unawaited() async { + await assertDiagnostics(r''' +void f() async { + g(); +} +Future g() => Future.value(0); +''', [ + lint(19, 4), + ]); + } + + test_functionCallInCascade_assignment() async { + await assertNoDiagnostics(r''' +void f() async { + C()..futureField = g(); +} +Future g() => Future.value(0); +class C { + Future? futureField; +} +'''); + } + + test_functionCallInCascade_inAsync() async { + await assertDiagnostics(r''' +void f() async { + C()..doAsync(); +} +class C { + Future doAsync() async {} +} +''', [ + lint(22, 11), + ]); + } + + test_functionCallInCascade_indexAssignment() async { + await assertNoDiagnostics(r''' +void f() async { + C() + ..x?[0] = g(); +} +Future g() => Future.value(0); +class C { + List>? x = []; +} +'''); + } + + test_functionCallInCascade_inSync() async { + await assertNoDiagnostics(r''' +void foo() { + C()..doAsync(); +} +class C { + Future doAsync() async {} +} +'''); + } + test_undefinedIdentifier() async { await assertDiagnostics(r''' f() async { diff --git a/pkg/linter/test/rules/void_checks_test.dart b/pkg/linter/test/rules/void_checks_test.dart index a6067da79745..5485e8c58f1b 100644 --- a/pkg/linter/test/rules/void_checks_test.dart +++ b/pkg/linter/test/rules/void_checks_test.dart @@ -17,6 +17,16 @@ class VoidChecksTest extends LintRuleTest { @override String get lintRule => LintNames.void_checks; + test_assert_blockBody_returnStatement() async { + await assertNoDiagnostics(r''' +void f() { + assert(() { + return true; + }()); +} +'''); + } + test_constructorArgument_genericParameter() async { await assertDiagnostics(r''' void f(dynamic p) { @@ -126,6 +136,28 @@ void m([void v]) {} ]); } + test_functionExpression_blockBody_returnStatement_genericContext() async { + await assertNoDiagnostics(r''' +generics_with_function() { + g(T Function() p) => p(); + g(() { + return 1; + }); +} +'''); + } + + test_functionExpression_blockBody_returnStatement_voidContext() async { + await assertNoDiagnostics(r''' +void f() { + void g(Function p) {} + g(() async { + return 1; + }); +} +'''); + } + // https://github.com/dart-lang/linter/issues/2685 test_functionType_FutureOrVoidReturnType_Never() async { await assertNoDiagnostics(r''' @@ -168,6 +200,93 @@ void f() { '''); } + test_futureOrVoidField_assignDynamic() async { + await assertNoDiagnostics(r''' +import 'dart:async'; +void f(A a, dynamic p) { + a.x = p; // OK +} +class A { + FutureOr x; + A(this.x); +} +'''); + } + + test_futureOrVoidField_assignFutureOrVoid() async { + await assertNoDiagnostics(r''' +import 'dart:async'; +void f(A a, FutureOr p) { + a.x = p; +} +class A { + FutureOr x; + A(this.x); +} +'''); + } + + test_futureOrVoidField_assignFutureVoid() async { + await assertNoDiagnostics(r''' +import 'dart:async'; +void f(A a) { + a.x = Future.value(); +} +class A { + FutureOr x; + A(this.x); +} +'''); + } + + test_futureOrVoidField_assignInt() async { + await assertDiagnostics(r''' +import 'dart:async'; +void f(A a) { + a.x = 1; +} +class A { + FutureOr x; + A(this.x); +} +''', [ + lint(37, 7), + ]); + } + + test_futureOrVoidField_assignNull() async { + await assertNoDiagnostics(r''' +import 'dart:async'; +void f(A a) { + a.x = null; // OK +} +class A { + FutureOr x; + A(this.x); +} +'''); + } + + test_futureOrVoidFunction_blockBody_returnsFuture() async { + await assertNoDiagnostics(r''' +import 'dart:async'; +FutureOr f() { + return Future.value(); +} +'''); + } + + test_futureOrVoidFunction_blockBody_returnStatement() async { + await assertDiagnostics(r''' +import 'dart:async'; +FutureOr f() { + return 1; +} +''', [ + lint(44, 9), + ]); + } + test_listPattern_local() async { await assertDiagnostics(r''' void f() { @@ -190,6 +309,15 @@ void f(void p) { ]); } + test_localFunction_emptyBlockBody_matchingFutureOrVoidSignature() async { + await assertNoDiagnostics(r''' +import 'dart:async'; +void f(FutureOr Function() p) { + p = () {}; +} +'''); + } + test_neverReturningCallbackThrows() async { await assertNoDiagnostics(r''' import 'dart:async'; @@ -204,6 +332,15 @@ void f() async { '''); } + test_nonVoidFunction_assignedToVoidFunction() async { + await assertNoDiagnostics(r''' +void f(void Function() p) { + int g() => 1; + p = g; +} +'''); + } + test_recordPattern() async { await assertDiagnostics(r''' void f(void p) { @@ -260,4 +397,28 @@ class A { lint(33, 7), ]); } + + test_voidFunction_blockBody_returnStatement() async { + await assertDiagnostics(r''' +void f(dynamic p) { + return p; +} +''', [ + lint(22, 9), + ]); + } + + test_voidFunction_blockBody_returnStatement_empty() async { + await assertNoDiagnostics(r''' +void f() { + return; +} +'''); + } + + test_voidFunction_expressionBody() async { + await assertNoDiagnostics(r''' +void f() => 7; +'''); + } } diff --git a/pkg/linter/test_data/rules/unawaited_futures.dart b/pkg/linter/test_data/rules/unawaited_futures.dart deleted file mode 100644 index ce0e420e0d77..000000000000 --- a/pkg/linter/test_data/rules/unawaited_futures.dart +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) 2016, 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 'dart:async'; - -Future fut() => Future.value(0); - -foo1() { - fut(); -} - -foo2() async { - fut(); //LINT - - // ignore: unawaited_futures - fut(); -} - -foo3() async { - await fut(); -} - -foo4() async { - var x = fut(); - return x; -} - -foo5() async { - Duration d = Duration(); - new Future.delayed(d); //LINT -} - -foo6() async { - var map = {}; - map.putIfAbsent('foo', () => fut()); -} - -foo7() async { - _Foo() - ..doAsync() //LINT - ..doSync(); -} - -foo8() { - // Fire and forget should not be reported per existing functionality - _Foo() - ..doAsync() - ..doSync(); -} - -foo9() async { - _Foo() - ..futureField = fut(); -} - -foo10() async { - _Foo() - ..futureListField?[0] = fut(); -} - -foo11() async { - _Foo() - ..bar?.futureField = fut(); -} - -foo12() async { - final x = [fut()]; - x..[0] = fut(); -} - -foo13() async { - var y = '${fut()}'; //LINT -} - -class _Bar { - Future? futureField; -} - -class _Foo { - Future? futureField; - List>? futureListField = []; - _Bar? bar; - Future doAsync() async {} - void doSync() => null; - Future get asyncProperty => doAsync(); - List> get futures => [doAsync()]; -} - -/// https://github.com/dart-lang/linter/issues/2211 -class Future2 implements Future { - @override - noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); -} - -Future2 fut2() => Future2(); - -f2() async { - fut2(); //LINT -} diff --git a/pkg/linter/test_data/rules/void_checks.dart b/pkg/linter/test_data/rules/void_checks.dart deleted file mode 100644 index 901c1a6a2097..000000000000 --- a/pkg/linter/test_data/rules/void_checks.dart +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright (c) 2018, 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. - -// ignore_for_file: unused_local_variable - -import 'dart:async'; - -Never fail() { throw 'nope'; } - -var x; - -class A { - late T value; - A(); - A.c(this.value); - void m1(T arg) {} - void m4(void arg) {} - T m5(e) => throw ''; -} - -void use_setter_with_futureOr_void_parameter() { - final a = new A>(); - // it's OK to pass Future or FutureOr to set value - a.value = new Future.value(); //OK - FutureOr fo; - a.value = fo; // OK - a.value = x; // OK - a.value = null; // OK - a.value = 1; // LINT -} - -void return_inside_block_function_body() { - return x; // LINT -} - -void simple_return_inside_block_function_body() { - return; // OK -} - -void return_from_expression_function_body() => x; // OK - -FutureOr return_value_for_futureOr() { - return 1; // LINT -} - -FutureOr return_future_for_futureOr() { - return new Future.value(); // OK -} - -FutureOr return_futureOr_for_futureOr() { - return x; // OK -} - -void assert_is_void_function_is_ok() { - assert(() { - return true; // OK - }()); -} - -async_function() { - void f(Function f) {} - f(() //OK - async { - return 1; // OK - }); -} - -inference() { - f(void Function() f) {} -} - -generics_with_function() { - f(T Function() f) => f(); - f(() // OK - { - return 1; - }); -} - -/// function ref are similar to expression function body with void return type -function_ref_are_ok() { - fA(void Function(dynamic) f) {} - fB({required void Function(dynamic) f}) {} - - void Function(Object? e) f1 = (e) {}; - fA(f1); // OK - final f2 = (e) {}; - fA(f2); // OK - final f3 = (e) => 1; - fA(f3); // OK - final a1 = new A(); - fA(a1.m5); // OK - fB(f: a1.m5); // OK - final a2 = new A(); - fA(a2.m5); // OK -} - -allow_functionWithReturnType_forFunctionWithout() { - takeVoidFn(void Function() f) {} - void Function() voidFn; - - int nonVoidFn() => 1; - - takeVoidFn(nonVoidFn); // OK - voidFn = nonVoidFn; // OK - void Function() returnsVoidFn() { - return nonVoidFn; // OK - } - returnsVoidFn(); -} - -allow_functionWithReturnType_forFunctionWithout_asComplexExpr() { - takeVoidFn(void Function() f) {} - void Function() voidFn; - - List listNonVoidFn = []; - - takeVoidFn(listNonVoidFn[0]); // OK - voidFn = listNonVoidFn[0]; // OK - void Function() returnsVoidFn() { - return listNonVoidFn[0]; // OK - } - returnsVoidFn(); -} - -allow_Null_for_void() { - forget(void Function() f) {} - - forget(() {}); // OK - - void Function() f; - f = () {}; // OK -} - -allow_Future_void_for_void() { - forget(void Function() f) {} - - forget(() async {}); // OK - - void Function() f; - f = () async {}; // OK -} - -allow_expression_function_body() { - forget(void Function() f) {} - int i = 0; - forget(() => i); // OK - forget(() => i++); // OK - - void Function() f; - f = () => i; // OK - f = () => i++; // OK -} - -void emptyFunctionExpressionReturningFutureOrVoid(FutureOr Function() f) { - f = () {}; // OK -}