5 月の OSS 活動
5 月のオープンソース活動です。意外とちゃんとやってた。
Prettier
Vue や HTML の改善をやっていたような気がします。あと Babel 7.10 や TypeScript 3.9 の対応も若干。ここに載せた以外にも細かな改善もしました。
Vue の SFC のパース改善
https://github.com/prettier/prettier/pull/8153
Prettier は HTML をパースするためにangular-html-parserという Angular の HTML パーサーのフォークを使っているんですが、Vue の SFC のような HTML ではないけど HTML っぽいものにもそれを使用しています。
今までは Vue の SFC をそのまんま HTML としてパースしていました。なのでカスタムブロック内や pug 等の HTML 以外の言語を使った template 内に HTML タグとして認識されちゃう文字のパターンを入れるとシンタックスエラーになっていました。(Playground Link)
<!-- これをPrettierでフォーマットしようとするとシンタックスエラーになる -->
<custom-block>
const foo = "</";
</custom-block>
これを解消するためにいくつか方法を考えました。vue-eslint-parserを使うか?とか、Vue 公式の SFC コンパイラのパーサーを使うか?とか。しかし、前者はカスタムブロックのサポートを公式にはしていないようで今回のニーズを満たすパース結果が得られず、後者はルートのコメント情報がパース結果に残らずフォーマッターに使うには不十分でした。
なので angular-html-parser を修正してもらって、最終的に少々トリッキーな方法で解決しました。気が向いたらそのお話もどこかに書くかもしれません。
Stage-1 プロポーザル private filed in in
の対応
https://github.com/prettier/prettier/pull/8431
Babel 7.10 で対応された Stage-1 のプロポーザルの対応です。次のようなコードはいままでシンタックスエラーだったんですが、フォーマットできるようになります。Prettier 側の対応はパーサーのバージョンアップとオプションの指定だけだったので楽でした。
#prop in obj;
TypeScript 3.9 で入った Non Null Assertion と Optional Chaining の解釈の変更の対応
https://github.com/prettier/prettier/pull/8450
リリースノートを見て TypeScript 3.9 は新しい構文ないから Prettier の対応ないじゃん!って思ってたらありましたね。
Babel 7.10 も同様の修正が入っているので、babel-ts
パーサーにも対応しています。
TypeScript 3.8 までは
x?.y!.z;
は
(x === null || x === void 0 ? void 0 : x.y).z;
という JavaScript にコンパイルされていたんですが、TypeScript 3.9 からは
x === null || x === void 0 ? void 0 : x.y.z;
にコンパイルされるようになりました。なので以前までの挙動を再現したい場合にカッコを補ってあげなくてはいけないんですが、Prettier はそのカッコをはずすようにフォーマットをしていたので、維持するようにしました。
// Input
(a?.b)!.c;
// Prettier stable
a?.b!.c;
// Prettier master
(a?.b)!.c;
eslint-plugin-vue
no-arrow-functions-in-watch
ルールの追加
https://github.com/vuejs/eslint-plugin-vue/pull/1155
ドキュメントに書いてあるんですが、Vue のwatch
にアロー関数を使うのはアンチパターンです。this
で束縛される値が変わってしまって、Vue インスタンスを指さなくなります。
なので、watch
にアロー関数を使っているときに警告を出すルールを追加しました。
詳しくは eslint-plugin-vue のドキュメントの https://eslint.vuejs.org/rules/no-arrow-functions-in-watch.html を見ていただけると。
typescript-eslint
method-signature-style
ルールの自動修正のバグの修正
https://github.com/typescript-eslint/typescript-eslint/pull/1966
TypeScript では interface の関数プロパティを二通りの方法で書くことができます。
// メソッドのショートハンド
interface T1 {
func(arg: string): number;
}
// 通常の関数プロパティ
interface T2 {
func: (arg: string) => number;
}
method-signagure-style
ルールはこれをどちらかに強制できます。
ただ、メソッドのオーバーロードがあったときにメソッドのショートハンドから通常の関数プロパティに強制すると、ルールの自動フォーマットの結果がエラーになってしまうバグがありました。
例えば、次のコードを通常の関数プロパティに強制することを考えます。
interface T {
method(): void;
method(arg: string): void;
method(arg: number): string;
}
今までの実装だと、このようにフォーマットされていました。
interface T {
method: () => void;
method: (arg: string) => void;
method: (arg: number) => string;
}
実際試してみるとわかりますが(Playground link)、これはDuplicate identifier 'method'.
でコンパイラに怒られてしまいます。なので、これを intersection types としてフォーマットすることでエラーを回避します。
interface T {
method: (() => void) & ((arg: string) => void) & ((arg: number) => string);
}
これはセーフになります(Playground link)。