Class: Rubocop::Cop::Style::MethodAndVariableSnakeCase

Inherits:
Cop
  • Object
show all
Defined in:
lib/rubocop/cop/style/method_and_variable_snake_case.rb

Overview

This cop makes sure that all methods and variables use snake_case for their names. Some special arrangements have to be made for operator methods.

Constant Summary collapse

MSG =
'Use snake_case for methods and variables.'
SNAKE_CASE =
/^@?[\da-z_]+[!?=]?$/

Constants inherited from Cop

Cop::OPERATOR_METHODS

Instance Attribute Summary

Attributes inherited from Cop

#config, #corrections, #offences, #processed_source

Instance Method Summary collapse

Methods inherited from Cop

#add_offence, all, #autocorrect?, #autocorrect_action, #convention, #cop_config, #cop_name, cop_name, cop_type, #debug?, #ignore_node, inherited, #initialize, lint?, #message, rails?, style?, #warning

Constructor Details

This class inherits a constructor from Rubocop::Cop::Cop

Instance Method Details

#after_dot(node, method_name_length, regexp) ⇒ Object

Returns a range containing the method name after the given regexp and a dot.



65
66
67
68
69
70
71
72
73
# File 'lib/rubocop/cop/style/method_and_variable_snake_case.rb', line 65

def after_dot(node, method_name_length, regexp)
  expr = node.loc.expression
  match = /\A#{regexp}\s*\.\s*/.match(expr.source)
  return unless match
  offset = match[0].length
  begin_pos = expr.begin_pos + offset
  Parser::Source::Range.new(expr.source_buffer, begin_pos,
                            begin_pos + method_name_length)
end

#investigate(processed_source) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/rubocop/cop/style/method_and_variable_snake_case.rb', line 13

def investigate(processed_source)
  ast = processed_source.ast
  return unless ast
  on_node([:def, :defs, :lvasgn, :ivasgn, :send], ast) do |n|
    range = case n.type
            when :def             then name_of_instance_method(n)
            when :defs            then name_of_singleton_method(n)
            when :lvasgn, :ivasgn then name_of_variable(n)
            when :send            then name_of_setter(n)
            end

    next unless range
    name = range.source.to_sym
    next if name =~ SNAKE_CASE || OPERATOR_METHODS.include?(name)

    convention(n, range)
  end
end

#name_of_instance_method(def_node) ⇒ Object



32
33
34
35
36
37
38
39
40
# File 'lib/rubocop/cop/style/method_and_variable_snake_case.rb', line 32

def name_of_instance_method(def_node)
  expr = def_node.loc.expression
  match = /^def(\s+)([\w]+[!?=]?\b)/.match(expr.source)
  return unless match
  space, method_name = match.captures
  begin_pos = expr.begin_pos + 'def'.length + space.length
  Parser::Source::Range.new(expr.source_buffer, begin_pos,
                            begin_pos + method_name.length)
end

#name_of_setter(send_node) ⇒ Object



55
56
57
58
59
60
61
# File 'lib/rubocop/cop/style/method_and_variable_snake_case.rb', line 55

def name_of_setter(send_node)
  receiver, method_name = *send_node
  return unless receiver && receiver.type == :self
  return unless method_name.to_s.end_with?('=')
  after_dot(send_node, method_name.length - '='.length,
            Regexp.escape(receiver.loc.expression.source))
end

#name_of_singleton_method(defs_node) ⇒ Object



42
43
44
45
46
# File 'lib/rubocop/cop/style/method_and_variable_snake_case.rb', line 42

def name_of_singleton_method(defs_node)
  scope, method_name, _args, _body = *defs_node
  after_dot(defs_node, method_name.length,
            "def\s+" + Regexp.escape(scope.loc.expression.source))
end

#name_of_variable(vasgn_node) ⇒ Object



48
49
50
51
52
53
# File 'lib/rubocop/cop/style/method_and_variable_snake_case.rb', line 48

def name_of_variable(vasgn_node)
  expr = vasgn_node.loc.expression
  name = vasgn_node.children.first
  Parser::Source::Range.new(expr.source_buffer, expr.begin_pos,
                            expr.begin_pos + name.length)
end