Naming/RescuedExceptionsVariableNameとは
RuboCopのCopで、rescue
節で例外をキャプチャした時の変数名を統一するためのCop。
デフォルトではe
に統一される。1
例
# good begin rescue StandardError => e end # bad begin rescue StandardError => ex end
どう壊れていたか
2つ壊れていた。
1つは例外クラスが指定されていない場合、もう1つは1ファイル中に複数のrescue
が存在する場合。
例外クラスが指定されていない場合
このCopはrescue => ex
のような、例外クラスが指定されずにrescue
がされているコードを考慮していなかった。
というより、rescue ex
がex
ローカル変数に例外をキャプチャするものだと勘違いして実装されていた。
rescue ex
はex
変数なりメソッドなりを評価した結果の例外クラスにマッチするかという意味なので、これは正しくない。
その結果、rescue *error_classes
やrescue Klass.error
といった書き方でエラーが発生してしまっていた。
これはrescue ex
をローカル変数として扱おうと無理やり色々やっていたのが問題だったので、そのへんの処理をバッサリと消してしまうだけでうまく動いた。
1ファイル中に複数のrescue
が存在する場合
次のようなケースでエラーになってしまっていた。
begin rescue StandardError => ex end begin rescue end
これはCop中でインスタンス変数が間違った使われ方をしていたのが原因。
このCopでは@exception_name
に変数名(:ex
)を保存するようにしていた。
ところが、RuboCopではCopのインスタンスの寿命(== インスタンス変数の寿命)はファイル単位であるため、後ろのrescue
で前のrescue
の変数名を上書きされてしまっていた。
RuboCopのCopの実装において、安易にインスタンス変数を使うのはだいたい間違った使い方になると思う。ファイル単位での寿命だということを意識して使う必要がある。
宣伝
なお、このバグはrubocop-regression-testというプロジェクトで発見したバグである。
1行で説明すると、「世の中の色んなRubyコードに対してRuboCopを実行して、バグを見つけ出そう」というプロジェクトである。 結構バグが見つかるので楽しい。
今の所、テストがコケているのに気がついて直す人が私一人しかいない2ので、その辺をいい感じにしてくれる知見がある人を募集している。 具体的にはCircleCIでテストがfailした時に、適切な人間にそのfailを修正させたい。