Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
ESLintの独自ルール作成にチャレンジした話
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
meijin
January 19, 2022
Technology
910
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
ESLintの独自ルール作成にチャレンジした話
https://rakus.connpass.com/event/232039
meijin
January 19, 2022
More Decks by meijin
See All by meijin
AI時代のコードレビューは人に向けるな、仕組みに向けろ
texmeijin
5
3.7k
Technical Decisions and Reflections on "Test Maker" After Two Years of Development
texmeijin
1
150
弊社の「意識チョット低いアーキテクチャ」10選
texmeijin
5
27k
DDDを志して3年経ったら「DDDの皮を被ったクリーンアーキテクチャ」になった話【デブサミ2024夏】
texmeijin
4
4.6k
サービス黎明期にNuxt.js v2からNext.js移行を決めた理由と進め方
texmeijin
0
580
スタートアップCTOが個人開発で収益化・年13本記事発信・5件登壇を平行するための時間管理
texmeijin
4
1.3k
個人開発がおすすめな理由
texmeijin
3
1.1k
弊社の開発体験の良いところは?メンバーに訊いてみた!
texmeijin
0
520
初めてESLintプラグインにコントリビュートした話
texmeijin
0
300
Other Decks in Technology
See All in Technology
AIにシークレットを見せない、WSL2で安全な開発環境
yazm
0
310
SAENM ~Jupyterで残すPoCの試行錯誤、未来の自分と仲間を助ける記録!~
terapyon
0
120
僕のハーネスを紹介します
watany
3
120
ブラウザとサーバーから考えるAI時代のフロントエンド監視
shogo4131
3
1k
Railsで挑む大量データ永続化 〜600億件を永続化するための設計とボトルネックとの戦い〜
occhi
1
830
Conditional PED-ANOVA: Hyperparameter Importance in Hierarchical & Dynamic Search Spaces
pfn
PRO
0
140
アウトプット初心者、半年間のふりかえり
4o1sobblue
0
450
トークン化預金DCJPYの取り組みと活用ユースケース
finengine
0
180
二歩目のフロントエンド・ウェブアクセシビリティ
camiha
2
670
大型犬好きによるPugの紹介
yamanoku
1
160
宣言型部分更新は何を解決しどこへ向かうのか
shuta13
1
480
会社紹介資料 / Sansan Company Profile
sansan33
PRO
31
430k
Featured
See All Featured
Done Done
chrislema
187
17k
AI Search: Where Are We & What Can We Do About It?
aleyda
0
8.1k
Git: the NoSQL Database
bkeepers
PRO
433
67k
Exploring anti-patterns in Rails
aemeredith
4
540
Believing is Seeing
oripsolob
1
250
Are puppies a ranking factor?
jonoalderson
2
4.1k
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
570
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.6k
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.8k
Fireside Chat
paigeccino
43
4.1k
Balancing Empowerment & Direction
lara
6
1.3k
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
330
Transcript
ESLint の独自ルール作成に チャレンジした話 株式会社 NoSchool meijin
目次 独自ルールを作ろうと思ったきっかけ 作って適用する手順 独自ルールの作りかた テストの書きかた 補足① TypeScript 対応 補足② 運用手段の候補
余談 勉強会の主催 まとめ
自己紹介 ニックネームは「名人」 Twitter: @Meijin_garden Web エンジニア6 年目 株式会社NoSchool CTO オンライン家庭教師マナリンク
-> https://manalink.jp 好きな分野はWeb フロントエンド 最近はWYSIWYG ライブラリのSlate.js に感動した 趣味は将棋(アマチュア二段くらい)
独自ルールを作ろうと思ったきっかけ ESLint って気軽にコードの品質を統一できて便利やな〜 業務上で、「今後はこのライブラリは使わないで欲しい」とか「この便利関数作ったからみんな使ってね」とい ったローカルルールを、レビューではなくLint で縛れたらいいな〜 でも、ESLint のルールって字句解析の知識とかないと作るの大変そう… → ちょっと作ってみるか!
独自ルールの大まかな手順 今回は以下の手順で独自ルールを動作させることができた。 独自ルールを記述したJavaScript(or TS) ファイルを作成して、 rules ディレクトリに置く npm scripts で
"lint": "eslint --rulesdir rules" のように記述して実行 ※ --rulesdir オプションはDeprecated なので、他の方法が有力(後述) https://eslint.org/docs/user-guide/command-line-interface
独自ルールの記述方法
本家のドキュメント 「Working with Rules 」 https://eslint.org/docs/developer-guide/working-with-rules 英語かつものすごく長く、(個人的には)理解に時間がかかるので、日本語の文献や巷のライブラリのコードを読み つつ進めるのが良いと思う。ある程度理解すると、公式ドキュメントが割と手にとるようにわかる(当社比)。 以後、これを分かっていれば公式ドキュメントの言っていることがなんとなくわかると思う知識をザッと書いていき ます。
ルールを記述する 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 };
meta その名の通りルールのメタ情報(fix できる?suggest はある?) を表現するオブジェクト ESLint v8 から必要となるプロパティが追加されたみたいなので、昔の日本語記事など一部参考にならないものがあ るかも。要注意。 https://eslint.org/docs/user-guide/migrating-to-8.0.0#rules-require-metahassuggestions-to-provide-
suggestions 1 module.exports = { 2 meta: { 3 hasSuggestions: true 4 }, 5 create(context) { 6 // your rule 7 } 8 };
create create は context を受け取る関数で、AST のノードに対応してLint ルールを実装したオブジェクトを返す プログラム中のこの種類のノードに対しては、このチェックをする!という考えで実装する なのでLint に関係ないノードについては実装しなくてよい
ここで疑問に思ったことが2 つ AST ってなに?AST のノードってなに? どうやってLint ルールを実装するか?
AST とはなにか ( 広義には) 文字列で表現されたプログラムから演算子や変数など、文法的に意味のある情報のみを取り出して、 木構造で表現したもの プログラムは、【プログラム全体-> 複数のクラス-> 複数の関数-> 複数の変数宣言や代入など】といったように木構造で表現できる
分解した各部品のことをノードという プログラムを木構造で表現すると、プログラムから扱いやすくなる ESLint などの「プログラムを意味的に解釈して何らかの動作をするもの」を実装しやすくなる( 他にもbabel とか、Prettier とか、 esbuild とかも多分そう)
AST を覗いてみる https://astexplorer.net/ で簡単な式のAST 表現を見てみると、文字列のコードが巨大なJSON として表現される ことがわかる。超絶雑に図解すると以下の感じ
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 結果をレポート.
リファレンス リファレンスがあるので丸暗記をしなくてもOK context の仕様 https://eslint.org/docs/developer-guide/working-with-rules#the-context-object VariableDeclaration などのAST のノードの種類名 ESTree https://github.com/estree/estree/blob/master/es5.md
@types/eslint https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/eslint/index.d.ts#L438
テストの書きかた 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 のコンストラクタでオプションも色々 設定できるらしい.
補足① TypeScript 対応 @types/eslint を使う 以下の記事が詳しい(厳密にはESLint7 時代の記事なので少しだけ注意が必要) https://blog.sa2taka.com/post/custom-eslint-rule-with-typescript ESLint 自体はts
を読み込んでくれないので、コンパイルフェーズを自前で組むことに注意
補足② 運用手段 冒頭で示した --rulesdir オプションはDeprecated あくまで外部プラグインとして、ローカルフォルダを読み込めるプラグインとしてのアプローチがいくつかある eslint-plugin-rulesdir https://github.com/not-an-aardvark/eslint-plugin-rulesdir eslintrc.js を使っている前提だが最も最新か?
https://github.com/cletusw/eslint-plugin-local-rules 使い方の癖があるように見えるが、任意のeslintrc の形式で対応できそう
余談 勉強会の主催 今回ESLint の独自ルールを調べるにあたって、勉強会を企画してみました https://connpass.com/event/232064/ 2021/12/13 に開催し、共催の RyoKawamata さんと2 時間作業してなんとか形にできた(ありがとうございました)
勉強会駆動開発(Meetup Driven Development, MDD ?)よさそう 勉強会企画したい方、一緒に主催できるので声かけてくださいw
まとめ ESLint の独自ルールを書くために難しい知識は必要ない ドキュメントは丁寧だが、概念をつかむまで少々大変なのと、 @types/eslint などを見たほうが理解が早く 進むところがあるので、手を動かして学ぶのが一番早そう 簡単なルールだったら業務でも作れそうな気がした(まだ作ってない) 勉強会駆動開発おすすめ
告知
Twitter フォローしてね @Meijin_garden だいたいWeb 開発の話か将棋の話してます 絶賛エンジニア採用中です! オンライン家庭教師のスタートアップです! 2020 年リリースで、これから塾や家庭教師や通信教育 を置き換える教育スタイルを広げていきます
少しでも興味があればカジュアル面談歓迎なので、DM やMeety でお声がけください!!
ご清聴ありがとうございました