TypeScript/コンパイルエラーの取り扱い
はじめに
honey-css-modules で*.module.cssの構文エラーやセマンティックエラーを出力したい
その実装の参考にするため、TypeScript のコンパイルエラーの取り扱いについて調べたい
メモ
TypeScript コンパイラ内部では、コンパイルエラーは「Diagnostic (診断情報)」というオブジェクトで表される
Diagnostic の定義は以下
code:ts
interface Diagnostic extends DiagnosticRelatedInformation {
/** May store more in future. For now, this will simply be true to indicate when a diagnostic is an unused-identifier diagnostic. */
reportsUnnecessary?: {};
reportsDeprecated?: {};
source?: string;
relatedInformation?: DiagnosticRelatedInformation[];
}
interface DiagnosticRelatedInformation {
category: DiagnosticCategory;
code: number;
file: SourceFile | undefined;
start: number | undefined;
length: number | undefined;
messageText: string | DiagnosticMessageChain;
}
category: error, warning, suggestion, message のどれか
suggestion はエディタ上でだけ表示されるもので、ターミナルには出力されない (ref) mizdra.icon 1002未満が使われてない理由はよくわからない
file: diagnostic 発生元のファイルの SourceFile オブジェクト。
mizdra.icon ファイル名ではなくSourceFileを持っているのは、おそらくstart/lengthをもとに、エラー発生箇所のコードフレームを出力できるようにするためではないか
コードフレームを出力するには、ファイルのソースコードの全文 (SourceFile.text) を持ってないといけない
messageText: メッセージ。diagnosticMessages.json で定義されてる。
relatedInformation: 関連情報を詰めておくところ。
「プロパティxxxが不足しています。プロパティxxxはここで定義されている型です」みたいな関連情報を出すために使われる模様。
sourceはエラーがどの plugin (TypeScript Language Service Plugin) 由来のものなのかを表す識別子
mizdra.icon plugin 独自の diagnostic を定義したかったら、このプロパティを埋めるべきなのだろう
ts.formatDiagnosticsWithColorAndContextでターミナル向けの diagnostic のフォーマットができる
色付きの出力になる
file/startがあればファイル名や line/column、コードフレームなども出力してくれる
逆にfile/startがなければ、省略される
内部的には、diagnostic は2種類に分類される (参考1, 参考2) syntactic diagnostic
シンタックスに関するエラー情報を含むもので、パース時に収集される
semantic diagnostic
シンタックス以外のエラー情報を含むもので、パース以外 (型検査など) のフェーズで収集される
前者は1ファイルだけ解析すれば収集できて、後者は複数ファイルを解析しないと収集できない
mizdra.icon エディタ上に診断情報を出す時に、両者で出すタイミングが異なるので (後者は複数ファイルを解析する分、出るタイミングが遅れる)、別々のものとしてモデリングされてるのだろう。たぶん...
あと前者は構文エラーにまつわるものなので、file/startなどの位置情報のプロパティが必須となってるけど、後者は省略可能になってる
プロジェクト内に syntactic diagnostic/semantic diagnostic の両方がある場合、tscで syntactic diagnostic だけ出力される
code:src/a.ts
const _num == 0; // ',' expected.
const _str: string = 1; // Type 'number' is not assignable to type 'string'.
code:src/b.ts
const _num == 0; // ',' expected.
const _str: string = 1; // Type 'number' is not assignable to type 'string'.
code:console
$ npx tsc
src/a.ts:1:12 - error TS1005: ',' expected.
1 const _num == 0;
~~
src/b.ts:1:12 - error TS1005: ',' expected.
1 const _num == 0;
~~
Found 2 errors in 2 files.
Errors Files
1 src/a.ts:1
1 src/b.ts:1
semantic diagnostic は出力されない
一方 tsserver では semantic diagnostic も出力される
https://gyazo.com/9b4287f11fedcc39fefa9633e9a963a2
mizdra.icon パッと見は tsc でも semantic diagnostic を出力すべきかのように思えるが...
構文的に正しくないファイルがある時は、大量の semantic diagnostic が出がち
仮に semantic diagnostic を出力してしまうと開発者が出力の量に圧倒されてしまう
それを避けるために、syntactic diagnostic は出すけど、semantic diagnostic は出さないようにしてるのだろう。勘だが...
気が利いてる