class RubyLint::Analysis::ArgumentAmount

The ArgumentAmount class is an analysis class that verifies the amount of arguments given with each method call and adds errors whenever an invalid amount was given.

Constants

MAP_METHODS

Hash that contains method names that should be used for analysis instead of the ones specified in the keys.

@return [Hash]

Public Instance Methods

on_send(node) click to toggle source

@param [RubyLint::Node] node

# File lib/ruby-lint/analysis/argument_amount.rb, line 24
def on_send(node)
  receiver, name, *args = *node

  scope  = scope_for_receiver(receiver)
  method = determine_method(scope, name.to_s)

  return unless method

  given    = argument_amount(args)
  min, max = argument_range(method)

  unless correct_argument_amount(min, max, given)
    text = argument_text(method, given)

    error(
      "wrong number of arguments for '#{method.name}' " \
        "(expected #{text} but got #{given})",
      node
    )
  end
end

Private Instance Methods

argument_amount(nodes) click to toggle source

@param [RubyLint::AST::Node] nodes @return [Fixnum]

# File lib/ruby-lint/analysis/argument_amount.rb, line 129
def argument_amount(nodes)
  return nodes.reject { |n| n.type == :block_pass }.length
end
argument_range(method) click to toggle source

Returns the minimum and maximum amount of arguments for a method call.

@param [RubyLint::Definition::RubyMethod] method @return [Array]

# File lib/ruby-lint/analysis/argument_amount.rb, line 107
def argument_range(method)
  min = method.amount(:arg)

  if method.amount(:restarg) > 0
    max = Float::INFINITY
  else
    max = min + method.amount(:optarg) + method.amount(:restarg)
  end

  # If the method follows the writer naming pattern with a '=' ending,
  # the parser generates send nodes with one less argument than needed in
  # the case of parallel assignment. Here reducing minimum prevents false
  # positive warnings to be generated.
  min -= 1 if method.name =~ /=$/

  return min, max
end
argument_text(method, given) click to toggle source

Returns a String that indicates the amount of required arguments.

@param [RubyLint::Definition::RubyMethod] method @param [Numeric] given @return [String]

# File lib/ruby-lint/analysis/argument_amount.rb, line 94
def argument_text(method, given)
  min = method.amount(:arg)
  opt = method.amount(:optarg)

  return opt > 0 ? "#{min}..#{min + opt}" : min.to_s
end
correct_argument_amount(min, max, given) click to toggle source

@param [Numeric] min @param [Numeric] max @param [Numeric] given @return [TrueClass|FalseClass]

# File lib/ruby-lint/analysis/argument_amount.rb, line 83
def correct_argument_amount(min, max, given)
  return given >= min && given <= max
end
determine_method(scope, name) click to toggle source

@param [RubyLint::Definition::RubyObject] scope @param [String] name @return [RubyLint::Definition::RubyMethod]

# File lib/ruby-lint/analysis/argument_amount.rb, line 67
def determine_method(scope, name)
  method = scope.lookup(scope.method_call_type, name)

  if method and MAP_METHODS[method.name]
    method = scope.lookup(*MAP_METHODS[method.name])
  end

  return method
end
scope_for_receiver(receiver) click to toggle source

@param [RubyLint::AST::Node] receiver @return [RubyLint::Definition::RubyObject]

# File lib/ruby-lint/analysis/argument_amount.rb, line 52
def scope_for_receiver(receiver)
  scope = current_scope

  if receiver and vm.associations.key?(receiver)
    scope = vm.associations[receiver]
  end

  return scope
end