class Object

Public Instance Methods

call_graph(filename_rb) click to toggle source

filename_rb [String] file with a ruby program @return a dot graph string

# File lib/code_explorer/call_graph.rb, line 9
def call_graph(filename_rb)
  ruby = File.read(filename_rb)
  ast = Parser::CurrentRuby.parse(ruby, filename_rb)
  defs = defs_from_ast(ast)
  def_names = defs.map {|d| def_name(d) }
  defs_to_hrefs = defs.map {|d| [def_name(d), "/files/" + def_location(d)] }.to_h

  defs_to_calls = {}
  defs.each do |d|
    calls = calls_from_def(d)
    call_names = calls.map {|c| send_name(c)}
    call_names = call_names.find_all{ |cn| def_names.include?(cn) }
    defs_to_calls[def_name(d)] = call_names
  end

  dot_from_hash(defs_to_calls, defs_to_hrefs)
end
calls_from_def(ast) click to toggle source
# File lib/code_explorer/call_graph.rb, line 89
def calls_from_def(ast)
  Defs.new.sends_from_ast(ast)
end
def_location(node) click to toggle source
# File lib/code_explorer/call_graph.rb, line 39
def def_location(node)
  range = node.loc.expression
  file = range.source_buffer.name
  line = range.line
  "#{file}#line=#{line}"
end
def_name(node) click to toggle source
# File lib/code_explorer/call_graph.rb, line 27
def def_name(node)
  case node.type
  when :def
    name, _args, _body = *node
  when :defs
    _obj, name, _args, _body = *node
  else
    raise
  end
  name
end
defs_from_ast(ast) click to toggle source
# File lib/code_explorer/call_graph.rb, line 85
def defs_from_ast(ast)
  Defs.new.defs_from_ast(ast)
end
dot_from_hash(graph, hrefs = {}) click to toggle source

@param graph [Hash{String => Array<String>}] vertex -> reachable vertices @param hrefs [Hash{String => String}] vertex -> href

# File lib/code_explorer/dot.rb, line 4
def dot_from_hash(graph, hrefs = {})
  dot = ""
  dot << "digraph g {\n"
  dot << "rankdir=LR;\n"
  graph.keys.sort.each do |vertex|
    href = hrefs[vertex]
    href = "href=\"#{href}\" " if href

    dot << "\"#{vertex}\"[#{href}];\n"
    destinations = graph[vertex].sort
    destinations.each do |d|
      dot << "\"#{vertex}\" -> \"#{d}\";\n"
    end
  end
  dot << "}\n"
  dot
end
numbered_lines(text) click to toggle source

Convert plain text to HTML where lines are hyperlinkable. Emulate RFC 5147 fragment identifier: line=42

# File lib/code_explorer/numbered_lines.rb, line 5
def numbered_lines(text)
  # but CodeRay wants to remove the equal sign;
  tag = "lI" + "-Ne" # avoid the literal tag if we process our own source
  html = CodeRay.scan(text, :ruby).page(line_number_anchors: tag)
  html.gsub(tag, "line=")
end
send_name(node) click to toggle source
# File lib/code_explorer/call_graph.rb, line 46
def send_name(node)
  _receiver, name, *_args = *node
  name
end