ESLintのカスタムルールを作る機会があったので手順とかメモ📝
公式Doc
ESLintのカスタムルールの作り方MEMO
カスタムルールを配置するディレクトリを作成する
以下のような形で任意のディレクトリを作成します。
mkdir eslint/rules
カスタムルールの雛作る
公式Docを参考にRuleの雛形を作成します。(以下はすべてのコードでsample rule!!
の警告を出すLint)
"use strict"; /** @type {import('eslint').Rule.RuleModule} */ module.exports = { meta: { type: "suggestion", // type (string) indicates the type of rule, which is one of "problem", "suggestion", or "layout": docs: { description: "sample rule", }, fixable: null, // fixable (string) is either "code" or "whitespace" if the --fix option on the command line automatically fixes problems reported by the rule schema: [], // no options }, /** @param {RuleContext} context */ create: function (context) { return { /** @param {Program} node */ Program(node) { context.report(node, "sample rule!!"); }, }; }, };
カスタムルールを実行するようにconfig及び実行コマンドを修正
作成したファイル名(拡張子なし)をrulesに追加して有効化し、
"rules": {
++ "sample-rule": 1
},
--rulesdir カスタムルールを配置したディレクトリパス
を付けてESLintを実行するようにする。
# 例) $ npx eslint app/javascript spec/javascript --ext .vue,.js,.ts --rulesdir eslint/rules
カスタムルールを作成
ESLintはASTをゴニョゴニョしてコードを解析できるので検知したいコードのASTを以下のサイトで解析してコードを検討する。
例えばconsole.log("Hello world!!")
を検知するようなルールを作りたい場合は以下のようなコードで検知できる。
"use strict"; /** @type {import('eslint').Rule.RuleModule} */ module.exports = { meta: { type: "problem", docs: { description: "sample rule", }, fixable: "code", schema: [], // no options }, /** @param {RuleContext} context */ create: function (context) { return { /** @param {CallExpression} node */ CallExpression(node) { if ( node.callee.type === "MemberExpression" && node.callee.object.type === "Identifier" && node.callee.property.type === "Identifier" && node.callee.object.name === "console" && node.callee.property.name === "log" && node.arguments[0].type === "Literal" && node.arguments[0].value === "Hello world!!" ) { context.report(node, "sample rule!!"); } }, }; }, };
以下のように検知できる🎉
$ eslint app/javascript spec/javascript --ext .vue,.js,.ts --rulesdir eslint/rules 23:1 warning sample rule!! sample-rule
終わりに
ESLintのカスタムルール、意外と手軽に作れて便利ですね🙌