何でも屋エンジニアのブログ

ソフトウェア関連技術、コミュニティ、日々の雑貨

RuboCop::AST::ProcessedSourceのAPIを触るときのメモ

コードのメトリクス自分で取りたいなと思いRubocopのソースコードを読んでいる。

Copが呼ばれるまでにソースコードがどう処理されて渡されるのか、Cop内でどう解析するのか気になって手元でいじっていた。

手元でRubocopを実行しブレークポイントを貼り見るのも良いけど、processed_source周りのAPIを自分でたたいて遊びたかったので以下のようなスクリプトを書いた。呼び出すcopの設定をしたりキャッシュをoffにしたりとちょっと面倒に感じたのもあるが、pockeさんの記事を読めばクリアできるのであくまでも副次的な理由である。

qiita.com

# 標準入力からソースコードを渡している
require 'pry'
require 'rubocop'
require 'rubocop-ast'

arg = ARGV.first
source = +arg

ps = RuboCop::AST::ProcessedSource.new(source, 3.0)

def visit_depth_last(node, &block)
  node.each_child_node { |child| visit_depth_last(child, &block) }
  yield node
end

visit_depth_last(ps.ast) do |child|
  binding.pry
end

Rubocopの各所で引数として渡されているnodeはprocessed_source.astなので、visit_depth_lastに渡してあげてゴニョニョするとRuboCop::AST::*NodeAPIを触れるようになる。これで自分の参考にしたいCopの実装を見つつ手元でデバッグするのが分かりやすかった。