カジュアルJavaScript AST

スライドをクリックでスタート、矢印キーでスライド移動、Escで一覧モードへ戻る

カジュアルJavaScript AST

ast-token

自己紹介

今日の概要

  • 実は使われてるJavaScript AST
  • JavaScript AST(Abstract Syntax Tree)とは?
  • JavaScript ASTを使ったツール紹介
  • 使うだけじゃなくて書いてみよう

browserify

  • Node.jsで書かれたものをブラウザ向けに変換するツール
  • Node環境で開発 -> browserifyでビルド -> ブラウザで動く
  • JavaScriptのコードを 変換 する
    • ≒ JavaScript ASTを見て変換 する
    • 本体の色々な部分、transform pluginなどでASTを使ってる

JSDoc 3

  • JSDocのアノテーションからHTMLリファレンスを作成する標準ツール
  • Node版の実装にesprimaが使われてる
  • JSDocを解析したい場合はdoctrineを使うのが楽

UglifyJS 2

  • JavaScriptコード圧縮ツール(minifier)
  • コードを圧縮するためにコードをパースしてAST(構文木)を作る
    • 1までは独自のASTのみ
    • 2からは一般的なSpiderMonkey ASTもサポート

plato

  • コードのメトリクス計測のビジュアライズ
  • コード解析的な事はJavaScript ASTを使うのに最もマッチした内容

ぷらとん

What is JavaScript AST?

ast-token

JavaScript ASTって何?

  • AST(Abstract Syntax Tree)はコードをパースした抽象構文木
  • Mozilla JavaScript AST(Parser API) がデファクト
  • 実際に扱う際にはただのJavaScriptオブジェクト
  • Code -> Token -> AST(tokenの関係を構造化したもの)
  • 端的に言えばコードをJSON/JavaScriptオブジェクトで表現したもの

JavaScript AST

new C(1 + a);

このコードには、以下のような要素(node)が存在する

  • NewExpression - new演算子
  • BinaryExpression+
  • 1 というvalueをもつ Literal
  • Ca という変数は Identifier

JS AST Structure

AST Image

JS AST as HTML


new C(1 + a);

  • ↑ Inspect Here ↑
  • JavaScript AST は HTMLの構造ににてる??(同じく木構造)
  • JavaScript ASTから同じような構造のHTMLにしてみた
  • azu/syntax-highlighted-js-ast

習うより慣れろ

  • Esprima: Parser
  • コードを入力してどういうASTが出力されるかをみて理解する
  • JavaScript ASTはECMAScriptの仕様を尊重してる
  • JavaScriptの基本的な文法がわかってれば問題ない
  • 既に公開されてるツールを見ていく

JavaScript ASTを使ったツール

Tern

CoffeeScriptRedux

power-assertのテスト失敗例

power-assert

  • テストコード中に出てくる assert() 等のASTを変換
  • 失敗した場合に欲しい情報を埋め込めるように介入
  • assertionの書き方はシンプル、だけど失敗しても分かりやすくなる

JSCS

  • JavaScript Code Style Checker
  • JSHintと併用してコーディングのスタイルをチェックするツール
    • JSHint 3.0でスタイル関係のルールは外される
  • tokensをみて スタイル をチェックする
    • AST自体は抽象表現なのでスタイルをチェックするには不向き
    • ホワイトスペースとか;があるとかそういう情報はASTには(そのままだと)ない
    • コードの最小単位であるtokensを見ることでスタイルをチェック

JSX言語のminifier

  • minify処理の一部でesmangleを利用
  • ASTレベルでminifyをする
  • 安全にコードを圧縮できるように設計されてる

Grasp

ESLint

  • ASTを元にコードのLintをするツール
  • JSHintと役割は被る部分が多い。
  • プラグインで独自のルールを追加しやすいのが特徴

ESLintで局所的Lint

局所的Lintの例

  • あるブログサイトのJSで特定のコメントが出てきてないかチェックしたい!
    • ✘ "なぜやってるのか不明"
    • ✘ "コピペ"
  • といったコメントを検出したい!
  • JavaScript ASTベースなら文字列リテラルとコメントの区別が簡単
  • hatena-blog-js-lint

あるブログサイトをLintした例

はてなブログのLint

ツールを書いてみよう

JavaScript ASTを使ったツールを書いてみよう

Mochaのテストをパースする例

  • BDD的なテスト構造をテキストとして吐きだしたい!
  • => JavaScript ASTを見てテストの構造を取ってみる
  • describe - context - it ...

Example

var assert = require("power-assert");
describe('Array', function () {
    describe('#indexOf()', function () {
        it('should return -1 when the value is not present', function () {
            assert.equal([1, 2, 3].indexOf(5), -1);
            assert.equal([1, 2, 3].indexOf(0), -1);
        });
        it('should return -1 when the value is not present', function () {
            assert.equal([1, 2, 3].indexOf(5), -1);
            assert.equal([1, 2, 3].indexOf(0), -1);
        })
    });
});
describe('IsNaN', function () {
    context("when value is NaN", function () {
        it('should return true', function () {
            assert(isNaN(NaN));
        });
    });
});

Output

テストコードから以下のようなテキストを出力

Array
   #indexOf()
     should return -1 when the value is not present
       [1, 2, 3].indexOf(5) equal -1
       [1, 2, 3].indexOf(0) equal -1
IsNaN
   when value is NaN
     should return true
       assert isNaN(NaN)

MechaMocha

  • Estraverseを使ったシンプルな走査
  • ASTは木構造だがプロパティの種類が多くて大変
  • traverseライブラリを使うのが一般的
  • enter
    • "describe", "context", "it"CallExpression ならindentレベルを+1
      • ["describe", "context", "it"] なら print
        • assert ならprint
  • leave
    • "describe", "context", "it"CallExpression ならindentレベルを-1

azu/inlining-node-require

  • node.jsのrequireをインライン化してつなげる
  • falafelを使いASTを編集

azu/remove-use-strict

  • 無意味な"use strict"を取り除く
  • 関数スコープを意識した作り
  • Estraverseを使うと楽に関数スコープをみていける

Node.jsのrequireをインライン化、無駄なuse strictを取り除くモジュールを書いた | Web scratch

まとめ

  • JavaScript ASTは既に色々なツールで使われてる
  • 言語仕様に近いので、より正確にJavaScriptコードを扱える
  • JS AST自体はただのJavaScriptオブジェクト/JSON
    • 実際にコードのASTを見る、トライアンドエラーして慣れるのが近道 - Esprima:Parser
    • JavaScriptの構文が分かってるならだれでも扱える
  • ESLintのプラグインやちょっとしたツールにASTを使えると楽しくなる

質問

正規表現でいいんじゃない?

❝ある人々は問題に直面すると、「そうか、正規表現を使うんだ」と考える。こうして彼らは2つの問題を抱えることになる。❞ — Jamie Zawinski

最新の正規表現でやってぶっ壊れた事例(fixed)

ASTからコードは?