発表資料: sonarish で俺がお前を叱る

## 自己紹介

- mizchi
- フリーランス
- リクルートでは yosuke_furukawa の元でR&Dみたいなことをしている

---

## 飛び入りLT用(発表ないかも)

---

## yosuke_furukawa 「コードメトリクスツール作って」

---

## コンテキスト

- リクルート社内に膨大なJS含むプロジェクトがある
- JSを(僕や yosuke_furukawa ぐらいに)真っ当に書ける人が少ない
- いろんなプロダクトを串刺しでスコアリングして可視化したい

---

## eslint は？

- プロジェクトごとに運用のされ方が違う || そもそもない
- 「1件でも落とすと exit-status = 1」 なので攻めたルールを採用しにくい

---

## どうせだったらOSSにしようぜ => はい

---

## ※ 画面は開発中のものです

---

## sonarish (仮)

```
$ npm i -g sonarish-cli
$ cd your-repo
$ sonarish src
```

---

## 実行例

```
$ cd sonarish
$ sonarish --detail
--- complexity
score: 96.4/100
┌──────────────────────┬───────┬──────────┬───────┐
│ rule                 │ score │ priority │ count │
├──────────────────────┼───────┼──────────┼───────┤
│ no-shadow            │ -2.6  │ 2        │ 2     │
├──────────────────────┼───────┼──────────┼───────┤
│ mutation/no-mutation │ -0.9  │ 1        │ 1     │
└──────────────────────┴───────┴──────────┴───────┘
--- best-practice
score: 92.9/100
┌───────────────────────────────────┬───────┬──────────┬───────┐
│ rule                              │ score │ priority │ count │
├───────────────────────────────────┼───────┼──────────┼───────┤
│ import/no-extraneous-dependencies │ -2.5  │ 3        │ 4     │
├───────────────────────────────────┼───────┼──────────┼───────┤
│ no-console                        │ -2    │ 1        │ 22    │
├───────────────────────────────────┼───────┼──────────┼───────┤
│ no-unused-vars                    │ -1.8  │ 1        │ 18    │
├───────────────────────────────────┼───────┼──────────┼───────┤
│ compat/compat                     │ -0.6  │ 1        │ 2     │
└───────────────────────────────────┴───────┴──────────┴───────┘
--- meta-comments
score: 63.8/100
┌───────────────────────────────────┬───────┬──────────┬───────┐
│ rule                              │ score │ priority │ count │
├───────────────────────────────────┼───────┼──────────┼───────┤
│ no-warning-comments               │ -20.2 │ 4        │ 4     │
├───────────────────────────────────┼───────┼──────────┼───────┤
│ eslint-comments/no-use            │ -7.9  │ 1        │ 10    │
├───────────────────────────────────┼───────┼──────────┼───────┤
│ eslint-comments/no-unused-disable │ -7.9  │ 1        │ 10    │
└───────────────────────────────────┴───────┴──────────┴───────┘

```
---

## babel/babel

```
--- complexity
score: 61.1/100
┌──────────────────────┬───────┬──────────┬───────┐
│ rule                 │ score │ priority │ count │
├──────────────────────┼───────┼──────────┼───────┤
│ no-param-reassign    │ -15.7 │ 3        │ 106   │
├──────────────────────┼───────┼──────────┼───────┤
│ no-shadow            │ -9.2  │ 2        │ 78    │
├──────────────────────┼───────┼──────────┼───────┤
│ max-lines            │ -5.5  │ 2        │ 28    │
├──────────────────────┼───────┼──────────┼───────┤
│ mutation/no-mutation │ -5.2  │ 1        │ 601   │
├──────────────────────┼───────┼──────────┼───────┤
│ no-unreachable       │ -2.9  │ 4        │ 2     │
└──────────────────────┴───────┴──────────┴───────┘
--- best-practice
score: 86.4/100
┌───────────────────────────────────┬───────┬──────────┬───────┐
│ rule                              │ score │ priority │ count │
├───────────────────────────────────┼───────┼──────────┼───────┤
│ prefer-arrow-callback             │ -4.8  │ 2        │ 503   │
├───────────────────────────────────┼───────┼──────────┼───────┤
│ import/no-extraneous-dependencies │ -3.6  │ 3        │ 25    │
├───────────────────────────────────┼───────┼──────────┼───────┤
│ promise/always-return             │ -2    │ 2        │ 17    │
├───────────────────────────────────┼───────┼──────────┼───────┤
│ no-console                        │ -1.2  │ 1        │ 25    │
├───────────────────────────────────┼───────┼──────────┼───────┤
│ eqeqeq                            │ -0.8  │ 1        │ 13    │
├───────────────────────────────────┼───────┼──────────┼───────┤
│ import/no-mutable-exports         │ -0.6  │ 2        │ 2     │
├───────────────────────────────────┼───────┼──────────┼───────┤
│ no-unused-vars                    │ -0.2  │ 1        │ 1     │
└───────────────────────────────────┴───────┴──────────┴───────┘
--- meta-comments
score: 34.1/100
┌───────────────────────────────────┬───────┬──────────┬───────┐
│ rule                              │ score │ priority │ count │
├───────────────────────────────────┼───────┼──────────┼───────┤
│ no-warning-comments               │ -49.4 │ 4        │ 75    │
├───────────────────────────────────┼───────┼──────────┼───────┤
│ eslint-comments/no-use            │ -9.2  │ 1        │ 42    │
├───────────────────────────────────┼───────┼──────────┼───────┤
│ eslint-comments/no-unused-disable │ -7.1  │ 1        │ 25    │
└───────────────────────────────────┴───────┴──────────┴───────┘

```

---

## オプション

```
$ sonarish [--root <root-path>] [--detail] 'src/**' 'subdir/**'
```

---

## sonarish の 設計

- 空白のスタイリングなどには関与しない(prettierでやれ)
- ルールが落ちることを前提に、エラーカウント/合計ファイル数 で減点
- 複数のカテゴリごとにeslintのルールセットを作る
- カテゴリ内の priority を設定

---

## 「攻めたルール」の例

- object-rest-spread あれば代入なんていらねーよな!
- クラス以外で this なんてつかわねーよな!
- 二重 if / switch はダサいよな!
- 複雑な論理オペレータのネストはダサいよな!
- TODOコメントなんて残んねーよな！

---

## ダサいを可視化する

- いわゆる codesmell の検出
- 自分でそのためのeslintルールを書いてる(既存のものにそういうルール集はあんまりない)

---

## スコアリングルール

そのルールの (エラー数/総ファイル数) * (priority/合計priority) 

(実際は細かい正規化とスレッショルドがいっぱいあって調整中)

---

## TODO

- 自分でスコアルールを書けるようにする
- ソースの公開
- eslint 以外のツール対応
  - package.json の health check
  - コピペ検出
  - etc...

---

## わかったこと

- no-unused-vars は結構効く
- TODO コメントはめっちゃ残ってる
- eslintをまともに運用してるように見えてもeslint-disableを数えると結構やばい