blog.yujinakayama.me

RuboCop 0.9.0

Jul 3rd, 2013

2013年7月1日、RuboCop 0.9.0 がリリースされました。といっても RuboCop をご存知ない方も多いかと思うので、まずは概要から。

RuboCop とは

RuboCop は Ruby のコーディングスタイルチェッカーです。Ruby コードを静的解析し、コーディングスタイル違反を検出します。Java で言う Checkstyle みたいなものですね。

RuboCop は、コーディングスタイルとして Ruby Style Guide を採用しています。むしろ、Ruby Style Guide の適用を押し進めるために RuboCop が作られたという方が正しいかもしれません。これは Bozhidar Batsov 氏が始めたコミュニティ主導のスタイルガイドプロジェクトで、GitHub 社内で使われている Ruby Styleguide のベースにもなっており、Rubyist ならご存知の方も多いでしょう。

Ruby のコードメトリックスツールとしては他に CaneReek などがありますが、これらはいわゆる「コードの臭い」を測定するものであり、コーディングスタイルを本格的にチェックするツールはこれまでなかったように思います。

RuboCop は、スタイル違反をチェックする cop(警官)達の集合体として構成されています。例えば、1行あたりの文字数をチェックする LineLength cop、メソッド名や変数名が snake_case になっているかチェックする MethodAndVariableSnakeCase cop、と言った形で、チェックする項目ごとに専任の cop が実装されています。

インストール

普通に gem コマンドでインストールできます。

$ gem install rubocop

実行

チェックしたい Ruby のソースファイルがあるディレクトリ内で rubocop コマンドを実行します。典型的にはプロジェクトルートディレクトリになるでしょう。

$ cd some-project
$ rubocop

この場合、カレントディレクトリ以下の、拡張子が .rb であるファイル、または拡張子が無く shebang(ファイル1行目の #! で始まる行)に ruby が含まれるファイルがチェック対象となります。

おそらく上記のコマンドを既存のプロジェクトに対して実行すると、大量のスタイル違反が検出されるかと思います。

設定

RuboCop の挙動は、設定を記述した .rubocop.yml ファイルを置くことで、ディレクトリ単位で変更することができます。

例えば .rubocop.yml に以下のような内容を記述すると、

Eval:
  Enabled: false

LineLength:
  Max: 100
  • Kernel.#eval メソッドの利用を警告する Eval cop を無効化
  • 1行あたりの最大文字数を100文字に設定(デフォルトは79文字)

といったカスタマイズができます。

既存のプロジェクトで RuboCop を使う場合、一旦最初は大半の cop を無効にしておき、一部 cop を有効化、違反箇所を修正、コミット、といった繰り返しで徐々にスタイルを適合させていくと良いのではないでしょうか。

バージョン 0.9.0 の新機能

さて、今回の 0.9.0 の新機能です。

Formatter

RSpec の formatter に似た仕組みを導入しました。-f/--format オプションで、結果の出力書式を切り替えられるようになっています。

これに伴い、標準の組み込み formatter もいくつか追加しています。

  • progress — RSpec の progress formatter ライクな、ドットによる進捗表示(デフォルト)
  • clang — 違反箇所を Clang の診断結果ライクに表示(後述)
  • json — 解析結果を JSON で出力

また、独自の formatter クラスを作成することで、カスタムフォーマッタを利用することも可能です。

違反箇所の詳細な表示

前述の clang formatter がこれにあたります。その名の通り Clang の診断結果 ライクに、違反箇所のハイライト表示をします。progress formatter も、解析完了後にサマリーとしてこの形式で表示をするようになっています。

features/support/helper.rb:6:3: W: Assigned but unused variable - stdin
  stdin, stdout, stderr, thread = Open3.popen3(*command)
  ^^^^^

Ruby の実装エンジン非依存の構文チェック

RuboCop はスタイルのチェックだけでなく、ruby -cw で警告されるような基本的な構文チェックも行います。例えば、利用していないローカル変数の検出なんかがこれにあたります。

バージョン 0.9.0 以前は、まさにそのまま ruby -cw コマンドを対象ファイル毎に実行してその出力をパースしていたのですが、この機能は MRI (CRuby) のみで有効で、JRuby や Rubinius ではスキップされていました(RuboCop は JRuby や Rubinius もサポートしています)。この理由として、JRuby は JVM 上で動くためプロセスの立ち上がりが非常に遅く実用に耐えないこと、また Rubinius は警告のバリエーションが MRI ほど充実していなかったことなどがあります。

RuboCop 0.9.0 では、MRI 2.0 で出力される警告のうち、一部をピュア Ruby で RuboCop 内に再実装し、依存 gem である Parser からの警告と合わせることで警告バリエーションの大半をカバーしており、JRuby や Rubinius 上でも同様に動作する構文チェックを実現しています。

違反コードの自動修正

これはまだ実験的な機能であり、ごく一部の cop でしかサポートされていませんが、-a/--auto-correct オプションによって違反箇所を自動的に修正することが可能となっています。

個人的にはこの機能の今後にはかなり期待しています。初めて RuboCop を使ってみて、大量の違反が検出された時点で修正する気をなくす人は多いでしょうし、チームでこういったスタイルチェッカーを導入する際にも「面倒くさい」といった心の声は確実に存在すると思います。

メソッドやクラスレベルのリファクタリングを要求するような違反(長過ぎるメソッドなど)の自動修正は難しいですが、書式の変換程度で済むような違反は、今後の実装でほぼ自動修正が可能になるのではないでしょうか。

Rails Cop

これも実験段階でまだ一つの cop しか実装されていませんが、Rails Style Guide をベースとした Rails 用 cop が追加されました。-R/--rails オプションを指定した場合のみ有効になります。

その他

多くの cop の追加やバグフィックスが含まれています。 詳細は Changelog をご覧下さい。

1.0 に向けて

次期バージョンの 1.0 では、前述の 0.9 で導入された機能のブラッシュアップを予定しています。

実は僕も少し前から RuboCop の開発に参加しています。 ファイル変更時に自動的に RuboCop を実行する Guard プラグイン、guard-rubocop も書いたので、Guard ファンの方は是非どうぞ。

あなたも RuboCop を使って、ナウでヤングな Rubyist になりませんか?