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
サポートらしいが・・・
- こちらも