RuboCopファミリーと周辺の更新 (GW 2021編)

GW に更新のあった RuboCop 周辺のアップデートについてざっくりまとめておく。

Parser 3.0.1.1

github.com

RuboCop が依存する Ruby構文解析の Gem で、Ruby 3.0 で入った endless method definition のバグ修正と Ruby 3.1 (dev) のサポート追加をしている。

Ruby 3.0 で導入された endless method definition は以下のように = で終わる writer メソッドは定義できない。

% ruby -cve 'def foo=(foo) = @foo = foo'
ruby 3.0.1p64 (2021-04-05 revision 0fb782ee38) [x86_64-darwin19]
-e:1: setter method cannot be defined in an endless method definition
def foo=(foo) = @foo = foo

それについて method_name.end_with?('=') でマッチさせていたので、受け入れられるべき比較演算子 (e.g. ==) となるメソッド定義までエラーにしていたという Parser gem のバグだった。

Ruby 3.1 (dev) のサポートについては、パターンマッチの新構文となる pin オペレータをサポートするようになった。大元のサンプルから持ってくると ^ を使った式をこんな感じでパターンマッチ中で取れるようになります。夢がありそうな拡張。

Prime.each_cons(2).lazy.find_all { _1 in [n, ^(n + 2)] }.take(3).to_a
#=> [[3, 5], [5, 7], [11, 13]]

RuboCop 1.4

github.com

Ruby 3.1 (dev) をサポートしました。また、Bundler/GemVersion cop と Layout/SingleLineBlockChain cop がデフォルト無効で追加されています。

Bundler/GemVersion は Gemfile に gem 指定するときにバージョンを必須にする cop だけれど、理由がなければバージョン指定するべきではないという見解でデフォルト無効です。個人的にはデフォルト無効ならまあ (コアに入れて) いいか。。。という気持ちです。 Layout/SingleLineBlockChain cop は、example.select { |item| item.cond? }.join('-') のようなチェーンを許可しない cop で、ふつうに厳しすぎるのでデフォルト無効は妥当だと思って見ていました。余談だけれど blockchain という用語は暗号資産を連想したという bbatsov のコメントがおもしろかった。

あと、RuboCop AST とそれが依存する Parser の依存バージョンを上げているので、bundle update --conservative rubocop でアップグレードしているようであれば、bundle update --conservative rubocop rubocop-ast parser あたりの依存 gem 指定をしないと 1.14 に上がらないかもしれません。

RuboCop AST 1.5

github.com

Ruby 3.1 (dev) をサポートしています。

RuboCop Performance 1.11.3

github.com

Performance/MapCompact cop の不具合修正をして v1.11.3 まで上がりました。あと互換のない compact.mapfilter_map に手動で置換されようとしたケースを rails/rails で見かけたので、それは検出しない旨をドキュメントとテストに追記しています。

RuboCop Rails 2.10

github.com

RuboCop Rails は半年くらいぶりのリリース。古めのイシューなんかもさらって、フィードバックにもとづいた cop の安全性などの見直しを入れており、2.9 系を調整した better バージョンな感じになっていると思います。RuboCop Performance 1.11 系と同様に、Ruby 2.4 のサポートを打ち切ったのと、今後のメジャーアップデートに向けて RuboCop 1.7.0 以上への依存に更新しています。古めのバージョンを使っているようであれば、あわせてアップデートが必要です。

ご活用ください。