RuboCop 1.24.0 と Ruby 3.1 対応

RuboCop 1.24.0 がリリースされました。

github.com

このリリースでは Ruby 3.1 のリリースに先行して、いくつかの Ruby 3.1 対応が入っています。

RuboCop の Ruby 3.1 対応の主だったものについて、ユーザー影響のありそうなものをピックアップして記しておきます。なお、現状で Ruby 3.1 サポートは experimental という位置づけです。

既存の Style/HashSyntax による hash value omission サポート

既存の Style/HashSyntax で、Ruby 3.1 の hash value omission をサポートするようにしています。

github.com

bad / good は以下。

# EnforcedShorthandSyntax: always (default)

# bad
{foo: foo, bar: bar}

# good
{foo:, bar:}


# EnforcedShorthandSyntax: never

# bad
{foo:, bar:}

# good
{foo: foo, bar: bar}

デフォルトではハッシュの値を省略できるケースはすべて省略する always オプションが適用される。これは ESLint のデフォルトに準拠させたことが理由のひとつ。

今月の Rails/OSS パッチ会 (2021年12月) で、この辺りを話題にしたところ、osyo さんの「ハッシュのキーと値が同じ場合は書かず、異なる (意図のある) 値は明示的に書く」というのは、考え方としてすっきりした。Ruby 3.0 から Ruby 3.1 への移行によって「省略可能できるようになったか」ではなく、もし最初から hash value omission を備えた言語だったら?という考え方と言えるのかもしれない (システム開発でのあるべき姿への考え方っぽい) 。

なお、最近の Ruby の構文変更では大きなもののようで、私が仕事で見ている Rails アプリケーションのひとつで、この Style/HashSyntax をドッグフィーディングしたところ、3,000 以上が hash value omission の対象になりました。

このようにインパクトはそれなりにありそうなものの、いかんせん周辺で事例が少なくて「Hash の書き方が、こうなるのどうですか?」と EnforcedShorthandSyntax: always 適用後の感想をヒアリングしても、「 (シンタックスへの) 慣れなのかな?」みたいな感じで戸惑いがまだありそうな感じなので、Cop 自体に調整は入っていくかもしれないです。 (3値での調整の余地を残せるように、UseShorthandSyntax: true のような真偽値ではなく、EnforcedShorthandSyntax: always といった文字列というデザインにもしているのだった)

そのほか、Layout/HashAlignment cop と Layout/SpaceAfterColon cop について、hash value omission を使った際にレイアウト崩れが起きないような対応を入れています。

新規 Naming/BlockForwarding cop による anonymous block forwarding サポート

既存の Naming/BlockForwarding で、Ruby 3.1 の anonymous block forwarding をサポートするようにしています。

github.com

bad / good は以下。

# EnforcedStyle: anonymous (default)

# bad
def foo(&block)
  bar(&block)
end

# good
def foo(&)
  bar(&)
end

# EnforcedStyle: onymous

# bad
def foo(&)
  bar(&)
end

# good
def foo(&block)
  bar(&block)
end

デフォルトでは anonymous block argument syntax が適用されます。これはブロック変数が概ね &block&proc に準ずる名前で、構文上 & にしても情報落ちはないだろうという理由から。反対に従来の記法に強制したい向けに explicit というオルタナティブを用意しています。なお、こちらも Style/HashSyntax 同様に、今後フィードバック次第で調整が入っていくかもしれません。

これらの変更は、RuboCop 1.24.0 で TargetRubyVersion: 3.1 の設定で試してみれます。それぞれの Cop にオートコレクトを実装しておいたので、新しい構文の世界を見てみたい方、お試しください。

なお、執筆時点の、Ruby 3.1 への構文アップデート自体については以下をどうぞ。

koic.hatenablog.com