From 16c03214277a6a971c4650ff33d5f8df683f89a6 Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Tue, 27 Apr 2021 02:07:19 +0900 Subject: [PATCH] Fix an incorrect auto-correct for `Style/SingleLineMethods` This PR fixes the following incorrect auto-correct for `Style/SingleLineMethods` when defining setter method. ```console % cat example.rb def foo=(other) @foo == foo end % bundle exec rubocop --only Style/SingleLineMethods -a (snip) Inspecting 1 file C Offenses: example.rb:1:1: C: [Corrected] Style/SingleLineMethods: Avoid single-line method definitions. def foo=(other) @foo == foo end ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1 file inspected, 1 offense detected, 1 offense corrected ``` ### Before Auto-corrected to invalid syntax because setter method cannot be defined in an endless method definition. ```ruby % cat example.rb def foo=(other) = @foo == foo % ruby -c example.rb example.rb:1: setter method cannot be defined in an endless method definition def foo=(other) = @foo == foo ``` ### After ```ruby % cat example.rb def foo=(other) @foo == foo end ``` --- ...rrect_autocorrect_for_single_line_methods.md | 1 + lib/rubocop/cop/style/single_line_methods.rb | 11 ++++++++--- .../cop/style/single_line_methods_spec.rb | 17 +++++++++++++++++ 3 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 changelog/fix_incorrect_autocorrect_for_single_line_methods.md diff --git a/changelog/fix_incorrect_autocorrect_for_single_line_methods.md b/changelog/fix_incorrect_autocorrect_for_single_line_methods.md new file mode 100644 index 00000000000..f58e3abb5a3 --- /dev/null +++ b/changelog/fix_incorrect_autocorrect_for_single_line_methods.md @@ -0,0 +1 @@ +* [#9740](https://github.com/rubocop/rubocop/pull/9740): Fix an incorrect auto-correct for `Style/SingleLineMethods` when defining setter method. ([@koic][]) diff --git a/lib/rubocop/cop/style/single_line_methods.rb b/lib/rubocop/cop/style/single_line_methods.rb index 41bde1fbe92..20e20fbb0c9 100644 --- a/lib/rubocop/cop/style/single_line_methods.rb +++ b/lib/rubocop/cop/style/single_line_methods.rb @@ -68,6 +68,7 @@ def correct_to_endless?(body_node) return false unless endless_method_config['Enabled'] return false if endless_method_config['EnforcedStyle'] == 'disallow' return false unless body_node + return false if body_node.parent.assignment_method? !(body_node.begin_type? || body_node.kwbegin_type?) end @@ -115,15 +116,19 @@ def move_comment(node, corrector) end def method_body_source(method_body) - if !method_body.send_type? || method_body.arguments.empty? || method_body.parenthesized? - method_body.source - else + if require_parentheses?(method_body) arguments_source = method_body.arguments.map(&:source).join(', ') body_source = "#{method_body.method_name}(#{arguments_source})" method_body.receiver ? "#{method_body.receiver.source}.#{body_source}" : body_source + else + method_body.source end end + + def require_parentheses?(method_body) + method_body.send_type? && !method_body.arguments.empty? && !method_body.comparison_method? + end end end end diff --git a/spec/rubocop/cop/style/single_line_methods_spec.rb b/spec/rubocop/cop/style/single_line_methods_spec.rb index 2802bb8f6d8..61d954132c5 100644 --- a/spec/rubocop/cop/style/single_line_methods_spec.rb +++ b/spec/rubocop/cop/style/single_line_methods_spec.rb @@ -211,6 +211,23 @@ def some_method() = body RUBY end + RuboCop::AST::Node::COMPARISON_OPERATORS.each do |op| + it "corrects to an endless class method definition when using #{op}" do + expect_correction(<<~RUBY.strip, source: "def #{op}(other) self #{op} other end") + def #{op}(other) = self #{op} other + RUBY + end + end + + # NOTE: Setter method cannot be defined in the endless method definition. + it 'corrects to multiline method definition when defining setter method' do + expect_correction(<<~RUBY.chop, source: 'def foo=(foo) @foo = foo end') + def foo=(foo)#{trailing_whitespace} + @foo = foo#{trailing_whitespace} + end + RUBY + end + it 'corrects to a normal method if the method body contains multiple statements' do expect_correction(<<~RUBY.strip, source: 'def some_method; foo; bar end') def some_method;#{trailing_whitespace}