diff --git a/changelog/fix_fix_stylesolenestedconditional_to.md b/changelog/fix_fix_stylesolenestedconditional_to.md new file mode 100644 index 00000000000..21796018322 --- /dev/null +++ b/changelog/fix_fix_stylesolenestedconditional_to.md @@ -0,0 +1 @@ +* [#10881](https://github.com/rubocop/rubocop/issues/10881): Fix `Style/SoleNestedConditional` to properly wrap `block` and `csend` nodes when necessary. ([@dvandersluis][]) diff --git a/lib/rubocop/cop/style/sole_nested_conditional.rb b/lib/rubocop/cop/style/sole_nested_conditional.rb index 4fb04b3c13c..d00c41f6ba5 100644 --- a/lib/rubocop/cop/style/sole_nested_conditional.rb +++ b/lib/rubocop/cop/style/sole_nested_conditional.rb @@ -148,7 +148,18 @@ def correct_for_basic_condition_style(corrector, node, if_branch, and_operator) ) corrector.replace(range, and_operator) corrector.remove(range_by_whole_lines(node.loc.end, include_final_newline: true)) - corrector.wrap(if_branch.condition, '(', ')') if wrap_condition?(if_branch.condition) + + wrap_condition(corrector, if_branch.condition) + end + + def wrap_condition(corrector, condition) + # Handle `send` and `block` nodes that need to be wrapped in parens + # FIXME: autocorrection prevents syntax errors by wrapping the entire node in parens, + # but wrapping the argument list would be a more ergonomic correction. + node_to_check = condition&.block_type? ? condition.send_node : condition + return unless wrap_condition?(node_to_check) + + corrector.wrap(condition, '(', ')') end def correct_for_outer_condition_modify_form_style(corrector, node, if_branch) @@ -207,7 +218,7 @@ def insert_bang_for_and(corrector, node) end def require_parentheses?(condition) - condition.send_type? && !condition.arguments.empty? && !condition.parenthesized? && + condition.call_type? && !condition.arguments.empty? && !condition.parenthesized? && !condition.comparison_method? end @@ -219,7 +230,7 @@ def arguments_range(node) def wrap_condition?(node) node.and_type? || node.or_type? || - (node.send_type? && node.arguments.any? && !node.parenthesized?) + (node.call_type? && node.arguments.any? && !node.parenthesized?) end def replace_condition(condition) diff --git a/spec/rubocop/cop/style/sole_nested_conditional_spec.rb b/spec/rubocop/cop/style/sole_nested_conditional_spec.rb index a4920bfc161..a121ceb157d 100644 --- a/spec/rubocop/cop/style/sole_nested_conditional_spec.rb +++ b/spec/rubocop/cop/style/sole_nested_conditional_spec.rb @@ -663,6 +663,46 @@ def foo end RUBY end + + context 'with a `csend` node' do + it 'registers an offense and corrects' do + expect_offense(<<~RUBY) + if foo + if bar&.baz quux + ^^ Consider merging nested conditions into outer `if` conditions. + do_something + end + end + RUBY + + expect_correction(<<~RUBY) + if foo && (bar&.baz quux) + do_something + end + RUBY + end + end + + context 'with a block' do + it 'registers an offense and corrects' do + expect_offense(<<~RUBY) + if foo + if ok? bar do + ^^ Consider merging nested conditions into outer `if` conditions. + do_something + end + end + end + RUBY + + expect_correction(<<~RUBY) + if foo && (ok? bar do + do_something + end) + end + RUBY + end + end end end