From afaa6047a9ac095f0098ccf85fd77196069b7a3d Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Fri, 3 Feb 2023 18:17:18 +0900 Subject: [PATCH] [Fix #11535] Fix a false positive for `Style/NumberedParametersLimit` Fixes #11535. This PR fixes a false positive for `Style/NumberedParametersLimit` when only `_2` or higher numbered parameter is used. --- ...ive_for_style_numbered_parameters_limit.md | 1 + .../cop/style/numbered_parameters_limit.rb | 14 ++++++++--- .../style/numbered_parameters_limit_spec.rb | 25 +++++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 changelog/fix_a_false_positive_for_style_numbered_parameters_limit.md diff --git a/changelog/fix_a_false_positive_for_style_numbered_parameters_limit.md b/changelog/fix_a_false_positive_for_style_numbered_parameters_limit.md new file mode 100644 index 00000000000..363570fa421 --- /dev/null +++ b/changelog/fix_a_false_positive_for_style_numbered_parameters_limit.md @@ -0,0 +1 @@ +* [#11535](https://github.com/rubocop/rubocop/issues/11535): Fix a false positive for `Style/NumberedParametersLimit` when only `_2` or higher numbered parameter is used. ([@koic][]) diff --git a/lib/rubocop/cop/style/numbered_parameters_limit.rb b/lib/rubocop/cop/style/numbered_parameters_limit.rb index 06a48e47efa..34d7ec82b96 100644 --- a/lib/rubocop/cop/style/numbered_parameters_limit.rb +++ b/lib/rubocop/cop/style/numbered_parameters_limit.rb @@ -12,10 +12,11 @@ module Style # # @example Max: 1 (default) # # bad - # foo { _1.call(_2, _3, _4) } + # use_multiple_numbered_parameters { _1.call(_2, _3, _4) } # # # good - # foo { do_something(_1) } + # array.each { use_array_element_as_numbered_parameter(_1) } + # hash.each { use_only_hash_value_as_numbered_parameter(_2) } class NumberedParametersLimit < Base extend TargetRubyVersion extend ExcludeLimit @@ -26,9 +27,10 @@ class NumberedParametersLimit < Base exclude_limit 'Max' MSG = 'Avoid using more than %i numbered %s; %i detected.' + NUMBERED_PARAMETER_PATTERN = /\A_[1-9]\z/.freeze def on_numblock(node) - _send_node, param_count, * = *node + param_count = numbered_parameter_nodes(node).uniq.count return if param_count <= max_count parameter = max_count > 1 ? 'parameters' : 'parameter' @@ -38,6 +40,12 @@ def on_numblock(node) private + def numbered_parameter_nodes(node) + node.each_descendant(:lvar).select do |lvar_node| + lvar_node.source.match?(NUMBERED_PARAMETER_PATTERN) + end + end + def max_count max = cop_config.fetch('Max', DEFAULT_MAX_VALUE) diff --git a/spec/rubocop/cop/style/numbered_parameters_limit_spec.rb b/spec/rubocop/cop/style/numbered_parameters_limit_spec.rb index 13ba9bb9279..68971571a51 100644 --- a/spec/rubocop/cop/style/numbered_parameters_limit_spec.rb +++ b/spec/rubocop/cop/style/numbered_parameters_limit_spec.rb @@ -54,6 +54,31 @@ context 'when Max is 1' do let(:max) { 1 } + it 'does not register an offense when only numbered parameter `_1` is used once' do + expect_no_offenses(<<~RUBY) + foo { do_something(_1) } + RUBY + end + + it 'does not register an offense when only numbered parameter `_1` is used twice' do + expect_no_offenses(<<~RUBY) + foo { do_something(_1, _1) } + RUBY + end + + it 'does not register an offense when only numbered parameter `_9` is used once' do + expect_no_offenses(<<~RUBY) + foo { do_something(_9) } + RUBY + end + + it 'does not register an offense when using numbered parameter with underscored local variable' do + expect_no_offenses(<<~RUBY) + _lvar = 42 + foo { do_something(_2, _lvar) } + RUBY + end + it 'uses the right offense message' do expect_offense(<<~RUBY) foo { do_something(_1, _2, _3, _4, _5) }