diff --git a/changelog/new_ignored_methods_options_for_lint_ambiguous_block_association.md b/changelog/new_ignored_methods_options_for_lint_ambiguous_block_association.md new file mode 100644 index 00000000000..14504bafe6e --- /dev/null +++ b/changelog/new_ignored_methods_options_for_lint_ambiguous_block_association.md @@ -0,0 +1 @@ +* [#9684](https://github.com/rubocop/rubocop/issues/9684): Support `IgnoredMethods` option for `Lint/AmbguousBlockAssociation`. ([@gprado][]) diff --git a/config/default.yml b/config/default.yml index d29f1371265..6008a131343 100644 --- a/config/default.yml +++ b/config/default.yml @@ -1387,6 +1387,8 @@ Lint/AmbiguousBlockAssociation: StyleGuide: '#syntax' Enabled: true VersionAdded: '0.48' + VersionChanged: '1.13' + IgnoredMethods: [] Lint/AmbiguousOperator: Description: >- diff --git a/docs/modules/ROOT/pages/cops_lint.adoc b/docs/modules/ROOT/pages/cops_lint.adoc index 401e1c630e4..b8a8a12b608 100644 --- a/docs/modules/ROOT/pages/cops_lint.adoc +++ b/docs/modules/ROOT/pages/cops_lint.adoc @@ -40,7 +40,7 @@ x != y # or x = !y | Yes | No | 0.48 -| - +| 1.13 |=== This cop checks for ambiguous block association with method @@ -71,6 +71,16 @@ foo == bar { |b| b.baz } foo = ->(bar) { bar.baz } ---- +=== Configurable attributes + +|=== +| Name | Default value | Configurable values + +| IgnoredMethods +| `[]` +| Array +|=== + === References * https://rubystyle.guide#syntax diff --git a/lib/rubocop/cop/lint/ambiguous_block_association.rb b/lib/rubocop/cop/lint/ambiguous_block_association.rb index ab7e01b1513..3f0a4770d77 100644 --- a/lib/rubocop/cop/lint/ambiguous_block_association.rb +++ b/lib/rubocop/cop/lint/ambiguous_block_association.rb @@ -6,6 +6,8 @@ module Lint # This cop checks for ambiguous block association with method # when param passed without parentheses. # + # This cop can customize ignored methods with `IgnoredMethods`. + # # @example # # # bad @@ -26,7 +28,14 @@ module Lint # # good # # Lambda arguments require no disambiguation # foo = ->(bar) { bar.baz } + # + # @example IgnoredMethods: [change] + # + # # good + # expect { do_something }.to change { object.attribute } class AmbiguousBlockAssociation < Base + include IgnoredMethods + MSG = 'Parenthesize the param `%s` to make sure that the ' \ 'block will be associated with the `%s` method ' \ 'call.' @@ -50,7 +59,8 @@ def ambiguous_block_association?(send_node) end def allowed_method?(node) - node.assignment? || node.operator_method? || node.method?(:[]) + node.assignment? || node.operator_method? || node.method?(:[]) || + ignored_method?(node.last_argument.send_node.source) end def message(send_node) diff --git a/spec/rubocop/cop/lint/ambiguous_block_association_spec.rb b/spec/rubocop/cop/lint/ambiguous_block_association_spec.rb index 7ad10aa068d..e39507128c9 100644 --- a/spec/rubocop/cop/lint/ambiguous_block_association_spec.rb +++ b/spec/rubocop/cop/lint/ambiguous_block_association_spec.rb @@ -83,4 +83,21 @@ end end end + + context 'IgnoredMethods' do + let(:cop_config) { { 'IgnoredMethods' => %w[change] } } + + it 'does not register an offense for an ignored method' do + expect_no_offenses(<<~RUBY) + expect { order.expire }.to change { order.events } + RUBY + end + + it 'registers an offense for other methods' do + expect_offense(<<~RUBY) + expect { order.expire }.to update { order.events } + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Parenthesize the param `update { order.events }` to make sure that the block will be associated with the `update` method call. + RUBY + end + end end