VSCodeでRuby書くにあたってコード整形とか構文チェックとかが自動で走るようにした


背景

自分はこれまで主にEmacsを使ってコーディングをしてきており、たまにAtomを使ってきました。
特にこれらの開発環境に不満があったわけでもありませんが、goやelixierで標準装備されているコードの自動整形をRubyでも使いたくなり調べた所、色々方法はありましたがエディタと一体化させて使う上ではVSCode+Prettier(自動整形)+RuboCop(構文チェック)が便利そう且つ簡単そうだったので使ってみることにしました。
VSCodeはWindows, MacOS, Linux等の各OS向けバイナリがマイクロソフトから無料で提供されています。
ちなみに既存のコードはUTF-8が多いものの、まだEUC-JPのような文字コードのファイルも残っている。

ゴール

以下のことを満たしたい。

  1. 文字エンコーディングの自動判別。
  2. リアルタイムなコードの自動整形。不必要な行・スペースや間違ったインデントなどはファイル保存のタイミングで自動修正して欲しい。
  3. リアルタイムな構文チェック。おかしな書き方をしたらエディタ上で即時警告して修正を促して欲しい。

VSCodeのインストール

VSCodeのサイトから対象OS向けのバイナリを落としてインストールします。

関連する拡張機能をインストール

メニューのExtensionsから必要な拡張機能をインストールします。私は以下をインストールしました。

  • Ruby
  • VSCode Ruby
  • Prettier - Code formatter
  • Remote - SSH
  • Remote - SSH: Editing Configuration

Prettier はコードの自動整形を行ってくれるツールで、後述の設定をすればファイル保存時に自動的にコードの整形を行ってくれます。
Remote - SSH は自分のPCではないリモートに有るファイルを開いて編集するためにインストールしました。最近はDockerなどで実行環境をそのまま自分のPCに立ち上げることも多いと思いますが、それでもリモートのサーバー上のファイルを直接編集したいことも有るのでインストールしました。

ファイルエンコーディングを自動判別する設定

現代の殆どのプログラムはUTF-8で書かれていますが、それでも古いエンコーディング、例えばEUC-JPで書かれたソフトウエアを修正する必要に迫られることがあります。
VSCodeはデフォルトで UTF-8 でファイルを開いたり書き込んだりしますので、EUC-JPやShift-JISで書かれたプログラムは文字化けしてしまいます。
そういう場合はVSCode画面の右下の UTF-8 と表示しているところをクリックして、画面上部に示された選択肢から Reopen with Encoding を選択、続いて実際のエンコーディングを選択すれば文字化けせずに表示できます。

ただ、できればはじめから自動判別してほしいものです。
その場合、
1. Preferences -> Settings と選択。
2. 検索窓に encoding と入力。
3. Files:Auto Guess Encoding に☑チェックマークを入れる。
4. Files: Encoding が UTF-8 であることを確認。

以上でファイルオープン時に自動的にエンコーディングを判別して開いてくれます。
なお、開いたファイルのエンコーディングを変更して保存したい時は、先ほどと同じように画面右下の UTF-8 などの所をクリックし、画面上部に示された選択肢から今度は Save with Encoding をクリックすれば保存する文字コードを選択できます。

コードの自動整形を行うための準備

まずはnode関連の必要なものを入れます。実際に書くコードはRubyなのにnode.jsまわりのものに依存するのは面白くない方もいらっしゃると思います。それももっともで私もそう感じたところは有るのですが、最初にRubocopにチャレンジしたところ、なかなか思ったようにならず、Prettierを使った所すぐに環境ができたのでこちらにしました。ここは好みも有ると思います。

yarnをインストールする。

これは開発を実際にするサーバー上で必要ですので注意してください

  • Ubuntu系のLinuxなら
    • $ sudo apt install npm
    • $ npm install -g yarn
  • MacOSなら
    • $ brew install yarn

です。

今回編集するプロジェクトのディレクトリに移動し以下を実行。

$ yarn init

質問に答えて準備完了。prettierをインストールします。

