From 7c8345c39f145d40bb800e0aace28becbaec5e4e Mon Sep 17 00:00:00 2001 From: pq Date: Fri, 26 May 2023 13:31:02 -0700 Subject: [PATCH 1/6] + no_wildcard_variable_uses --- example/all.yaml | 1 + lib/src/rules.dart | 2 + lib/src/rules/no_wildcard_variable_uses.dart | 79 +++++++++++++++++++ test/rules/all.dart | 2 + .../rules/no_wildcard_variable_uses_test.dart | 48 +++++++++++ 5 files changed, 132 insertions(+) create mode 100644 lib/src/rules/no_wildcard_variable_uses.dart create mode 100644 test/rules/no_wildcard_variable_uses_test.dart diff --git a/example/all.yaml b/example/all.yaml index 922888a1e..ed5871463 100644 --- a/example/all.yaml +++ b/example/all.yaml @@ -100,6 +100,7 @@ linter: - no_runtimeType_toString - no_self_assignments - non_constant_identifier_names + - no_wildcard_variable_uses - noop_primitive_operations - null_check_on_nullable_type_parameter - null_closures diff --git a/lib/src/rules.dart b/lib/src/rules.dart index 90a41213d..6d027f6e4 100644 --- a/lib/src/rules.dart +++ b/lib/src/rules.dart @@ -108,6 +108,7 @@ import 'rules/no_literal_bool_comparisons.dart'; import 'rules/no_logic_in_create_state.dart'; import 'rules/no_runtimeType_toString.dart'; import 'rules/no_self_assignments.dart'; +import 'rules/no_wildcard_variable_uses.dart'; import 'rules/non_constant_identifier_names.dart'; import 'rules/noop_primitive_operations.dart'; import 'rules/null_check_on_nullable_type_parameter.dart'; @@ -341,6 +342,7 @@ void registerLintRules({bool inTestMode = false}) { ..register(NoopPrimitiveOperations()) ..register(NoRuntimeTypeToString()) ..register(NoSelfAssignments()) + ..register(NoWildcardVariableUses()) ..register(NullCheckOnNullableTypeParameter()) ..register(NullClosures()) ..register(OmitLocalVariableTypes()) diff --git a/lib/src/rules/no_wildcard_variable_uses.dart b/lib/src/rules/no_wildcard_variable_uses.dart new file mode 100644 index 000000000..d61d6816c --- /dev/null +++ b/lib/src/rules/no_wildcard_variable_uses.dart @@ -0,0 +1,79 @@ +// 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:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/dart/ast/visitor.dart'; + +import '../analyzer.dart'; +import '../util/ascii_utils.dart'; + +const _desc = r"Don't use wildcard parameters or variables."; + +const _details = r''' +**DON'T** use wildcard parameters or variables. + +In a future version of the Dart langauge, wildcard parameters and local +variables (e.g., named with just underscores like `_`, `__`, `___`, etc.) will +become non-binding. When that happens, existing code that uses wildcard +parameters or variables will break. In anticipation and to make adoption +easier, this lint disallows wildcard and variable parameter uses. + + +**BAD:** +```dart +var _ = 1; +print(_); // LINT +``` + +```dart +void f(int __) { + print(__); // LINT multiple underscores too +} +``` + +**GOOD:** +```dart +for (var _ in [1, 2, 3]) count++; +``` + +```dart +var [a, _, b, _] = [1, 2, 3, 4]; +``` +'''; + +class NoWildcardVariableUses extends LintRule { + static const LintCode code = LintCode( + 'no_wildcard_variable_uses', 'The referenced identifier is a wildcard.', + correctionMessage: 'Use an identifier name that is not a wildcard.'); + + NoWildcardVariableUses() + : super( + name: 'no_wildcard_variable_uses', + description: _desc, + details: _details, + group: Group.errors); + + @override + LintCode get lintCode => code; + + @override + void registerNodeProcessors( + NodeLintRegistry registry, LinterContext context) { + var visitor = _Visitor(this); + registry.addSimpleIdentifier(this, visitor); + } +} + +class _Visitor extends SimpleAstVisitor { + final LintRule rule; + + _Visitor(this.rule); + + @override + void visitSimpleIdentifier(SimpleIdentifier node) { + if (node.name.isJustUnderscores) { + rule.reportLint(node); + } + } +} diff --git a/test/rules/all.dart b/test/rules/all.dart index 60e493519..bad6a6426 100644 --- a/test/rules/all.dart +++ b/test/rules/all.dart @@ -71,6 +71,7 @@ import 'no_duplicate_case_values_test.dart' as no_duplicate_case_values; import 'no_leading_underscores_for_local_identifiers_test.dart' as no_leading_underscores_for_local_identifiers; import 'no_self_assignments_test.dart' as no_self_assignments; +import 'no_wildcard_variable_uses_test.dart' as no_wildcard_variable_uses; import 'non_adjacent_strings_in_list_test.dart' as no_adjacent_strings_in_list; import 'non_constant_identifier_names_test.dart' as non_constant_identifier_names; @@ -202,6 +203,7 @@ void main() { no_duplicate_case_values.main(); no_leading_underscores_for_local_identifiers.main(); no_self_assignments.main(); + no_wildcard_variable_uses.main(); non_constant_identifier_names.main(); null_check_on_nullable_type_parameter.main(); null_closures.main(); diff --git a/test/rules/no_wildcard_variable_uses_test.dart b/test/rules/no_wildcard_variable_uses_test.dart new file mode 100644 index 000000000..198495880 --- /dev/null +++ b/test/rules/no_wildcard_variable_uses_test.dart @@ -0,0 +1,48 @@ +// 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(NoWildcardVariableUsesTest); + }); +} + +@reflectiveTest +class NoWildcardVariableUsesTest extends LintRuleTest { + @override + String get lintRule => 'no_wildcard_variable_uses'; + + test_declaredIdentifier() async { + await assertNoDiagnostics(r''' +f() { + for (var _ in [1, 2, 3]) ; +} +'''); + } + + test_localVar() async { + await assertDiagnostics(r''' +f() { + var _ = 1; + print(_); +} +''', [ + lint(27, 1), + ]); + } + + test_param() async { + await assertDiagnostics(r''' +f(int __) { + print(__); +} +''', [ + lint(20, 2), + ]); + } +} From 71d1d391bb91f4477d0dc264a1f86191fe907ab0 Mon Sep 17 00:00:00 2001 From: pq Date: Fri, 26 May 2023 13:40:20 -0700 Subject: [PATCH 2/6] sort --- example/all.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/all.yaml b/example/all.yaml index ed5871463..63510240e 100644 --- a/example/all.yaml +++ b/example/all.yaml @@ -99,8 +99,8 @@ linter: - no_logic_in_create_state - no_runtimeType_toString - no_self_assignments - - non_constant_identifier_names - no_wildcard_variable_uses + - non_constant_identifier_names - noop_primitive_operations - null_check_on_nullable_type_parameter - null_closures From 4f1da04421e0357e23af05f191e0ab272ad164e3 Mon Sep 17 00:00:00 2001 From: pq Date: Fri, 26 May 2023 14:02:56 -0700 Subject: [PATCH 3/6] skip executable elements --- lib/src/rules/no_wildcard_variable_uses.dart | 3 + .../rules/no_wildcard_variable_uses_test.dart | 66 +++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/lib/src/rules/no_wildcard_variable_uses.dart b/lib/src/rules/no_wildcard_variable_uses.dart index d61d6816c..40923a2fe 100644 --- a/lib/src/rules/no_wildcard_variable_uses.dart +++ b/lib/src/rules/no_wildcard_variable_uses.dart @@ -4,6 +4,7 @@ import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/visitor.dart'; +import 'package:analyzer/dart/element/element.dart'; import '../analyzer.dart'; import '../util/ascii_utils.dart'; @@ -72,6 +73,8 @@ class _Visitor extends SimpleAstVisitor { @override void visitSimpleIdentifier(SimpleIdentifier node) { + if (node.staticElement is ExecutableElement) return; + if (node.name.isJustUnderscores) { rule.reportLint(node); } diff --git a/test/rules/no_wildcard_variable_uses_test.dart b/test/rules/no_wildcard_variable_uses_test.dart index 198495880..b9ace8f55 100644 --- a/test/rules/no_wildcard_variable_uses_test.dart +++ b/test/rules/no_wildcard_variable_uses_test.dart @@ -17,6 +17,17 @@ class NoWildcardVariableUsesTest extends LintRuleTest { @override String get lintRule => 'no_wildcard_variable_uses'; + test_constructor() async { + await assertNoDiagnostics(r''' +class C { + C._(); + m() { + print(C._); + } +} +'''); + } + test_declaredIdentifier() async { await assertNoDiagnostics(r''' f() { @@ -25,6 +36,28 @@ f() { '''); } + test_field() async { + await assertNoDiagnostics(r''' +class C { + int _ = 0; + m() { + print(_); + } +} +'''); + } + + test_getter() async { + await assertNoDiagnostics(r''' +class C { + int get _ => 0; + m() { + print(_); + } +} +'''); + } + test_localVar() async { await assertDiagnostics(r''' f() { @@ -36,6 +69,18 @@ f() { ]); } + test_method() async { + await assertNoDiagnostics(r''' +class C { + String _() => ''; + m() { + print(_); + print(_()); + } +} +'''); + } + test_param() async { await assertDiagnostics(r''' f(int __) { @@ -45,4 +90,25 @@ f(int __) { lint(20, 2), ]); } + + test_topLevelFunction() async { + await assertNoDiagnostics(r''' +String _() => ''; + +f() { + print(_); + print(_()); +} +'''); + } + + test_topLevelGetter() async { + await assertNoDiagnostics(r''' +int get _ => 0; + +f() { + print(_); +} +'''); + } } From 79cb838960f83f7ac896b44f5b4ccc25300a497f Mon Sep 17 00:00:00 2001 From: pq Date: Fri, 26 May 2023 14:04:27 -0700 Subject: [PATCH 4/6] ++ --- test/rules/no_wildcard_variable_uses_test.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/test/rules/no_wildcard_variable_uses_test.dart b/test/rules/no_wildcard_variable_uses_test.dart index b9ace8f55..808664d28 100644 --- a/test/rules/no_wildcard_variable_uses_test.dart +++ b/test/rules/no_wildcard_variable_uses_test.dart @@ -23,6 +23,7 @@ class C { C._(); m() { print(C._); + print(C._()); } } '''); From 07f40d7dcd0c4e29a1d41c6db48d2742bc2dca41 Mon Sep 17 00:00:00 2001 From: pq Date: Fri, 26 May 2023 14:08:47 -0700 Subject: [PATCH 5/6] ++ --- lib/src/rules/no_wildcard_variable_uses.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/src/rules/no_wildcard_variable_uses.dart b/lib/src/rules/no_wildcard_variable_uses.dart index 40923a2fe..e715e54ac 100644 --- a/lib/src/rules/no_wildcard_variable_uses.dart +++ b/lib/src/rules/no_wildcard_variable_uses.dart @@ -73,7 +73,10 @@ class _Visitor extends SimpleAstVisitor { @override void visitSimpleIdentifier(SimpleIdentifier node) { - if (node.staticElement is ExecutableElement) return; + var element = node.staticElement; + if (element is! LocalVariableElement && element is! ParameterElement) { + return; + } if (node.name.isJustUnderscores) { rule.reportLint(node); From 17d0582bf3c9c8cc23ddf814867c9637679dccd9 Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Tue, 30 May 2023 09:18:16 -0700 Subject: [PATCH 6/6] Update lib/src/rules/no_wildcard_variable_uses.dart Co-authored-by: Marya <111139605+MaryaBelanger@users.noreply.github.com> --- lib/src/rules/no_wildcard_variable_uses.dart | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/src/rules/no_wildcard_variable_uses.dart b/lib/src/rules/no_wildcard_variable_uses.dart index e715e54ac..fb762cc85 100644 --- a/lib/src/rules/no_wildcard_variable_uses.dart +++ b/lib/src/rules/no_wildcard_variable_uses.dart @@ -14,11 +14,12 @@ const _desc = r"Don't use wildcard parameters or variables."; const _details = r''' **DON'T** use wildcard parameters or variables. -In a future version of the Dart langauge, wildcard parameters and local -variables (e.g., named with just underscores like `_`, `__`, `___`, etc.) will -become non-binding. When that happens, existing code that uses wildcard -parameters or variables will break. In anticipation and to make adoption -easier, this lint disallows wildcard and variable parameter uses. +Wildcard parameters and local variables +(e.g. underscore-only names like `_`, `__`, `___`, etc.) will +become non-binding in a future version of the Dart language. +Any existing code that uses wildcard parameters or variables will +break. In anticipation of this change, and to make adoption easier, +this lint disallows wildcard and variable parameter uses. **BAD:**