hitode909の日記

趣味はマリンスポーツですの日記です

PPI::Transformを使ってソースコード中のトークンを置換する

会社でKyoto.pmのハッカソンあったからハッカソンとは無関係に出社してPerl書いてた.


Perlのソースコードをパースした上でトークンを置換するのを作った.実行するとifunlessが入れ替わる.


こういうのやるとき,IDEを使うか,IDEがなかったらsedとかで雑に書き換えてしまう(たとえば,Gitリポジトリ内の特定の語を全て置換する #git #sed - Qiita)けど,正規表現でソースコードを操作するのはよくない.間違うと動かなくなるので,目視で確認する必要がある.
たとえば,単純にs/if/unless/gとかすると,文字列中のifもunlessになってしまう.
逆に,パースしてから置換すると,コメント中のifはunlessにならないので,クラス名をパースした上で置換する場合に,コメント中のだけ古いクラス名が残る,ということになる.
それが困るようなら,コメントのトークンだけ取り出して,その中だけ正規表現で置換するとよいと思う.
PerlのIDEで,Padre, the Perl IDEっていうのがあるけど,素朴な感じで,変数名の置換くらいしかできなかった.すぐにクラッシュするし,おまけみたいな感じだった.
PPI::Transformっていうクラスでソースコードをパースした上で操作できるようになってたので,それを使った.
find('PPI::Token')としてるけど,PPI::Token::Quoteとかやると特定のクラスのトークンだけ取れる.

説明

  • PPI::Transformを継承してdocumentメソッドをオーバーライドする
  • 引数にdocumentが渡ってくるので,トークンを操作して,書き換えた数を返す
    • 実装見ると真ならなんでもいいけどドキュメントにはReturns the numbers of changes made to the documentって書いてあった
  • コンストラクタに渡したパラメータはblessされてるので勝手に使ってよい

参考