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