Class: RubyLint::Analysis::ArgumentAmount

Inherits:
Base show all
Defined in:
lib/ruby-lint/analysis/argument_amount.rb

Overview

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.

Constant Summary

MAP_METHODS =

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

Returns:

  • (Hash)
{
  'new' => [:instance_method, 'initialize']
}

Constants inherited from Base

Base::SCOPES

Instance Attribute Summary

Attributes inherited from Base

#config, #report, #vm

Attributes inherited from Iterator

#arity_cache, #arity_cache Hash containing the amount of arguments for

Instance Method Summary collapse

Methods inherited from Base

#add_message, #after_initialize, analyze?, #current_scope, #error, #info, #previous_scope, register, #set_current_scope, #set_previous_scope, #warning

Methods included from MethodEvaluation

#unpack_block

Methods inherited from Iterator

#execute_callback, #initialize, #iterate, #skip_child_nodes!

Constructor Details

This class inherits a constructor from RubyLint::Iterator

Instance Method Details

#argument_amount(nodes) ⇒ Fixnum (private)

Parameters:

Returns:

  • (Fixnum)


129
130
131
# 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) ⇒ Array (private)

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

Parameters:

Returns:

  • (Array)


107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# 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) ⇒ String (private)

Returns a String that indicates the amount of required arguments.

Parameters:

Returns:



94
95
96
97
98
99
# 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) ⇒ TrueClass|FalseClass (private)

Parameters:

  • min (Numeric)
  • max (Numeric)
  • given (Numeric)

Returns:

  • (TrueClass|FalseClass)


83
84
85
# 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) ⇒ RubyLint::Definition::RubyMethod (private)



67
68
69
70
71
72
73
74
75
# 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

#on_send(node) ⇒ Object

Parameters:

  • node (RubyLint::Node)


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# 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

#scope_for_receiver(receiver) ⇒ RubyLint::Definition::RubyObject (private)

Parameters:

Returns:



52
53
54
55
56
57
58
59
60
# 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