class RuboCop::Cop::Style::MethodOrder
This cop enforces methods to be sorted alphabetically within the context of their scope and permission level such as `private` or `protected`. The method `initialize` is given special treatment by being required to be listed first in the context of a class if it's a public method.
@example
# bad # `bar` should be listed before `foo`. The method `bar` will show # a linter error with a message indicating which method is should show # before. The private method `another_method` will also an error # saying it should be before `private_method`. class ExampleClass def foo end def bar end private def private_method end def another_method end end
@example
# bad # Works on modules too. module ExampleModule def foo end def bar end end
@example
# bad # As well as top level ruby methods in a file. def foo end def bar end
@example
# good class ExampleClass def bar end def foo end private def another_method end def private_method end end
@example
# good module ExampleModule def bar end def foo end end
@example
# good def bar end def foo end
Constants
- MSG
Public Instance Methods
rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, rubocop:disable Metrics/MethodLength, Metrics/PerceivedComplexity
# File lib/rubocop/cop/style/method_order.rb, line 111 def autocorrect(_node) lambda do |corrector| @method_collector.nodes_by_scope.values.each do |method_collection| next if @autocorrected_method_collections.include?(method_collection) @autocorrected_method_collections << method_collection method_collection.replacements.values.each do |replacement_collection| replacement_collection.each do |node_to_move, node_to_replace| next if @autocorrected_nodes.include?(node_to_move) @autocorrected_nodes << node_to_move node_source = range_with_method_comments(node_to_move).source replacement_range = range_with_method_comments(node_to_replace) if node_source.end_with?("\n") && !replacement_range.source.end_with?("\n") corrector.replace(replacement_range, node_source.chomp("\n")) elsif !node_source.end_with?("\n") && replacement_range.source.end_with?("\n") corrector.replace(replacement_range, node_source + "\n") else corrector.replace(replacement_range, node_source) end end end end end end
rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, rubocop:enable Metrics/MethodLength, Metrics/PerceivedComplexity
# File lib/rubocop/cop/style/method_order.rb, line 140 def investigate(_processed_source) @autocorrected_method_collections = [] @autocorrected_nodes = [] @method_collector = RuboCopMethodOrder::MethodCollector.new( should_skip_method: ->(node) { !cop_enabled_for_node?(node) } ) @offenses_checked = false end
NOTE: Change this if cops get a callback method for running validations
after the on_* methods have been executed.
# File lib/rubocop/cop/style/method_order.rb, line 151 def offenses(*args) unless @offenses_checked @offenses_checked = true check_nodes end super(*args) end
# File lib/rubocop/cop/style/method_order.rb, line 160 def on_class(node) @method_collector.collect_nodes_from_class(node) end
# File lib/rubocop/cop/style/method_order.rb, line 164 def on_def(node) @method_collector.collect(node) end
# File lib/rubocop/cop/style/method_order.rb, line 169 def on_module(node) @method_collector.collect_nodes_from_module(node) end
Private Instance Methods
rubocop:disable Metrics/MethodLength
# File lib/rubocop/cop/style/method_order.rb, line 176 def begin_pos_with_comments(node) range = node.source_range begin_of_first_line = range.begin_pos - range.column line_number = range.first_line loop do line_number -= 1 break if line_number <= 0 source_line = @processed_source.buffer.source_line(line_number) break unless source_line.match?(/\s*#/) begin_of_first_line -= (source_line.length + 1) # account for \n char end begin_of_first_line end
rubocop:enable Metrics/MethodLength
# File lib/rubocop/cop/style/method_order.rb, line 193 def check_nodes @method_collector.nodes_by_scope.values.each do |method_collection| method_collection.offenses.each do |offense| add_offense(offense[:node], location: :expression, message: message( offense[:node].method_name, offense[:other_node].method_name )) end end end
# File lib/rubocop/cop/style/method_order.rb, line 204 def cop_enabled_for_node?(node) processed_source.comment_config.cop_enabled_at_line?(self, node.first_line) end
rubocop:disable Metrics/AbcSize, Metrics/MethodLength
# File lib/rubocop/cop/style/method_order.rb, line 209 def end_pos_with_comments(node) range = node.source_range last_line = @processed_source.buffer.source_line(range.last_line) end_of_last_line = range.end_pos + last_line.length - range.last_column line_number = node.source_range.last_line if line_number != @processed_source.lines.count end_of_last_line += 1 # account for newline end loop do line_number += 1 break if line_number > @processed_source.lines.count source_line = @processed_source.buffer.source_line(line_number) break unless source_line.match?(/\s*#/) adjustment = 0 if line_number != @processed_source.lines.count adjustment = 1 # account for newline end end_of_last_line += source_line.length + adjustment end end_of_last_line end
rubocop:enable Metrics/AbcSize, Metrics/MethodLength
# File lib/rubocop/cop/style/method_order.rb, line 236 def message(method_name, following_method_name) format(MSG, method: method_name, previous_method: following_method_name) end
# File lib/rubocop/cop/style/method_order.rb, line 242 def range_with_method_comments(node) Parser::Source::Range.new(@processed_source.buffer, begin_pos_with_comments(node), end_pos_with_comments(node)) end