鈴木颯介のブログ

Prettier にコントリビュートした(6)

Prettierにコントリビュートしました。

解決したIssue

https://github.com/prettier/prettier/issues/5846

Prettierにはtrailing-cmmmaというオプションがあります。これはオブジェクトなどの末尾にカンマをつけるかどうかを指定するオプションで、設定できる値としてnonees5allがあります。

noneは末尾にカンマをつけず、以下のような変換を行います。

// Input
const obj = {
  a: "a",
  b: "b",
}

// Output
const obj = {
  a: "a",
  b: "b"
}

es5は、ES5でバリッドになるような末尾カンマをつけます。ES5の時点では、配列とオブジェクトリテラルに対しての末尾カンマは許されていましたが、関数の引数の末尾カンマはインバリッドでした。そのため、以下のような変換を行います。

// Input
const obj = {
  a: "a",
  b: "b"
}

const arr = [
  1,
  2 // コメントを入れないと一行にたたまれる
]

function func(
  arg1,
  arg2, // ES5ではこのカンマはインバリッド
) {
  foo();
}

// Output
const obj = {
  a: "a",
  b: "b",
};

const arr = [
  1,
  2, // コメントを入れないと一行にたたまれる
];

function func(
  arg1,
  arg2 // ES5ではこのカンマはインバリッド
) {
  foo();
}

allはES2017以降から許可された、関数の引数も含めて末尾のカンマを追加します。

// Input
const obj = {
  a: "a",
  b: "b"
}

const arr = [
  1,
  2 // コメントを入れないと一行にたたまれる
]

function func(
  arg1,
  arg2, // ES5ではこのカンマはインバリッド
) {
  foo();
}

// Output
const obj = {
  a: "a",
  b: "b",
};

const arr = [
  1,
  2, // コメントを入れないと一行にたたまれる
];

function func(
  arg1,
  arg2, // ES5ではこのカンマはインバリッド
) {
  foo();
}

で、この変換はTypeScriptでも同様に行われるものなんですが、タプル型の末尾カンマだけはつけないようになっていました。というのも、TypeScriptのタプル型の末尾カンマがサポートされたのがバージョン3.3からだったので、それに合わせて実装されていたみたいです。最近もうTSの3.5が出たことだしそろそろええやろということで、PRを投げてみました。

出したPR

https://github.com/prettier/prettier/pull/6172

今回はとっても楽でした。Prettierのプリンタ関数では基本的にノードのtypeプロパティに対してswitch文で処理を行っていきます。Flowのタプル型(TupleTypeAnnotation)のノードとTSのタプル型(TSTupleType)は同じステートメントで処理されるのですが、その中で以下にようなコードがありました。

// TypeScript doesn't support trailing commas in tuple types

n.type === "TSTupleType"	
  ? ""	
  : ifBreak(shouldPrintComma(options) ? "," : ""),

詳細に触れなくても、なんとなく意図することがわかりますね。この3項演算子の条件分岐を消せば良いだけです。

感想

ESTreeの形にもちょっとずつ慣れてきました。他の言語のASTも見れるようになりたいですね。