ClaudeCodeにしろ、DeepWikiにしろ、便利ではあるけどやっぱりなんか物足りなくて、結局自分で読んじゃうのよな・・・。
esrapとは
sveltejs/esrap: Parse in reverse https://github.com/sveltejs/esrap/
Svelteコンパイラの中でも使われてるライブラリで、
sveltejs/acorn-typescriptでパースしたASTをRich-Harris/zimmerframeでwalkして更新してからsveltejs/esrapでコード文字列に戻す
この最後の、AST-to-stringのステップを担うパーツ。
できること・できないこと
acornでパースしたJSのASTを文字列化することはできる。おそらくacornじゃなくても、ESTree ASTなら対応してる。
ただし、acorn-jsxのような拡張は考慮していないようで、JSXXxxなノードが現れるとエラーになってしまう。まぁ.svelteでJSXを書くことはないからな・・・。
TSについては、sveltejs/acorn-typescriptでパースしたTSのASTの文字列化もできると書いてある。
が、コードを追ってみるとサポートは完全ではないようで、目grepする限り、結構いろんな型がサポートされてないように見える。
@typescript-eslint/typescript-estreeでは、79種類のTSXxxノードが定義されてるけど、40ちょいくらいしかサポートされてなさそう・・・?
(というかそもそも、acorn-typescriptのSpecが見当たらないし、typescript-estreeと同一の構造というわけでもなさそうだった)
そもそも、Svelteコンパイラのユースケースでは、ASTから型のノードを消し去ってからesrapに投げてそうだった・・・。
ソースマップには対応してて、いわゆるリレーもできるようになってる。
あとはコメントの出力にも対応してる。
が、ASTノードの任意の位置にleadingCommentsとtrailingCommentsというプロパティを事前に差し込んでおく必要がある。
いわゆるattachComments()的な実装は含まれておらず、テストコードに簡易な実装だけあった。
https://github.com/sveltejs/esrap/blob/31e5a4096adb533a1ed2dbe970dab7a7d9488bad/test/common.js#L14
実装
端的に言うと、軽量なPrettierだった。ASTをまずはIRにして、それを文字列にしてる。 (ただし絶対的な違いとして、たった2ファイルしか実装がない!読みやすい!)
- APIは
print(ast, { /* ほぼソースマップ関連オプション */ })のみとシンプル node.typeに応じてハンドラが分かれていて- https://github.com/sveltejs/esrap/blob/31e5a4096adb533a1ed2dbe970dab7a7d9488bad/src/handlers.js#L856
- ここにないものはエラーになる、
JSXXxxしかり、TSXxxしかり
stateにCommandを積んでいく- ESTreeのAST上には存在しない
()について、それが必要な場所で自動挿入するneeds_parens()もある - IR化が終わったら、それを文字列にしていく
- Prettierのそれみたく、長くなってきたから改行すべきかチェックする
measure()もあったりする
以上。
感想
実装としてはシンプルで、特に気になるところはなかった。
しかしTSの型サポートが中途半端なのは、優先度の問題なのかポリシーの問題なのかが気になるところ。まぁJSXと同じで、Svelteコンパイラとして必要ないからサポートされてない気がする。
どこまでPrettyに文字列化するかは厳密ではなく、テストケースも70パターンくらいしかなかった。
コメントに関しては、Prettierと比べるとそもそもdanglingCommentsの扱いがなかったりと、思い切った割り切りを感じる。まあ仕方ない。うん、だって、仕方ないあれは。
同じような役割のライブラリとしては、astringもある。
davidbonnet/astring: 🌳 Tiny and fast JavaScript code generator from an ESTree-compliant AST. https://github.com/davidbonnet/astring
こっちは、IRを持たないより簡素な実装になっていつつ、ハンドラは外部から拡張できるようになってる。
JSXとTSのサポートは、それぞれ本家ではない野良プラグインがあるという感じ。
- https://github.com/Qard/astring-jsx
- https://github.com/vardario/astring-ts-generator
- こちらも
acorn-typescriptサポートらしいが・・・
- こちらも