module RuboCop::AST::Traversal::CallbackCompiler

def arity_check(range)

def arity_check(range)
  <<~RUBY
    n = node.children.size
    raise DebugError, [
      'Expected #{range} children, got',
      n, 'for', node.inspect
    ].join(' ') unless (#{range}).cover?(node.children.size)
  RUBY
end

def body(signature, prelude)

def body(signature, prelude)
  signature
    .map.with_index do |arg, i|
      TEMPLATE[arg].gsub('%<index>i', i.to_s)
    end
    .unshift(prelude)
    .join("\n")
end

def def_callback(type, *signature,

def def_callback(type, *signature,
                 arity: signature.size..signature.size,
                 arity_check: ENV.fetch('RUBOCOP_DEBUG', nil) && self.arity_check(arity),
                 body: self.body(signature, arity_check))
  type, *aliases = type
  lineno = caller_locations(1, 1).first.lineno
  module_eval(<<~RUBY, __FILE__, lineno) # rubocop:disable Style/EvalWithLocation
    def on_#{type}(node)        # def on_send(node)
      #{body}                   #   # body ...
      nil                       #   nil
    end                         # end
  RUBY
  aliases.each do |m|
    alias_method "on_#{m}", "on_#{type}"
  end
end