4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Ruby のメソッド、Proc のソースを取り出す

Posted at

Ruby 2.6 から RubyVM::AbstractSyntaxTree.of が使えるようになりました。これは MethodProc オブジェクトを受け取りその AST を返すものです。

RubyVM::AbstractSyntaxTree.of(-> {1 + 1}) #=> RubyVM::AbstractSyntaxTree::Node

例えばこんな感じでメソッドや Proc のソースを取り出すことが出来るようになります。

module NodeToSource
  def to_source
    node = RubyVM::AbstractSyntaxTree.of(self)
    return nil if node.nil?

    path, _lineno = source_location
    lines_for_file = File.readlines(path)
    extract_source(node: node, lines_for_file: lines_for_file)
  end

  private

  def extract_source(node:, lines_for_file:)
    first_lineno = node.first_lineno - 1
    first_column = node.first_column
    last_lineno = node.last_lineno - 1
    last_column = node.last_column - 1

    if first_lineno == last_lineno
      lines_for_file[first_lineno][first_column..last_column]
    else
      src = ' ' * first_column + lines_for_file[first_lineno][first_column..]
      ((first_lineno + 1)...last_lineno).each do |lineno|
        src << lines_for_file[lineno]
      end
      src << lines_for_file[last_lineno][0..last_column]
    end
  end
end

class Method
  include NodeToSource
end

class Proc
  include NodeToSource
end

def foo
  puts 'hello world'
end

n = Proc.new { |i| i * 3 }

puts method(:foo).to_source
puts n.to_source

実行結果

def foo
  puts 'hello world'
end
{ |i| i * 3 }

ただ、C で定義されているメソッドは RubyVM::AbstractSyntaxTree.of(self) の返り値が nil になるためソースは取得出来ません。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?