読者です 読者をやめる 読者になる 読者になる

本当は怖い情報科学

情報系大学院生の趣味&実益ブログ。

[ruby] set_trace_funcでメソッド定義を監視する

簡単かと思ったら、微妙だったので書いておく。ポイントは、ファイルの行の文字列そのものを渡してくれないので面倒くさい点と、class定義はわかるけどメソッド定義ははっきりとわからない点。だから、defを手動で発見してクラス定義のbindingでのselfを取ることで対象クラスを取得している。

# trace_method_def.rb

$files = Hash.new

set_trace_func Proc.new{ |event, file, line, id, binding, klass|
  if event == 'line'
    unless $files[file]
      $files[file] = open(file){ |f| [''] + f.readlines }
    end
    line_content = $files[file][line].sub(/#.*$/,'') # remove comment
    if $files[file][line] =~ /^\s*def\s*([^(\s]*)/
      _class = eval "self",binding
      _method = $1
      puts "#{_class}##{_method} = #{file}:#{line}"
    end
  end
}

class TestClass
  def foo
    puts "Test#foo"
  end

  def bar
    puts "Test#bar"
  end

  def baz
    puts "Test#baz"
  end

  def +()
      puts "Test#+"
  end
end

でとりあえず取得できる。

結果:

TestClass#foo = trace_method_def.rb:18
TestClass#bar = trace_method_def.rb:22
TestClass#baz = trace_method_def.rb:26
TestClass#+ = trace_method_def.rb:30

一行でメソッド定義をする場合に対処するというか、def文の解析はもう少しがんばったほうがいいんだけど、そこは妥協。

【広告】