Tech

ESLintの導入にあたりルール別のエラー数を出せるようにした

何かプロジェクトに参画したらタスクランナー入れようlint入れようformatter入れようが初手な今日この頃…。

そんな中でESLintのエラーログをルール別に集計してjsonを吐き出すスクリプトを作ったよという話と
こんな感じで進めると実際に導入まで(ルール詰めるのが)早いのではないのではという話です。

追記:stylelintのものも作りました。 -> stylelintの導入にあたりルール別のエラー数を出せるようにした

はじめに

ESLintをこれから導入しようってプロジェクトは数多にあると思います。
まさに最近自分が参画したプロジェクトもESLintを入れようという話がありました。

入れたい、入れる予定と言っているプロジェクトは多いと思いますが、
実際に入れようとするとルールの微調整等が結構手間で、
一年経っても「あれ?そういえば入ってないやん…」的なプロジェクトも多いと思います。

誰かがボール握らないプロジェクトは大体そんな感じになる所感(愚痴)
なのでそんな時はとりあえずボール持ちましょう。

「ワタシタタキダイツクッテモヨイデスカ?」

これを言ってみるだけで意外とOKが出ます。

できたもの

変な英語なのは許してください。そして大したことなくてすいません。

/**
 * Create eslint error report by type
 *
 *  result example:
 *  {
 *      "key-spacing": 1855,
 *      "comma-dangle": 743,
 *      "no-unused-vars": 304,
 *      ...
 *
 * Download Usage: node eslint-report.js "yarn run --silent ESLINT EXEC COMMAND HERE(required -f json option)"
 * Direct Usage Example(bash): node -e "$(curl https://gist.githubusercontent.com/isoppp/e799be580a4caf1605907bc1461a560e/raw/86f7b05edc94af25d1708d7aaed0f4b2c5e8dee6/eslint-reporter.js)" "yarn run --silent eslint --ext .js,.vue -f json src"
 */

const cmd = process.argv[process.argv.length - 1]
const spawnSync = require('child_process').spawnSync

const cmdResult = spawnSync(cmd, { shell: true, maxBuffer: 10000 * 1024 })
const log = JSON.parse(cmdResult.stdout.toString())

const report = {}
log.forEach(item => {
  item.messages.forEach(message => {
    const ruleId = message.ruleId
    if (report[ruleId] == null) report[ruleId] = 0
    report[ruleId] += 1
  })
})

console.log(JSON.stringify(report, null, '\t'))

使い方

無駄にローカルに落とさない方法を模索してみました。
ただ、何かこれじゃない感がすごいですが、一旦…

gistを直接叩く戦法です。bashでお願いしますとか縛りもきついです(多分zshも大丈夫です)

node -e "$(curl https://gist.githubusercontent.com/isoppp/e799be580a4caf1605907bc1461a560e/raw/86f7b05edc94af25d1708d7aaed0f4b2c5e8dee6/eslint-reporter.js)" "ここにeslintのformatをjson形式で出力するコマンド"

ここにeslintのformatをjson形式で出力するコマンド については大抵npmで入れている場合json出力していないと思うのとnpm周りのコマンドの実行ログも出てきちゃうとだめなので推奨としては yarn run --silent eslint ... となります。

追記

npm publish して npx で使えるようにすれば?と知人からアドバイス頂いたので使えるようにしました。

https://www.npmjs.com/package/eslint-report-by-rulehttps://www.npmjs.com/package/eslint-report-by-rule
usage: npx eslint-report-by-rule "yarn --silent run eslint --ext .js -f json ."

結果

こんな結果が出ます

{
  "vue/max-attributes-per-line": 119,
  "vue/html-self-closing": 27,
  "vue/mustache-interpolation-spacing": 7,
  "vue/attributes-order": 34,
  "vue/require-default-prop": 4,
  "vue/html-indent": 12
}

導入へ向けて

このログを利用すると上は極論なvueしかないデータですが、本当にプロジェクトによっては1000overのものも勿論出てきます。
ここから先はもう煮るなり焼くなり好きに使ってくださいという感じですがなんとなくこうしたらいいんじゃないかという話です。

  1. "vue/max-attributes-per-line": 119, こういう結果部分をスプレッドシートに貼り付けて区切り文字を : にして適当に " 等のゴミ文字を置換で消す
  2. その横に議論参加メンバーが設定に対するコメントを書く(これは切っても良いのでは?等)
  3. 意見が揃っているものについてはそのまま導入、揉めているもののみ話し合って設定を詰める

とすすめるとMTG最小限でルール確定までが早いのかなと思います。
決まったら後は導入して導入完了です。

余談的にはドキュメントのリンクもある程度どれもフォーマットが決まっているのでスプレッドシートでいうと、
=CONCAT(ルール名前までのURL,ルール名セル) という風にすれば簡単にドキュメントへのリンクも作成できます。
例: =CONCAT("https://eslint.org/docs/rules/", B2)

おわりに

余談1

ESLintのデフォルトcliで似たようなことができたらとても恥ずかしい
集計はおまけだったりしますが、エラーが出るルールの一覧ログとか出せないんですかね…

余談2

ESLintの実行結果のjsonがでかすぎるとmaxBuffer設定により出力が途中で途切れてしまいjsonにparseできずコケてしまいます。
こいつぁやべえというログの量だと思ったら maxBuffer を適宜調整してください

const cmdResult = spawnSync(cmd, { shell: true, maxBuffer: 10000 * 1024 })

余談3

色々制約が強いので読める人や編集できちゃう人はいい感じに書き換えつつコメントにコピペ頂けたらうれしいです
あとローカルに持たずに実行するコマンドも違う感すごいですが、結構詰んでるのでわかったら教えて頂きたいです。

share