⚡️

eslint-plugin-unicornでファイル名のケーススタイルを統一する

2024/09/18に公開

背景

ある日。

彡(゚)(゚) 「ファッ!? 基本ケバブケースでファイル名が作られてるのに、一部でスネークケースとキャメルケースが混じっとる!!」

という状況に直面しました。

Nest.jsで作っていたマイクロサービスで起こっており、基本的にキャメルケースで当初は命名が統一されていました。

が、別のマイクロサービス(Laravel)でModel(Actice Record)の定義などを先にしていたのをNest.jsにそのまま持ち込んだ際に、テーブル名がキャメルケースだったりすることもあり、そこから紛れ込み始めたものと思われます。

要するに、人為的なエラーです。

ということでこれを修正する

目に見えるケバブケース以外のファイル命名は潰せましたが、本当潰し切れているか。あるいはこれから先も同じようなことが起こらないかが気になるところ。

こんなときの解法がlinterによる静的解析です。

ということで「eslintにそういうルールを持ったpluginがないかな〜」と探していたところ見つけたのがeslint-plugin-unicornです。

セットアップ

npm install --save-dev eslint-plugin-unicorn
import eslintPluginUnicorn from 'eslint-plugin-unicorn';
export default [
  {
    files: ['src/**/*.ts'],
    plugins: {
      unicorn: eslintPluginUnicorn,
    },
    rules: {
      ...eslintPluginUnicorn.configs.recommended.rules,
    },
  },
];

ファイル名を統一するルールを追加

先の問題を解決すべく、ファイル名を統一するルールを追加します。

Recommend設定であればデフォルトでケバブケースが有効になっています。

ケバブケースに限らずキャメルケースのみに統一したり、あるいはキャメルとケバブの混在なども可能です。

今回はRecommend設定は使わず、特定のルールだけを有効にしておきたいため以下のように明示的に設定します。

import eslintPluginUnicorn from 'eslint-plugin-unicorn';
export default [
  {
    files: ['src/**/*.ts'],
    plugins: {
      unicorn: eslintPluginUnicorn,
    },
    rules: {
      'unicorn/filename-case': [
        'error',
        {
          cases: {
            kebabCase: true,
          },
        },
      ],
    },
  },
];

https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/filename-case.md

以上を設定し、npm run lintなどで静的解析を実行すると以下のように怒ってくれるようになりました。

src/common/StructuredLogger.ts
  1:1  error  Filename is not in camel case. Rename it to `structured-logger.ts`  unicorn/filename-case

他に便利なルールをいくつかご紹介

表題の問題はこれで解決なのですがドキュメントを見ていると他にも便利なルールがいくつかあったので、せっかくなのでご紹介したいと思います。

expiring-todo-comments

単純にコメントされた TODO がある場合に怒ってくれます。

TODO とすることは必要な場合もありますが、それだけ書いた場合永遠に放置されてしまうことがほとんどです。

そのためこのルールでは期限を明記することが求められるようになります。

https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/expiring-todo-comments.md

33:9  error  Unexpected 'todo' comment without any conditions: 'TODO #1 負荷試験時に適切なコネクションプールを設定する'  unicorn/expiring-todo-comments

ただし、明確に期日を明記できることは稀なため、多くの場合issueやチケットの番号などを記載するかと思います。

そういったパターンに対応できるよう、正規表現で無視するルールを定めることが可能です。

以下のように設定した場合、「#1」のようにissueの番号を含むTODOコメントは無視してくれます。

  {
    files: ['src/**/*.ts'],
    plugins: {
      unicorn: eslintPluginUnicorn,
    },
    rules: {
      // 省略
      'unicorn/expiring-todo-comments': [
        'error',
        {
          ignoreDatesOnPullRequests: true,
          allowWarningComments: false,
          ignore: ['#\\d+'],
        },
      ],
    },
  },

no-useless-undefined

https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-useless-undefined.md

無意味なundefinedが存在する場合エラーにしてくれます。

無意味なundefinedとは次のようなパターンです。

let foo = undefined;

function foo() {
	return undefined;
}

これはRecommendで設定した場合、デフォルトで有効になっています。

no-unused-properties

https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-unused-properties.md

賛否両論あるところかと思いますが、有効にした場合objectに未使用のプロパティがあった場合は怒ってくれるようになります。

ただ、objectのプロパティが後から未使用になった場合も修正を強要されてしまうため、1度のPRでの修正範囲が広範になる可能性があります。

その考えが根底にあるからか、Recommend設定では無効になっています。

が、筆者としては先の状況でも一度のPRで修正し切るべきというスタンスなので、有効にしておいても良いのではと考えています。

no-null

nullを明示的に利用していた場合に怒ってくれます。

しばしば取り沙汰される 「undefinedを使え vs nullを使え問題」にてundefinedに寄せる場合はこのルールによって全体的に統一が可能になりそうです。

このルールはRecommend設定で有効になっています。

https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-null.md

おわりに

「ファイル名の命名が気づいたらバラバラになってた…」はよくある話だと思うので、設定しておきたいですよね。

あとこの解析を「VSCode拡張機能とかでできるよ〜」っていうのをご存知の方がいらっしゃれば是非ともコメント欄で教えていただきたいです🙏

Discussion