Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ESLintの独自ルール作成にチャレンジした話

meijin
January 19, 2022

 ESLintの独自ルール作成にチャレンジした話

meijin

January 19, 2022
Tweet

More Decks by meijin

Other Decks in Technology

Transcript

  1. 自己紹介 ニックネームは「名人」 Twitter: @Meijin_garden Web エンジニア6 年目 株式会社NoSchool CTO オンライン家庭教師マナリンク

    -> https://manalink.jp 好きな分野はWeb フロントエンド 最近はWYSIWYG ライブラリのSlate.js に感動した 趣味は将棋(アマチュア二段くらい)
  2. 独自ルールの大まかな手順 今回は以下の手順で独自ルールを動作させることができた。 独自ルールを記述したJavaScript(or TS) ファイルを作成して、 rules ディレクトリに置く npm scripts で

    "lint": "eslint --rulesdir rules" のように記述して実行 ※ --rulesdir オプションはDeprecated なので、他の方法が有力(後述) https://eslint.org/docs/user-guide/command-line-interface
  3. ルールを記述する JS ファイルの構造 meta と create から構成される大きなオブジェクトをexport する 1 module.exports

    = { 2 meta: { 3 type: "suggestion", 4 // ... 5 }, 6 7 create(context) { 8 return { 9 VariableDeclaration(node) { 10 // ... 11 } 12 }; 13 14 } 15 };
  4. AST とはなにか ( 広義には) 文字列で表現されたプログラムから演算子や変数など、文法的に意味のある情報のみを取り出して、 木構造で表現したもの プログラムは、【プログラム全体-> 複数のクラス-> 複数の関数-> 複数の変数宣言や代入など】といったように木構造で表現できる

    分解した各部品のことをノードという プログラムを木構造で表現すると、プログラムから扱いやすくなる ESLint などの「プログラムを意味的に解釈して何らかの動作をするもの」を実装しやすくなる( 他にもbabel とか、Prettier とか、 esbuild とかも多分そう)
  5. create に Lint ルールを実装する 引数 context に含まれる、エラーや警告をレポートする report() 関数や、node から変数名を取得できる

    getDeclaredVariables() 関数を活用して、便利にルールを実装できる 1 // 変数名が _ から始まっていたらエラーになる独自ルールの例 2 create(context) { 3 return { 4 VariableDeclaration(node) { 5 context.getDeclaredVariables(node).forEach(variable => { 6 const name = variable.name; 7 if (name.charAt(0) === "_") { 8 context.report({ 9 node, 10 messageId: "unexpected", 11 data: { name } 12 }); 13 } 14 }); 15 } 16 }; 17 } VariableDeclaration が変数宣言ノードの種類名. context.getDeclaredVariables() で変数名を全取得. context.report() でLint 結果をレポート.
  6. テストの書きかた 1 const rule = require("../no-underscore-prefix"), 2 RuleTester = require("eslint").RuleTester;

    3 const ruleTester = new RuleTester(); 4 ruleTester.run("no-underscore-prefix", rule, { 5 valid: [ 6 "'hoge'", 7 // ... 8 { code: "const obj = { _name: 'hoge' };", env: { es6: true } }, 9 ], 10 invalid: [ 11 { 12 code: "var _hoge = 'hoge';", 13 errors: [{ messageId: "unexpected", data: { name: "_hoge" }, type: "VariableDeclaration", 14 }, 15 // ... 16 { code: "let x,_y = 'hoge';", env: { es6: true }, errors: [{ messageId: "unexpected", data: { 17 // ... 18 ] 19 }); RuleTester を使ってテストを実装. valid / invalid キーで正常系と異常系を書く. RuleTester のコンストラクタでオプションも色々 設定できるらしい.