$ yarn add -D prettier @prettier/plugin-ruby

コマンドラインからコードの自動整形を行う

最も簡単な方法は単一ファイルに対して整形を実行する方法です。

$ ./node_modules/.bin/prettier --write lib/hoge.rb

ただしこれだとファイルがたくさん有る場合に面倒です。先程の $ yarn init で自動生成された package.json に以下を追記します。(このpackage.jsonはこの後の内容も含みます。)

package.json
{
  "license": "UNLICENSED",

  "dependencies": {
    "@prettier/plugin-ruby": "^1.5.2"
  },
  "devDependencies": {
    "prettier": "^2.2.1"
  },
  "scripts": {
    "format": "find ./src -name *.rb | xargs node_modules/.bin/prettier --write",
    "lint": "bundle exec guard"
  }
}

これで
$ yarn format

のように実行すると、lib ディレクトリ以下のファイルが全て自動整形されます。
Railsプロジェクトの場合は、ここが "format": "find ./app -name *.rb | xargs node_modules/.bin/prettier --write" のようになると思います。

ファイル保存時に自動的に整形されるように設定する

  1. VSCodeの Preferences -> Settings を開く。
  2. 画面右上のファイルのような形をしたアイコン(Open Settings (JSON))をクリックし、Settings.jsonを開く。
  3. 下記を追記する。
    • formatOnSave をtrueにすると、保存時にファイル全体をフォーマット
    • formatOnType をtrueにすると、タイプ時にその行のみをフォーマットしてくれます。
{
    "[ruby]": {
        "editor.formatOnSave": true,
    },

    "editor.formatOnSaveTimeout": 5000,
    "prettier.packageManager": "yarn",
    "prettier.jsxSingleQuote": true
}

念の為、一度VSCodeを終了して再度立ち上げてください。これで保存時に自動的に整形されるようになったはずです。

RuboCopでコードチェック

自動整形まで来たら、こんどはコードが規約に沿っているかどうかリアルタイムにチェックしたくなります。
RuboCopを使ってVSCodeでファイルが編集されたときにチェックを入れることもできますが、これをするとRuboCopのチェックに引っかかると先の自動整形が行われなくなり、実質自動整形は意味がなくなります。
そこで、VSCodeは自動整形を走らせるものとし、RuboCopはGuardを使ってコマンドラインで走らせます。

Gemfileに必要なライブラリを書いて $bundle install し、rubocopを初期化します。

Gemfile
source 'https://rubygems.org'

group :development do
  gem 'guard', require: false
  gem 'guard-rubocop', require: false
  gem 'rubocop', require: false
end
$ bundle install --path=.bundle ( or $ bundle update )
$ bundle exec rubocop --auto-gen-config

生成された .rubocop.yml に以下を設定。
FrozenStringLiteralComment をfalseに設定しているのは、rubocopが問題ないコメントに対しても警告を出すのを防ぐためです。

rubocop.yml
inherit_from: .rubocop_todo.yml

Style/FrozenStringLiteralComment:
  Enabled: false

Guardを初期化します。

$ bundle exec guard init rubocop

guardを起動する。

$ bundle exec guard

19:05:44 - INFO - Inspecting Ruby code style of all files
Inspecting 4 files
....
4 files inspected, no offenses detected
[1] guard(main)>

こんな感じに実行されたらOK。あとは生成されたGuardfileに記述されているとおり、拡張子が .rb.yml のファイルが編集されるたびにrubocopが走る。
なお、このエントリーの上の方で package.json のなかの scriptlint としてguardを実行するようにしているので、

$ yarn lint

でも同様にrubocopが走る。

さらにVSCodeは cmd+shift+m でコンソール画面が開くため、そこで

$ yarn lint

しておけば、コード編集するたびに自動整形と構文チェックが行われることになる。
下のスクショはその画面。画面下部でguard+rubocopが走っており、修正箇所をリアルタイムに見つけてくれる。VSCode一つでコーディング、自動整形、構文チェックする環境ができた。