kachick / times_kachick

`#times_kachick channel in chat` as a public repository. Personal Note and TODOs
https://github.com/kachick/times_kachick/issues?q=is%3Aissue+is%3Aclosed
6 stars 0 forks source link

2023-02-07 - rubocop を dprint の plugin っぽく走らせる #209

Closed kachick closed 1 year ago

kachick commented 1 year ago

最近触る言語は大抵 オフィシャルかデファクトの高速な formatter を備えている。慣れるとやはり楽…… Ruby は 歴史の積み重ねから公式のフォーマットというのはまだ無いのかな? (tDiary とかハードタブ且つ3だったし) それはそれで良いと思うんだけど、自分で書いてても微妙なインデントミスとか一々直すの嫌なので、リポジトリ単位で決める手段ぐらいは欲しい rubyfmt というのが合って確かに結構早いんだけど、パターンマッチへ未対応だったりダブルクォート強制だったりで自分は避けてる

(デフォルトにいきなり強い主張を放り込んでくるのでプチプチoffにする事も多いけれど)機能面が充実していてカスタマイズの手段も用意されているということから 結局 rubocop をフォーマッタとして使っている 基本的に早くは無いんだけど、CIで回す分にはそんな困ってなかった。厄介なのは vscode との integration 方法で、 vscode-ruby はメンテナンスを止めてて https://github.com/rubyide/vscode-ruby/commit/dc81c809c82003d26af9c4dc7c89fa8f8a26cbf5 、 rubocop 連携エラーへの修正 https://github.com/rubyide/vscode-ruby/pull/647 がずっとリリースされていない ref: https://github.com/rubyide/vscode-ruby/issues/227, https://github.com/rubyide/vscode-ruby/pull/825

あまりこの辺頑張る気力もなく、フォークしてどうこうみたいなのは考えてなかった。そもそも単にフォーマッタとして走らせたいだけなので https://github.com/pucelle/vscode-run-on-save みたいなアプローチも検討したけど、 config に色々増えるし時間はかかるとうーむだった。また色んなフォーマッタを一つにまとめる https://github.com/numtide/treefmt みたいなプロジェクトもあるんだけど、 dprint 以外の物まで増やしたくはない。なんとか dprint にやらせるとしたら、 Wasm で ruby と rubocop を固めるとかなのかな・・・? と dprint の org を漁ってたら https://github.com/dprint/dprint-plugin-exec というのが合った。

これがまさに他のフォーマッタとの連携を dprint にさせる手段の一つで、標準入出力でフォーマット掛けられる物なら何でも巻き取れそう rubocop に一杯あるオプションを改めて漁ると、この形式にも対応してくれてた

$ rubocop --autocorrect --stdin file_path --stderr
Autocorrection:
    -a, --autocorrect                Autocorrect offenses (only when it's safe).
        --auto-correct               (same, deprecated)
        --safe-auto-correct          (same, deprecated)
    -A, --autocorrect-all            Autocorrect offenses (safe and unsafe).
        --auto-correct-all           (same, deprecated)
        --disable-uncorrectable      Used with --autocorrect to annotate any
                                     offenses that do not support autocorrect
                                     with `rubocop:todo` comments.

似たようなオプションが一杯合って引っかかりそうになるけど、とりあえず safe 以外で auto format する気にならないのでこんな感じにしている

dprint-plugin-exec 側はこんな感じに dprint.json へ設定する

{
  "exec": {
    "associations": ["**/*.{rb,gemspec,rake}", "Rakefile", "Gemfile", "Steepfile"],
    "rubocop": "bundle exec rubocop --autocorrect --stdin {{file_path}} --stderr",
    "rubocop.associations": "**/**"
  },
  "includes": ["**/*.{json,md,yml,html,css,rb,gemspec,rake}", "{Rakefile,Gemfile,Steepfile}"]
}

associations 側では他の箇所みたいに複数 glob に対応していない https://github.com/dprint/dprint-plugin-exec/blob/94ed0fe3fac6a631c5e3e00538f29c30770a0738/src/configuration.rs#L165-L173 ということなので、更に他の外部プラグインとは連携させづらい強引な config なんだけど、今のところは足りている。 nix の formatter とかも巻取りたくなってきたけど、まぁそのうち誰かが直してくれるのでは・・・

しかし dprint.json を単純に拡張すると、高速なはずの dprint が常に rubocop へ引っ張られて重々になる。なので dprint 用の config を分割する必要があるんだけど、https://github.com/dprint/dprint-vscode は config path 変更に対応しておらず、サクッと対応させるのも難しそうだったので https://github.com/dprint/check 側へ変更コードを入れてもらった https://github.com/dprint/check/commit/23e4f056b94440b959d779df4ba14c987b4da350

最終的にはこうなる

https://github.com/kachick/ruby-gem-template/blob/40c1ee9605359e548b959b3151c402c815167806/dprint-ci.json#L1-L22 https://github.com/kachick/ruby-gem-template/blob/40c1ee9605359e548b959b3151c402c815167806/dprint.json#L1-L22

rubocop の servermode を有効にしておくと走るまでの間が大分改善するんだけど、vscode でワークスペース開いた時に有効化出来ても、閉じる時に上げた時のサーバーを落とさせるみたいなのが難しそう https://github.com/microsoft/vscode/issues/65986 で手動でやってる。

$ bundle exec rubocop --start-server
$ bundle exec rubocop --stop-server
kachick commented 1 year ago

https://github.com/rubocop/vscode-rubocop が必要最低限かつ十分といった動きをしてくれるので、vscodeでこれを使わない理由はないと思う。 ということで、この目的で dprint-plugin-exec は使わなくなった