diff --git a/changelog/fix_update_lintassignmentincondition_to_not.md b/changelog/fix_update_lintassignmentincondition_to_not.md new file mode 100644 index 00000000000..71279be925a --- /dev/null +++ b/changelog/fix_update_lintassignmentincondition_to_not.md @@ -0,0 +1 @@ +* [#10136](https://github.com/rubocop/rubocop/issues/10136): Update `Lint/AssignmentInCondition` to not consider assignments within blocks in conditions. ([@dvandersluis][]) diff --git a/lib/rubocop/cop/lint/assignment_in_condition.rb b/lib/rubocop/cop/lint/assignment_in_condition.rb index cc058ad23b0..836a7bc8f61 100644 --- a/lib/rubocop/cop/lint/assignment_in_condition.rb +++ b/lib/rubocop/cop/lint/assignment_in_condition.rb @@ -49,7 +49,7 @@ class AssignmentInCondition < Base def on_if(node) return if node.condition.block_type? - traverse_node(node.condition, ASGN_TYPES) do |asgn_node| + traverse_node(node.condition) do |asgn_node| next :skip_children if skip_children?(asgn_node) next if allowed_construct?(asgn_node) @@ -83,13 +83,15 @@ def skip_children?(asgn_node) (safe_assignment_allowed? && safe_assignment?(asgn_node)) end - # each_node/visit_descendants_with_types with :skip_children - def traverse_node(node, types, &block) - result = yield node if types.include?(node.type) + def traverse_node(node, &block) + # if the node is a block, any assignments are irrelevant + return if node.block_type? + + result = yield node if ASGN_TYPES.include?(node.type) return if result == :skip_children - node.each_child_node { |child| traverse_node(child, types, &block) } + node.each_child_node { |child| traverse_node(child, &block) } end end end diff --git a/spec/rubocop/cop/lint/assignment_in_condition_spec.rb b/spec/rubocop/cop/lint/assignment_in_condition_spec.rb index 6a2fac253e4..6287c83f7f8 100644 --- a/spec/rubocop/cop/lint/assignment_in_condition_spec.rb +++ b/spec/rubocop/cop/lint/assignment_in_condition_spec.rb @@ -90,6 +90,21 @@ expect_no_offenses('return 1 if any_errors? { o = file }.present?') end + it 'accepts assignment in a block after ||' do + expect_no_offenses(<<~RUBY) + if x?(bar) || y? { z = baz } + foo + end + RUBY + end + + it 'registers an offense for = in condition inside a block' do + expect_offense(<<~RUBY) + foo { x if y = z } + ^ Use `==` if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition. + RUBY + end + it 'accepts ||= in condition' do expect_no_offenses('raise StandardError unless foo ||= bar') end