From e36d23d9278464ffa7644f7adf84b68fbcfb9701 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Wed, 19 Apr 2023 17:36:13 -0700 Subject: [PATCH] Move use_key_in_widget_constructors tests to be reflective --- test/rule_test_support.dart | 31 +++- test/rules/all.dart | 3 + .../use_key_in_widget_constructors_test.dart | 156 ++++++++++++++++++ .../super_parameters/analysis_options.yaml | 3 - .../super_parameters/rules/.mock_packages | 1 - .../rules/use_key_in_widget_constructors.dart | 22 --- .../rules/use_key_in_widget_constructors.dart | 29 ---- 7 files changed, 189 insertions(+), 56 deletions(-) create mode 100644 test/rules/use_key_in_widget_constructors_test.dart delete mode 100644 test_data/rules/experiments/super_parameters/analysis_options.yaml delete mode 100644 test_data/rules/experiments/super_parameters/rules/.mock_packages delete mode 100644 test_data/rules/experiments/super_parameters/rules/use_key_in_widget_constructors.dart delete mode 100644 test_data/rules/use_key_in_widget_constructors.dart diff --git a/test/rule_test_support.dart b/test/rule_test_support.dart index 677a3d208..a8fb0e59b 100644 --- a/test/rule_test_support.dart +++ b/test/rule_test_support.dart @@ -469,6 +469,14 @@ abstract class BuildContext { bool get mounted; } +class Container extends StatelessWidget { + const Container({super.key}); +} + +class Key { + Key(String value); +} + class Navigator { static NavigatorState of( BuildContext context, {bool rootNavigator = false}) => NavigatorState(); @@ -476,7 +484,28 @@ class Navigator { class NavigatorState {} -class Widget {} +abstract class StatefulWidget extends Widget { + const StatefulWidget({super.key}); +} + +abstract class Widget { + final Key? key; + + const Widget({thi.key}); +} + +abstract class StatelessWidget extends Widget { + const StatelessWidget({super.key}); + + @protected + Widget build(BuildContext context); +} + +abstract class Widget { + final Key? key; + + const Widget({thi.key}); +} '''); } } diff --git a/test/rules/all.dart b/test/rules/all.dart index 28c21d793..96c7e2041 100644 --- a/test/rules/all.dart +++ b/test/rules/all.dart @@ -133,6 +133,8 @@ import 'use_build_context_synchronously_test.dart' import 'use_enums_test.dart' as use_enums; import 'use_is_even_rather_than_modulo_test.dart' as use_is_even_rather_than_modulo; +import 'use_key_in_widget_constructors_test.dart' + as use_key_in_widget_constructors; import 'use_late_for_private_fields_and_variables_test.dart' as use_late_for_private_fields_and_variables; import 'use_named_constants_test.dart' as use_named_constants; @@ -236,6 +238,7 @@ void main() { use_build_context_synchronously.main(); use_enums.main(); use_is_even_rather_than_modulo.main(); + use_key_in_widget_constructors.main(); use_late_for_private_fields_and_variables.main(); use_named_constants.main(); use_super_parameters.main(); diff --git a/test/rules/use_key_in_widget_constructors_test.dart b/test/rules/use_key_in_widget_constructors_test.dart new file mode 100644 index 000000000..8977bdc11 --- /dev/null +++ b/test/rules/use_key_in_widget_constructors_test.dart @@ -0,0 +1,156 @@ +// Copyright (c) 2023, 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:test_reflective_loader/test_reflective_loader.dart'; + +import '../rule_test_support.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(UseKeyInWidgetConstructorsTest); + }); +} + +@reflectiveTest +class UseKeyInWidgetConstructorsTest extends LintRuleTest { + @override + bool get addFlutterPackageDep => true; + + @override + String get lintRule => 'use_key_in_widget_constructors'; + + test_constNamedConstructor_missingKey() async { + await assertDiagnostics(r''' +import 'package:flutter/widgets.dart'; + +abstract class MyWidget extends StatelessWidget { + const MyWidget.named(); +} +''', [ + lint(107, 5), + ]); + } + + test_constUnnamedConstructor_missingKey() async { + await assertDiagnostics(r''' +import 'package:flutter/widgets.dart'; + +abstract class MyWidget extends StatelessWidget { + const MyWidget(); +} +''', [ + lint(98, 8), + ]); + } + + test_factoryConstructor() async { + await assertNoDiagnostics(r''' +import 'package:flutter/widgets.dart'; + +class MyWidget extends StatelessWidget { + MyWidget({super.key}); + factory MyWidget.fact() => MyWidget(); + @override + Widget build(BuildContext context) => Container(); +} +'''); + } + + test_missingConstructor() async { + await assertDiagnostics(r''' +import 'package:flutter/widgets.dart'; + +class NoConstructorWidget extends StatefulWidget {} +''', [ + lint(46, 19), + ]); + } + + test_missingKey() async { + await assertDiagnostics(r''' +import 'package:flutter/widgets.dart'; + +abstract class MyWidget extends StatelessWidget { + MyWidget(); +} +''', [ + lint(92, 8), + ]); + } + + test_missingKey_keyPassedToSuper() async { + await assertNoDiagnostics(r''' +import 'package:flutter/widgets.dart'; + +abstract class MyWidget extends StatelessWidget { + MyWidget.superCall() : super(key: Key('')); +} +'''); + } + + test_privateClass() async { + await assertNoDiagnostics(r''' +import 'package:flutter/widgets.dart'; + +// ignore: unused_element +class _PrivateWidget extends StatefulWidget {} +'''); + } + + test_privateConstructor() async { + await assertNoDiagnostics(r''' +import 'package:flutter/widgets.dart'; + +abstract class MyWidget extends StatelessWidget { + MyWidget._private(); +} +'''); + } + + test_redirectingConstructor_withKey() async { + await assertNoDiagnostics(r''' +import 'package:flutter/widgets.dart'; + +abstract class MyWidget extends StatelessWidget { + MyWidget.redirect() : this.withKey(key: Key('')); + MyWidget.withKey({Key? key}) : super(key: key ?? Key('')); +} +'''); + } + + test_simpleFormalParameter_notPassedToSuper() async { + await assertDiagnostics(r''' +import 'package:flutter/widgets.dart'; + +abstract class MyWidget extends StatelessWidget { + MyWidget.withKey({Key? key}); +} +''', [ + lint(101, 7), + ]); + } + + test_simpleFormalParameter_passedToSuper() async { + await assertNoDiagnostics(r''' +import 'package:flutter/widgets.dart'; + +abstract class MyWidget extends StatelessWidget { + MyWidget.withKey({Key? key}) : super(key: key ?? Key('')); +} +'''); + } + + test_superParameter() async { + await assertNoDiagnostics(r''' +import 'package:flutter/widgets.dart'; + +class OtherWidget extends StatelessWidget { + const OtherWidget({required super.key}); + + @override + Widget build(BuildContext context) => Container(); +} +'''); + } +} diff --git a/test_data/rules/experiments/super_parameters/analysis_options.yaml b/test_data/rules/experiments/super_parameters/analysis_options.yaml deleted file mode 100644 index 16dd3805f..000000000 --- a/test_data/rules/experiments/super_parameters/analysis_options.yaml +++ /dev/null @@ -1,3 +0,0 @@ -analyzer: - enable-experiment: - - super-parameters diff --git a/test_data/rules/experiments/super_parameters/rules/.mock_packages b/test_data/rules/experiments/super_parameters/rules/.mock_packages deleted file mode 100644 index 236a8a870..000000000 --- a/test_data/rules/experiments/super_parameters/rules/.mock_packages +++ /dev/null @@ -1 +0,0 @@ -flutter:../../../../mock_packages/flutter/lib/ diff --git a/test_data/rules/experiments/super_parameters/rules/use_key_in_widget_constructors.dart b/test_data/rules/experiments/super_parameters/rules/use_key_in_widget_constructors.dart deleted file mode 100644 index 66e7a1252..000000000 --- a/test_data/rules/experiments/super_parameters/rules/use_key_in_widget_constructors.dart +++ /dev/null @@ -1,22 +0,0 @@ -// 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. - -// test w/ `dart test -N use_key_in_widget_constructors` - -// todo(pq): re-enable (or migrate) when mocked Flutter packages can be resolved internally -// see: https://github.com/dart-lang/linter/issues/3296 - -// import 'package:flutter/foundation.dart'; -// import 'package:flutter/widgets.dart'; -// -// /// https://github.com/flutter/flutter/issues/100297 -// class OtherWidget extends StatelessWidget { -// const OtherWidget({required super.key}); //OK -// -// @override -// Widget build(BuildContext context) { -// return Container(); -// } -// } - diff --git a/test_data/rules/use_key_in_widget_constructors.dart b/test_data/rules/use_key_in_widget_constructors.dart deleted file mode 100644 index 6de5e8c1e..000000000 --- a/test_data/rules/use_key_in_widget_constructors.dart +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2019, 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. - -// test w/ `dart test -N use_key_in_widget_constructors` - -import 'package:flutter/foundation.dart'; -import 'package:flutter/widgets.dart'; - -class NoConstructorWidget extends StatefulWidget { // LINT -} - -class _PrivateWidget extends StatefulWidget { // OK -} - -class MyWidget extends StatelessWidget { - MyWidget(); // LINT - MyWidget.withKey({Key? key}) : super(key: key ?? Key('')); // OK - MyWidget.withUnusedKey({Key? key}); // LINT - factory MyWidget.fact() => MyWidget(); // OK - MyWidget._private(); // OK - MyWidget.redirect() : this.withKey(key: Key('')); // OK - MyWidget.superCall() : super(key: Key('')); // OK -} - -class ConstWidget extends StatelessWidget { - const ConstWidget(); // LINT [9:11] - const ConstWidget.named(); // LINT [21:5] -}