Method#source_location

なるものをRuby1.9.1を触っていて見つけた。
名前からして素敵そうな気がする。これはMethodにしかないのだろうか。
探してみた。

ObjectSpace.each_object(Module) do |c|
  p c if c.instance_methods.include?(:source_location)
end
# >> UnboundMethod Method Proc

おおー。

expectationsはcallerをパースしてテストの位置を取ってたりするけど、1.0.0でのドライブレターの扱いとか、Ruby1.9.1でcallerの書式が変わってダメになったりとか、鬼門だと思う。が、これがあれば解決じゃないか。

def Expectations
  yield
end

def expect(expected, &actual)
  p caller[0]
  p actual.source_location
end

Expectations do
  expect 4 do
    'Ruby'.size
  end
end

# >> "C:/home/ruby/try_source_location.rb:11:in `block in <main>'"
#    ["C:/home/ruby/try_source_location.rb", 12]

…callerより1行ずれるな。

p method(:expect).source_location
# => ["C:/home/ruby/try_source_location.rb", 5]

Methodは合ってるんだけど。
これはそういうものなのか、バグなのか。

def expect(expected, &actual)
  p caller[0]
  p actual.source_location
end

expect 'R' do
  'Ruby'[0]
end
expect('R'){
  'Ruby'[0]
}
expect 'R' do 'Ruby'[0] end
expect('R'){ 'Ruby'[0] }
"C:/home/ruby/check_lineno_gap.rb:6:in `<main>'"
["C:/home/ruby/check_lineno_gap.rb", 7]
"C:/home/ruby/check_lineno_gap.rb:9:in `<main>'"
["C:/home/ruby/check_lineno_gap.rb", 9]
"C:/home/ruby/check_lineno_gap.rb:12:in `<main>'"
["C:/home/ruby/check_lineno_gap.rb", 12]
"C:/home/ruby/check_lineno_gap.rb:13:in `<main>'"
["C:/home/ruby/check_lineno_gap.rb", 13]

どうも複数行に渡ってdo ... end形式でブロックを書くとずれるっぽい?
要調査かね。