From dd7dba8e93b270fa4c3dd6b6355534d129c7cd99 Mon Sep 17 00:00:00 2001 From: Daniel Vandersluis Date: Fri, 26 Mar 2021 13:02:57 -0400 Subject: [PATCH] [Fix #9641] Fix `Layout/MultilineMethodCallIndentation` triggering on method calls that look like operators. `right_hand_side` was not correctly calculating when the send node looks like an operator but has a receiver (ie. `foo.&`). This was leading to an autocorrection loop with `Layout/ArgumentAlignment`, `Layout/ClosingParenthesisIndentation` and `Layout/FirstArgumentIndentation`. --- ...ix_layoutmultilinemethodcallindentation.md | 1 + .../multiline_method_call_indentation.rb | 12 +++++++++++ .../layout/multiline_operation_indentation.rb | 4 ++++ .../mixin/multiline_expression_indentation.rb | 20 ------------------- .../multiline_method_call_indentation_spec.rb | 9 +++++++++ .../multiline_operation_indentation_spec.rb | 5 +++++ 6 files changed, 31 insertions(+), 20 deletions(-) create mode 100644 changelog/fix_fix_layoutmultilinemethodcallindentation.md diff --git a/changelog/fix_fix_layoutmultilinemethodcallindentation.md b/changelog/fix_fix_layoutmultilinemethodcallindentation.md new file mode 100644 index 00000000000..1880e290cfe --- /dev/null +++ b/changelog/fix_fix_layoutmultilinemethodcallindentation.md @@ -0,0 +1 @@ +* [#9641](https://github.com/rubocop/rubocop/issues/9641): Fix `Layout/MultilineMethodCallIndentation` triggering on method calls that look like operators. ([@dvandersluis][]) diff --git a/lib/rubocop/cop/layout/multiline_method_call_indentation.rb b/lib/rubocop/cop/layout/multiline_method_call_indentation.rb index f1a73962a99..d7d25365ace 100644 --- a/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +++ b/lib/rubocop/cop/layout/multiline_method_call_indentation.rb @@ -72,6 +72,18 @@ def relevant_node?(send_node) send_node.loc.dot # Only check method calls with dot operator end + def right_hand_side(send_node) + dot = send_node.loc.dot + selector = send_node.loc.selector + if send_node.dot? && selector && dot.line == selector.line + dot.join(selector) + elsif selector + selector + elsif send_node.implicit_call? + dot.join(send_node.loc.begin) + end + end + def offending_range(node, lhs, rhs, given_style) return false unless begins_its_line?(rhs) return false if not_for_this_cop?(node) diff --git a/lib/rubocop/cop/layout/multiline_operation_indentation.rb b/lib/rubocop/cop/layout/multiline_operation_indentation.rb index 0e80d5bd975..62b4a4b022f 100644 --- a/lib/rubocop/cop/layout/multiline_operation_indentation.rb +++ b/lib/rubocop/cop/layout/multiline_operation_indentation.rb @@ -118,6 +118,10 @@ def message(node, lhs, rhs) "spaces for indenting #{what} spanning multiple lines." end end + + def right_hand_side(send_node) + send_node.first_argument.source_range + end end end end diff --git a/lib/rubocop/cop/mixin/multiline_expression_indentation.rb b/lib/rubocop/cop/mixin/multiline_expression_indentation.rb index 0e8a7129861..1ea9d33c362 100644 --- a/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +++ b/lib/rubocop/cop/mixin/multiline_expression_indentation.rb @@ -35,26 +35,6 @@ def left_hand_side(lhs) lhs end - def right_hand_side(send_node) - if send_node.operator_method? && send_node.arguments? - send_node.first_argument.source_range # not used for method calls - else - regular_method_right_hand_side(send_node) - end - end - - def regular_method_right_hand_side(send_node) - dot = send_node.loc.dot - selector = send_node.loc.selector - if send_node.dot? && selector && dot.line == selector.line - dot.join(selector) - elsif selector - selector - elsif send_node.implicit_call? - dot.join(send_node.loc.begin) - end - end - # The correct indentation of `node` is usually `IndentationWidth`, with # one exception: prefix keywords. # diff --git a/spec/rubocop/cop/layout/multiline_method_call_indentation_spec.rb b/spec/rubocop/cop/layout/multiline_method_call_indentation_spec.rb index c66e95ffc76..f4d0617a177 100644 --- a/spec/rubocop/cop/layout/multiline_method_call_indentation_spec.rb +++ b/spec/rubocop/cop/layout/multiline_method_call_indentation_spec.rb @@ -95,6 +95,15 @@ .my_method RUBY end + + it 'accepts alignment of method with assignment and operator-like method' do + expect_no_offenses(<<~RUBY) + query = x.|( + foo, + bar + ) + RUBY + end end shared_examples 'common for aligned and indented' do diff --git a/spec/rubocop/cop/layout/multiline_operation_indentation_spec.rb b/spec/rubocop/cop/layout/multiline_operation_indentation_spec.rb index 5e807ed82e4..c063f5e4759 100644 --- a/spec/rubocop/cop/layout/multiline_operation_indentation_spec.rb +++ b/spec/rubocop/cop/layout/multiline_operation_indentation_spec.rb @@ -81,6 +81,11 @@ .a .b(c) + Foo.&( + foo, + bar + ) + expect { Foo.new }. to change { Bar.count }. from(1).to(2)