class RubyLint::Iterator

The Iterator class provides the means to iterate over an AST generated by {RubyLint::Parser} using callback methods for the various node types generated by this parser.

For each node type two events are called: one before and one after processing the node and all of its children. The names of these events are the following:

Here “X” is the name of the event. For example, when iterator an integer this would result in the event names `on_integer` and `after_integer`.

These event names are used to call the corresponding callback methods if they exist. Each callback method takes a single argument: the node (an instance of {RubyLint::AST::Node}) that belongs to the event.

Creating iterator classes is done by extending this particular class and adding the needed methods to it:

class MyIterator < RubyLint::Iterator
  def on_int(node)
    puts node.children[0]
  end

  def after_int(node)
    puts '---'
  end
end

When used this particular iterator class would display the values of all integers it processes. After processing an integer it will display three dashes.

## Skipping Child Nodes

The `on_*` callbacks can tell the Iterator class to not process any following child nodes by calling `skip_child_nodes!`:

def on_const(node)
  # ...

  skip_child_nodes!(node)
end

Internally this uses `throw` and makes sure to only skip the child nodes of the specified node (`throw` calls bubble up regardless of `catch` calls, unlike when using `begin/rescue`).

@!attribute [r] arity_cache Hash containing the amount of arguments for

each method.
@return [Hash]

Attributes

arity_cache[R]

Public Class Methods

new(options = {}) click to toggle source

@param [Hash] options Hash containing custom options to set for the

iterator.
# File lib/ruby-lint/iterator.rb, line 64
def initialize(options = {})
  options.each do |key, value|
    instance_variable_set("@#{key}", value)
  end

  after_initialize if respond_to?(:after_initialize)

  @arity_cache = {}
end

Public Instance Methods

iterate(node) click to toggle source

Recursively processes the specified list of nodes.

@param [RubyLint::Node] node A node and optionally a set of sub nodes to

iterate over.
# File lib/ruby-lint/iterator.rb, line 80
def iterate(node)
  return unless node.is_a?(AST::Node)

  before    = :"on_#{node.type}"
  after     = :"after_#{node.type}"
  skip_node = catch :skip_child_nodes do
    execute_callback(before, node)
  end

  if skip_node != node
    node.children.each do |child|
      iterate(child) if child.is_a?(AST::Node)
    end
  end

  execute_callback(after, node)
end

Protected Instance Methods

execute_callback(name, *args) click to toggle source

Executes the specified callback method if it exists.

@param [String|Symbol] name The name of the callback method to execute. @param [Array] args Arguments to pass to the callback method.

# File lib/ruby-lint/iterator.rb, line 115
def execute_callback(name, *args)
  return unless respond_to?(name)

  unless arity_cache.key?(name)
    arity_cache[name] = method(name).arity
  end

  if arity_cache[name] == 0
    send(name)
  else
    send(name, *args)
  end
end
skip_child_nodes!(node) click to toggle source

Instructs {#iterate} to not process any child nodes.

@param [RubyLint::AST::Node] node

# File lib/ruby-lint/iterator.rb, line 105
def skip_child_nodes!(node)
  throw :skip_child_nodes, node
end