Class: RuboCop::Cop::InternalAffairs::UseRestrictOnSend

Inherits:
Base
  • Object
show all
Defined in:
lib/rubocop/cop/internal_affairs/use_restrict_on_send.rb

Overview

Flags if ‘RESTRICT_ON_SEND` constant not defined and method name is checked programmatically in `on_send` methods.

Examples:

# bad
def on_send(node)
  return unless method_name(node) == :foo
  return unless node.children[1] == :foo
  return unless METHOD_NAMES.include?(method_name(node))

  name = node.children[1]
  return unless name == :foo
  name2 = method_name(node)
  return unless name == :foo

  # more code
end

# good
RESTRICT_ON_SEND = %i[foo].freeze

def on_send(node)
  # more code
end

# ignored - not `on_send`
def on_def(node)
  return unless method_name(node) == :foo
end

# ignored - `else` branch
def on_send(node)
  if method_name(node) == :foo
    add_offense(node)
  else
    something_else
  end
end

Constant Summary collapse

MSG =
'Define constant `RESTRICT_ON_SEND` to speed up calls to `on_send`. ' \
'The following line is then no longer necessary:'

Instance Method Summary collapse

Instance Method Details

#method_name_assignment(node) ⇒ Object



67
68
69
# File 'lib/rubocop/cop/internal_affairs/use_restrict_on_send.rb', line 67

def_node_search :method_name_assignment, <<~PATTERN
  (lvasgn $_name #method_name_plain)
PATTERN

#method_name_call(node) ⇒ Object



59
60
61
62
63
64
# File 'lib/rubocop/cop/internal_affairs/use_restrict_on_send.rb', line 59

def_node_matcher :method_name_call, <<~PATTERN
  {
    #method_name_plain
    (lvar %1)
  }
PATTERN

#method_name_check(node) ⇒ Object



72
73
74
75
76
77
78
79
80
# File 'lib/rubocop/cop/internal_affairs/use_restrict_on_send.rb', line 72

def_node_search :method_name_check, <<~PATTERN
  (if
    ${
      (send #method_name_call(%1) {:== :!=} _) # method_name(node) == foo
      (send _ :include? #method_name_call(%1)) # a.include?(method_name(node))
    }
    {!nil? nil? | nil? !nil?}                  # has either `if` or `else` branch - not both
  )
PATTERN

#method_name_plain(node) ⇒ Object



49
50
51
52
53
54
55
56
# File 'lib/rubocop/cop/internal_affairs/use_restrict_on_send.rb', line 49

def_node_matcher :method_name_plain, <<~PATTERN
  {
    (send _ :method_name _ ...)       # method_name(node)
    (send
      (send _ :children) :[] (int 1)  # node.children[1]
    )
  }
PATTERN

#on_casgn(node) ⇒ Object



93
94
95
# File 'lib/rubocop/cop/internal_affairs/use_restrict_on_send.rb', line 93

def on_casgn(node)
  @restrict_on_send_set = true if node.name == :RESTRICT_ON_SEND
end

#on_def(node) ⇒ Object



82
83
84
85
86
87
88
89
90
91
# File 'lib/rubocop/cop/internal_affairs/use_restrict_on_send.rb', line 82

def on_def(node)
  return unless node.method?(:on_send)
  return if @restrict_on_send_set

  local_assignments = method_name_assignment(node).to_set

  method_name_check(node, local_assignments) do |call_node|
    add_offense(call_node)
  end
end