class RuboCop::Cop::Layout::OrderedMethods

@example EnforcedStyle: alphabetical (default)

# Check that methods are defined alphabetically.

# bad
def self.b; end
def self.a; end

def b; end
def a; end

private

def d; end
def c; end

# good
def self.a; end
def self.b; end

def a; end
def b; end

private

def c; end
def d; end

Constants

COMPARISONS
ERR_INVALID_COMPARISON

Public Instance Methods

autocorrect(node) click to toggle source
# File lib/rubocop/cop/layout/ordered_methods.rb, line 45
def autocorrect(node)
  @corrector.correct(node, @previous_node)
end
on_begin(node) click to toggle source
# File lib/rubocop/cop/layout/ordered_methods.rb, line 49
def on_begin(node)
  cache(node)
  consecutive_methods(@siblings) do |previous, current|
    unless ordered?(previous, current)
      @previous_node = previous
      add_offense(
        current,
        message: 'Methods should be sorted in ' \
          "#{cop_config['EnforcedStyle']} order."
      )
    end
  end
end

Private Instance Methods

access_modified?(node, is_class_method_block) click to toggle source
# File lib/rubocop/cop/layout/ordered_methods.rb, line 65
def access_modified?(node, is_class_method_block)
  (node.defs_type? && !is_class_method_block) ||
    (node.def_type? && is_class_method_block) ||
    (node.send_type? && node.bare_access_modifier?)
end
cache(node) click to toggle source

Cache to avoid traversing the AST multiple times

# File lib/rubocop/cop/layout/ordered_methods.rb, line 72
def cache(node)
  @cache ||= begin
    @siblings = node.children

    # Init the corrector with the cache to avoid traversing the AST in
    # the corrector.
    #
    # We always init the @corrector, even if @options[:auto_correct] is
    # nil, because `add_offense` always attempts correction. This
    # correction attempt is how RuboCop knows if the offense can be
    # labeled "[Correctable]".
    comment_locations = ::Parser::Source::Comment.associate_locations(
      processed_source.ast,
      processed_source.comments
    )
    @corrector = OrderedMethodsCorrector.new(comment_locations, @siblings, cop_config)
  end
end
consecutive_methods(nodes) { |left_method, right_method| ... } click to toggle source

We disable `Style/ExplicitBlockArgument` for performance. See github.com/shanecav84/rubocop-ordered_methods/pull/5#pullrequestreview-562957146 rubocop:disable Style/ExplicitBlockArgument

# File lib/rubocop/cop/layout/ordered_methods.rb, line 94
def consecutive_methods(nodes)
  filtered = filter_relevant_nodes(nodes)
  filtered_and_grouped = group_methods_by_access_modifier(filtered)
  filtered_and_grouped.each do |method_group|
    method_group.each_cons(2) do |left_method, right_method|
      yield left_method, right_method
    end
  end
end
filter_relevant_nodes(nodes) click to toggle source

rubocop:enable Style/ExplicitBlockArgument

# File lib/rubocop/cop/layout/ordered_methods.rb, line 105
def filter_relevant_nodes(nodes)
  nodes.select do |node|
    (
      (node.defs_type? || node.def_type?) &&
        !ignored_method?(node.method_name)
    ) || (node.send_type? && node.bare_access_modifier?)
  end
end
group_methods_by_access_modifier(nodes) click to toggle source

Group methods by the access modifier block they are declared in. Multiple blocks of the same modifier will have their methods grouped separately; for example, the following would be separated into two groups:

private
def a; end
private
def b; end
# File lib/rubocop/cop/layout/ordered_methods.rb, line 122
def group_methods_by_access_modifier(nodes)
  is_class_method_block = false

  nodes.each_with_object([[]]) do |node, grouped_methods|
    if access_modified?(node, is_class_method_block)
      grouped_methods << []
    end
    is_class_method_block = node.defs_type?
    next if node.send_type? && node.bare_access_modifier?

    grouped_methods.last << node
  end
end
ordered?(left_method, right_method) click to toggle source
# File lib/rubocop/cop/layout/ordered_methods.rb, line 136
def ordered?(left_method, right_method)
  comparison = COMPARISONS[cop_config['EnforcedStyle']]
  raise Error, ERR_INVALID_COMPARISON if comparison.nil?

  comparison.call(left_method, right_method)
end