Class: CodeNode::SexpWalker

Inherits:
Object
  • Object
show all
Defined in:
lib/code_node/sexp_walker.rb

Overview

Walks a Sexp representing a ruby file looking for classes and modules.

Instance Method Summary collapse

Constructor Details

#initialize(graph, sexp, opt = {}) ⇒ SexpWalker

Initialize a walker with a graph and sexp

All files in a code base should be walked once in :find_nodes mode, and then walked again in :find_relations mode.

Parameters:

  • graph (IR::Graph)

    a graph to which nodes and relations will be added

  • sexp (Sexp)

    the root sexp of a ruby file

  • opt (Hash) (defaults to: {})

    a customizable set of options

Options Hash (opt):

  • :mode (Symbol) — default: :find_nodes

    one of :find_nodes or :find_relations



14
15
16
17
18
# File 'lib/code_node/sexp_walker.rb', line 14

def initialize(graph, sexp, opt={})
  @graph = graph
  @root = sexp
  @mode = opt[:mode] || :find_nodes
end

Instance Method Details

#walk(s = nil) ⇒ nil

Walk the tree rooted at the given sexp

Parameters:

  • s (Sexp) (defaults to: nil)

    if nil will be the root sexp

Returns:

  • (nil)


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/code_node/sexp_walker.rb', line 23

def walk(s = nil)
  s ||= @root
  if [:module, :class].member?(s[0])
    node = @graph.node_for(s[0], s[1]) do |node|
      if find_relations? && s[0] == :class && !s[2].nil?
        super_node = @graph.node_for :class, s[2], :not_sure_if_nested => true
        node.inherits_from super_node unless super_node.nil?
      end
      rest = s[0] == :module ? s.slice(2..-1) : s.slice(3..-1)
      rest.each do |c|
        walk(c) if c.class == Sexp
      end
    end
    unless @graph.scope.empty?
      @graph.scope.last.contains node
    end
  elsif find_relations? && s[0] == :call && s.length >= 4 && [:extend, :include].member?(s[2]) && !@graph.scope.empty?
    s.slice(3..-1).each do |mod_sexp|
      node = @graph.node_for :module, mod_sexp, :not_sure_if_nested => true
      unless node.nil?
        if s[2] == :extend
          @graph.scope.last.extends node
        else
          @graph.scope.last.includes node
        end
      end
    end
  else
    s.slice(1..-1).each do |c|
      walk(c) if c.class == Sexp
    end
  end
end