JavaScriptのASTと戯れる
pastak.icon pastak @ YAPC::Kyoto 2023
自己紹介
Pasta-K / @pastak
京都でJavaScriptを書いたり、マンガを読んだり、サッカー観戦をしたりしています
Kyoto.jsのオーガナイザー
YAPC::Kyoto 2023のコアスタッフ
株式会社Helpfeel(社員)と株式会社はてな(アルバイト)のダブルワーク
両社共にPerl Sponsorをしています!ブースもあるのでよろしくおねがいします!!
アジェンダ
JavaScriptのASTについて
関連ツールとASTとの関係性について
ASTの例を見てみよう
ASTを扱うコードを書くライブコーディング
この発表で扱うこと・扱わないこと
ASTとは何かという話
JavaScriptのASTの詳細について
ASTとは
抽象構文木(Abstract Syntax Tree)
ソースコードをパースして得られた構文木から、意味のない情報(空白や改行など)を除いた物のこと
https://gyazo.com/044b4981f359d52f2d9827f82afab32a
JavaScriptのASTについて
JavaScriptのASTについて標準化されている表現は存在しない
SpiderMonkeyで利用しているParser APIのドキュメントが流行ってしまったので、コミュニティでメンテナンスしてECMAScriptの仕様に追随出来るようにESTreeを作ったという経緯が書かれている
JavaScript関連ツールとASTまたはESTreeとの関係
ESLintやBabel、typescript-eslint、といったようなJavaScriptやAlt JSのコードを扱うようなするツールはそれぞれESTreeに緩く準拠しながら、拡張したり改変したものを利用している
例: @babel/parserはESTreeに入ってない文法のサポート(現在はESTreeと互換があるわけではない)、@typescript-eslint/parserは型アノテーションなどのTypeScript表現のサポート、ESLintは ESPree という acorn をベースにしたパーサー ASTを操作するツールの振る舞いの例
パーサーを利用して、コードをASTに変換
ASTをtraverseして処理
コードのチェックをするLinter的なものならここまで
ASTからコードを生成
最後のコード生成に使うジェネレーターはASTに合わせる必要があるので、パーサーから一貫して同じパッケージのものを使っておくと便利
JavaScriptのASTがどうなっているか見てみる
今回のAST操作に使うpackageの紹介
ESTreeに準拠した軽量でシンプルなパーサー
acornと一緒に提供されている、acorn-walkもあるが、置換などをやる場合はこっちの方が便利 acornでコードをパースして、acorn-walkでASTを舐めていきながら処理を行い新たなASTを生成し、Astringでコードを生成
実際にやってみます
練習したら1〜3くらいで時間いっぱいだったので、出来るところまでやります
1. console.logの中身を置き換えてみる
1. とりあえず文字列を置き換えてみる
2. ちゃんとconsole.logかどうかを識別する
2. console.logをconsole.traceに置き換えてみる
3. 変数の中身の文字列を展開して埋め込む
4. Array#indexOfを使った判定をArray#includesに置き換える
1. 置き換えられる判定と置き換えられない判定を読み分ける
置き換えるのは arr.includesと置換可能なもののみ
arr.indexOf(any) >= 0
arr.indexOf(any) > -1
置き換えない
上記以外
まとめ
ASTの操作についてのライブコーディングを通して、JavaScriptのAST操作を行うツールの作り方を紹介しました
実際にはこれらの方法と同様の手法でESLintやBabelなどのプラグインのような形で開発するようになるかと思います
内部的なパーサーなどのグッズは異なりますが、実際にプラグインを書くときの書き味としては概ねestree-walkerと大差ないかと思います
参考
今回の発表はこJSConfでのt_wadaさんの発表がふと脳裏に過ぎったのと、YAPCでライブコーディングする人々への憧れがあったので、今回のYAPC::Kyoto 2023でチャレンジしようと思ったのがキッカケでした