Ruby用簡易コーディングルールチェッカーを作る

こんにちは、技術推進室の篠崎です。
現在、RailsのプロジェクトでRuboCopを利用してコーディングルールのチェックを行っています。
RuboCopをもっと知るために簡易版のコーディングルールチェッカー(以後簡易チェッカー)を作成してみました。
今回は簡易チェッカーのご紹介をさせて頂きたいと思います。
簡易版コーディングルールチェッカー
インスタンスメソッド名が「aaa」と「bbb」になっているかをチェックします。
こんなSampleクラスに対して実行すると
class Sample def aaa(num) num * 2 end def bbb(num) num + 2 end end
こんな感じで行数とエラーメッセージを表示するものです。
$ ./sample_checker sample.rb 2: aaaというメソッド名を利用してはだめ! 6: bbbというメソッド名を利用してはだめ!
ソースはここ
試したバージョン
ruby
- 2.1.1p76parser
- 2.1.9
処理
簡易チェッカーは以下の順番で処理をします。
- ソース解析
- チェック実施
- 結果出力
※ RuboCopは「1. ソース解析」前にオプション解析を実施していますが基本は同じ順番です
ソース解析
ソースの解析にparserを利用します。
$ gem install parser
※ RuboCopもこれを利用しています
引数で指定されたソースコードをASTに変換します。
source_buffer = Parser::Source::Buffer.new('(string)') source_buffer.source = File.read(ARGV[0]) parser = Parser::CurrentRuby.new ast = parser.parse(source_buffer)
チェック実施
Parser::AST::Processor
を継承したクラスSampleProcessor
を作成します
このクラスのproccess
メソッドに先ほど変換したASTを引数に渡して呼ぶとnode毎にon_xxx
というメソッドを呼び出してくれるのでそこでルールチェックを行います。
processor = SampleProcessor.new processor.process(ast)
今回はインスタンスメソッド名のチェックなのでon_def
を実装します。
class SampleProcessor < Parser::AST::Processor attr_reader :errors def initialize @errors = [] end def on_def(node) method_name, _other = *node if method_name.to_s == 'aaa' @errors << "#{node.loc.line}: aaaというメソッド名を利用してはだめ!" end if method_name.to_s == 'bbb' @errors << "#{node.loc.line}: bbbというメソッド名を利用してはだめ!" end end end
結果出力
結果は@errors
に入っているのでそれを出力するだけです
processor.errors.each { |error| puts error }
最後に
本当に簡単なコーディングルール(とよんでいいのかどうかも怪しい)チェッカーができました。
が、実際に運用するとなると
- ファイルが存在しなかったらどうするの?
- 複数ファイル対応したい
- Syntax間違えたらどうするの?
- 規約毎にクラス分けたい
- 自動で修正してほしい!
とか数え切れない課題、要望が出てくることかと思いますが、RuboCopならばほとんどの要望に対応してくれています(はず)
ので大人しくRuboCopを利用しましょうw
あと、こんなお役だち情報がありますよ! > RuboCopのCustom Copを作る
以上