現在JavaScriptの設定が無効になっています。このページを利用するにはJavaScriptの設定を有効にしてください。2015の4日目の記事です。一覧はこちら12月から福岡勤務の穴井(@pirosikick)です。Flight」の開発・運用を行っています。今回は、リッチ広告の開発で利用しているESLintのルールを自作する方法について書きたいと思います。サンプルの動作環境について本記事に登場するサンプルは、下記の環境で実行しましたので、適宜ご自身の環境に置き換えてご覧ください。3.3.9サンプルのJavaScriptは一部ES6で書いておりますので、先日伊藤が書きました「ES6時代のNode.js」も併せてご覧ください。linterESLintは、JavaScriptの静的検証ツールで、バグの原因になりそうな問題のあるコードを見つけたり、インデント数や括弧前後のスペースなどのコーディングスタイルを統一するのに役立ちます。類似のツールとしては、古くからあるものだとJSLintやJSHint、最近のものだとJSCSがあります。ESLintはルールを自作できる!ESLintの最大の特徴は、ルールを自分で開発できることです。リッチラボでも独自のルールを開発し、ESLintのプラグインとして公開しています。window.innerWidthを禁止するルールなどがあります。ESLintを動かすルールの開発に入る前に、ESLintを動かしてみましょう。npmでESLintをインストールします。設定ファイル(.eslintrcか、package.jsonのeslintConfigフィールド)を用意するか、2種類の方法があります。今回は.eslintrcを用意します。ESLintの推奨設定を継承するように、下記を.eslintrcに書きます。"eslint:recommended"}これで動かす準備が出来ました。見るからに悪そうなコードでファイルを作り、ESLintで検査を実行してみましょう。warnings)無事(?)悪そうな部分が炙りだされました!ESLintはルールが100個以上あり、一つ一つルールのドキュメントを確認しながら設定していくはかなり辛い作業です。新しく設定ファイルを作る際は、上記のように推奨設定を継承し、使いながらルールを増やしていくのがおすすめです。editorというツールを作りましたので、そちらもぜひ使ってみてください!ルールの仕組みESLintを動かす環境が整ったので、ルールがどのように動いているのか、軽く説明したいと思います。treeの略で日本語にすると抽象構文木です。抽象構文木とは、ソースコードを文法的に解析し、それを木構造で表現したものです。AST");からは下記のようなJSONが出力されます。出力されるJSONのフォーマットはASTを生成するパーサーによって違いますが、ESLintはespreeを利用しているので、ESTreeの仕様に沿ったフォーマットでJSONを出力します。[]}ESLintは生成されたASTをまるごとルールに渡すのではなく、ルールが必要としているノード(CallExpressionなど)だけ渡します。下記のようにASTの木構造をルート(Program)から巡回し、ルールが必要としているノードに到達した時にルール内に定義されているノードに対応した関数を実行します。関数の実行タイミングは、巡回時に「ノードに入る(enter)」時か「ノードから出る(leave)」時の2種類があります。実行タイミングの使い分けについては後述します。ルールの開発ルールの開発方法を段階的に説明したいと思います。最初は、hogeという変数名の定義・参照を禁止する「no-hoge」ルールを作ってみたいと思います。ルールを置くディレクトリを作ります。rulesそのディレクトリの中に「ルール名.js」でJSファイルを作ります。no-hogeなので「no-hoge.js」です。rules/no-hoge.jsJSファイルの中では、contextを引数に取る関数を定義し、module.exportsで外部から参照可能にします。その関数は、キーが必要なノード名、値がそのノードが出現した時に実行する関数になっているObjectを返します。引数のcontextには、検査結果の通知に使うreport関数や、ルール実行時の設定の参照、検査対象のファイル名の取得などのための変数・関数が定義されています。(contextの機能について)下記がno-hogeルールの実装です。Identifierが出現した時にそのノードのnameが”hoge”の場合は、hoge変数がソースコード上に現れたとみなし、context.reportでエラーメッセージと対象のノードを通知します。}};.eslintrcのrulesフィールドにno-hogeを追加し、ルールを有効にしましょう。}}では、作ったルールを実行しましょう。ルールを置いたディレクトリを—rulesdirオプションで指定し、実行します。(no-unused-varsも出ていますが。warnings)ルールのテストESLintのルールは単体テストが可能です。上記のno-hogeの例ではエラーになりそうなコードでJSファイルを作っていますが、毎回そんなことをしていたら辛いので、単体テストを書いて想定通りに動いているかのチェックをしましょう。単体テスト用のディレクトリを用意し、単体テストを実行するためにmochaをインストールします。mochaESLintのRuleTesterを使うと簡単に単体テストが書けます。問題のないコードとエラーになるコードをインスタンス化したRuleTesterのrun関数に渡すだけです。no-hogeの単体テストを下記のように書きました。});mochaで単体テストを実行します。(48ms)テスト通ってますね!ルールのオプション単体テストができる環境が整いましたので、ちょっとルールを複雑にします。ルールには設定ファイルからオプションを渡すことができますので、その機能を活用したルールを作ってみましょう。no-hogeをちょっと修正して、任意の変数名の参照を禁止するtaboo-varsルールを作ります。設定ファイルからオプションを渡します。配列の先頭はルールの無効/警告/エラーのフラグで、2番目以降がオプションとしてルールに渡されます。}}ルール側では、オプションはcontext.optionsで受け取れます。Schemaでオプションのフォーマットを指定することができ、そのフォーマットと異なる値が渡された場合にエラーにすることができます。指定することで余計なバリデーション処理が不要となり、コードがすっきりしますのでぜひ書きましょう。Schemaが定義してあります!)下記がtaboo-varsの実装です。rule;テストはno-hogeとほとんど一緒ですが、optionsでオプションを渡してテストしています。});実行タイミングの使い分け「ルールの仕組み」のところで、ノードに対応する関数の実行タイミングに2種類(入る時・出る時)あると書きました。これまでのサンプルは全てノードに「入る時」に実行されており、ノードから「出る時」に実行したい場合はノード名に:exitを付けます。};};:exitの用途ですが、例えばmax-nested-callbacksルールの場合だと、FunctionExpressionに入る時にカウンタに+1、FucntionExpressionから出る時にカウンタから-1し、関数のネスト数をカウントして閾値に達した時にエラーを出したりしています。特定のノードだけを見ても分からないようなルールの場合に:exitを使っているケースが多いようです。ルールの共有これまでのサンプルでは、ルールを置いたディレクトリを—rulesdirオプションで指定し、そのルールを実行してきました。複数のプロジェクトでそのルールを共有したい場合に、やや不便です。複数のプロジェクトをまたいで利用するルールは、プラグイン化してnpmパッケージにすると便利です。冒頭で紹介したリッチラボが公開しているルールを使用したい場合、まずプラグインをインストールします。eslint-plugin-richlab設定ファイルのpluginsフィールドにプラグイン名(eslint-plugin-を除いた部分)を追加します。プラグインに含まれるルールは「プラグイン名/ルール名」で参照できます。簡単にプラグインを作ることができますので、npmに公開しても問題ないルールでしたらプラグイン化を検討しましょう。Explorerルールを書く際に、コードがどのようなASTになるのか確認する機会が多いと思いますが、espreeなどのパーサーを使ってASTを生成し、それをconsole.logなどで出力して確認するのはかなり面倒です。Explorerを使いましょう。ブラウザでインタラクティブにASTを確認できます。最近では利用者も増え、日本語のドキュメントも多くあります。誰も考えついていないような素晴らしいルールを作れるのでは!と、とてもワクワクします。みなさまもコードレビュー時に毎回指摘していることや、チーム内で暗黙的に広まっているルールなどございましたら、ESLintでルールを自作して、楽をしましょうっ!!参考資料ESLintはドキュメントが充実していますので、今回の記事で興味が湧いた方は公式ドキュメントに一通り目を通すとよいと思います。http://eslint.org/docs/developer-guide/working-with-ruleshttp://eslint.org/docs/developer-guide/working-with-pluginsASTの仕様等については、jser.infoのazuさんの資料がとてもわかりやすいです。JAPANでは情報技術を駆使して人々や社会の課題を一緒に解決していける方を募集しています。詳しくは採用情報をご覧ください。JAPANのサービス開発を支える技術やデザイン、文化を発信しています。Reserved.このページの先頭へ。