Dive into ASTというJavaScriptのASTを使ったツールの作り方を見ていく話を書きました。 自作の正規表現、ASTチェックツール、ESLint、Babel、jscodeshiftでそれぞれ動くツールを実装してるので、リポジトリにまとめてあります。

スライドではCode Surferを使ってASTや書き方をインタラクティブに解説しています。

背景

以前にもASTについては記事やスライドを書いています。 ASTとは何?という話はこの辺と大きくは変わってないです。

JSConf.JPASTの野外ライブコーディングをしていたt_wadaさんとASTについて教えるときにどこにフォーカスして話すのがいいのかという話をしてました。

ASTの触りの話は以前もやってたので、もっとツールとか狭い領域にフォーカスしたものをやってみるかということで作ってみました。

ASTを触るツールを書いてみると、普段のプログラミングであまりしないパターンも結構行うので色々学びがあると思います。 DOMもツリーなのでASTと似た構造ですが(実際にTreeWalkerとかTraverseするものもある)、ウェブサイトを作るのとツールを作るのはやっぱり違う感じはします。

スライドでも書いてましたが、ASTを扱うパーサなどのツールはかなり充実してきているので、最近ではかなり簡単にASTに触れます。 ASTを使ってちょっとした自動化をするようなツールを作ってみると面白いのかもしれません。

自然言語を扱うtextlintもMarkdownなどのASTを扱ってルールを書きます。 npx create-textlint-rule exampleでルールを書き始められるので、文章に興味がある人はこの辺を見てみるのもいいかもしれません。

その他

ASTを吐くパーサの作り方は誰かがやってください。

ASTを扱うツールのテストはスナップショットテストをするのがいいと思います。 大体がコード(AST)を入力にしてコード(AST)を出力とかになるのでスナップショットテストが向いていることが多いです。 テストケースをファイルを追加するだけで増やせてカバー率が上げやすくなります。

たとえばPrettierのテストはほとんどがスナップショットテストです。

パーサとかはテストファースト的にやると進みやすい気がします。 考えすぎるとScanner書くまでに時間がかかるので、テストケースを集めるところからやるのがいい気がします。 無理な構造になってくるとそこまでの実装は捨てたくなって捨てるかもしれませんが、テストケースは残ります。

sentence-splitterはそんな感じで書いてた気がします。

入力になるテストケースはあればあるほど安心はできるので(CIじゃなくて手動でいい)、コーパス的に集めたものを使うこともあります。 textlintルールを書くときは次のようなコーパスを使ったりしてます。

ASTを使ったライブラリとして使うようなValidatorを実装するときは、実データを使ってIntegrationテストすると安心できます。 データベースから対象となるものを全部ダンプしてきて、手動でValidateを通して意図に反した結果がないかを検証していくとか。

次のValidationはクロールした実データを使って手動で試したりしてました。

目的の形のランダムなデータを生成できるfuzzerがあるならFuzzingしてテストするのも面白いかもしれません。

特にパーサを作る場合は、許可された書き方なのにパースエラーが出るのは一番嫌がられるので、物量でカバーするのが良い気がします。 JavaScriptのコード/ASTなら、有名所のライブラリをテストケースに使うというのがよく取られる手法です(ベンチマークにもなる)。