diff --git a/changelog/fix_incorrect_autocorrection_of_rails_action_order.md b/changelog/fix_incorrect_autocorrection_of_rails_action_order.md new file mode 100644 index 0000000000..f591bf2b95 --- /dev/null +++ b/changelog/fix_incorrect_autocorrection_of_rails_action_order.md @@ -0,0 +1 @@ +* [#837](https://github.com/rubocop/rubocop-rails/pull/837): Fix incorrect autocorrection of `Rails/ActionOrder` about comments. ([@r7kamura][]) diff --git a/lib/rubocop/cop/rails/action_order.rb b/lib/rubocop/cop/rails/action_order.rb index 45487ad492..2cb0a64aa4 100644 --- a/lib/rubocop/cop/rails/action_order.rb +++ b/lib/rubocop/cop/rails/action_order.rb @@ -35,6 +35,7 @@ class ActionOrder < Base extend AutoCorrector include VisibilityHelp include DefNode + include RangeHelp MSG = 'Action `%s` should appear before `%s`.' @@ -80,7 +81,30 @@ def register_offense(previous, current) end def correction_target(def_node) - def_node.each_ancestor(:if).first || def_node + range_with_comments_and_lines(def_node.each_ancestor(:if).first || def_node) + end + + def add_range(range1, range2) + range1.with( + begin_pos: [range1.begin_pos, range2.begin_pos].min, + end_pos: [range1.end_pos, range2.end_pos].max + ) + end + + def range_with_comments(node) + ranges = [ + node, + *processed_source.ast_with_comments[node] + ].map do |element| + element.location.expression + end + ranges.reduce do |result, range| + add_range(result, range) + end + end + + def range_with_comments_and_lines(node) + range_by_whole_lines(range_with_comments(node), include_final_newline: true) end end end diff --git a/spec/rubocop/cop/rails/action_order_spec.rb b/spec/rubocop/cop/rails/action_order_spec.rb index 0e7fae8c09..6197e32c94 100644 --- a/spec/rubocop/cop/rails/action_order_spec.rb +++ b/spec/rubocop/cop/rails/action_order_spec.rb @@ -187,4 +187,29 @@ def index; end RUBY end end + + context 'when action has some comments' do + it 'corrects comments properly' do + expect_offense(<<~RUBY) + class UserController < ApplicationController + # show + def show; end + + # index + def index; end + ^^^^^^^^^^^^^^ Action `index` should appear before `show`. + end + RUBY + + expect_correction(<<~RUBY) + class UserController < ApplicationController + # index + def index; end + + # show + def show; end + end + RUBY + end + end end