ちゃんと区別できてなくて、地味に誤解してたことに気付いたのでメモしておく。
それぞれの役割
@typescript-eslint/parser
@typescript-eslint/typescript-estree
最初はestree
のほうが表向きのパッケージで、内部的にparser
を使ってるのかと思ってたけど、まったくの逆だった。
parser
こそがESLintのための表向きのパッケージで、純粋にASTだけ取り出したい場合は、typescript-estree
のほうをそのまま使えばよさそう。
parser
側のコード
2つの関数がexportされてる。
parseForESLint()
parse()
で、parseForESLint()
のここで、typescript-estree
のparseAndGenerateServices()
を呼び出すことで、ASTを作ってる。
そもそもparser
のほうのパッケージは中身が薄くて、200行くらいしかない。
ASTのパース以外には、scope-manager
でスコープ解析したりもしてる。
typescript-estree
側のコード
(わかりにくいことに)こっちも2つの関数をexportしてる。
parseAndGenerateServices()
parse()
まずparse()
だが、こっちはparseWithNodeMapsInternal().ast
を返すだけで、いたってシンプル。
ts.createSourceFile()
でTSのASTを生成しastConverter()
でESTree互換に調整- それを返すだけ
注意点として、parse()
のほうでは、errorOnTypeScriptSyntacticAndSemanticIssues
オプションが使えない。
つまりTSCが拾った構文エラーは検知できるけど、意味論的なエラーは検知できないってこと。これを検知したい場合は、parseAndGenerateServices()
のほうを使えっていうエラーになる。
つぎにparseAndGenerateServices()
では、parse()
で返すASTに加えて、TSのProgram
を作ってる。
そのおかげで、意味論的なエラーまでも検知することができてるってわけ。
まとめ
@typescript-eslint
では、parser
とtypescript-estree
パッケージから、それぞれ以下4種類のパース関数でASTを取得できる。
typescript-estree
にあるもののほうが、よりプリミティブな用途になってて、
typescript-estree/parse()
- 構文エラーあり、意味論的エラーなし
typescript-estree/parseAndGenerateServices()
- 構文エラーあり、意味論的エラーあり
parser
にあるのはtypescript-estree
のラッパーでしかなく、
parser/parseForESLint()
parseAndGenerateServices()
を呼びつつ、スコープ解析なんかもやる
parser/parse()
parseForESLint().ast
を返すだけ
という感じ。
ということを、Prettierのtypescript
パーサーが有効にしてるsuppressDeprecatedPropertyWarnings
というオプションを追うために調べてた。
ちなみにPrettierのtypescript
パーサーでは、最もプリミティブなtypescript-estree/parse()
が使われてる。