Skip to content

Commit

Permalink
docs(ja): update Formatter in japanese (#1076)
Browse files Browse the repository at this point in the history
Co-authored-by: Daiki Nishikawa <[email protected]>
  • Loading branch information
chansuke and nissy-dev authored Dec 13, 2023
1 parent 570d680 commit 582e1c4
Show file tree
Hide file tree
Showing 3 changed files with 353 additions and 1 deletion.
288 changes: 288 additions & 0 deletions website/src/content/docs/ja/formatter/differences-with-prettier.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,288 @@
---
title: Prettier との違い
description: Prettier との違いを深く解説
---

Prettier との間にいくつかの相違点が存在します。

### Prettierは有効なJavaScript識別子である一部のオブジェクトプロパティの引用符を外しません

PrettierとBiomeは、有効なJavaScript識別子であるオブジェクトおよびクラスプロパティの引用符を外します。
Prettierは、特に[ES5において有効な識別子のみ引用符を外します](https://github.com/prettier/prettier/blob/a5d502513e5de4819a41fd90b9be7247146effc7/src/language-js/utils/index.js#L646)

ES2015が広まっている現在のエコシステムにおいて、これは古い制限です。
そのため、私たちはES2015以降の全ての有効なJavaScript識別子の引用符を外すことにしました。

プロジェクトが使用するECMAScriptバージョンを設定するための設定を導入することは可能な解決策かもしれません。
そのバージョンに基づいて引用符を外す動作を調整できます。
ECMAScriptのバージョンをES5に設定することで、Prettierの挙動に一致させることができます。

入力

```js title="example.js"
const obj = {
'a': true,
b: true,
"𐊧": true,
}
```

差分

```js title="exmaple.js" del={4} ins={5}
const obj = {
a: true,
b: true,
"𐊧": true,
𐊧: true,
};
```


### Prettierは計算プロパティでの代入で一貫性のない挙動を示します

PrettierとBiomeは、特に条件文などで代入式を括弧で囲みます。
これにより、Biomeは比較式であるべきコードを識別できます。

Prettierは、オブジェクトの計算プロパティでの代入では括弧を追加する一方で、クラスの計算プロパティではそれを行いません。以下の例で示されます:

入力

```js title="example.js"
a = {
[x = 0]: 1,
}

class C {
[x = 0] = 1
}
```

差分

```js title="example.js" del={2} ins={3}
a = {
[(x = 0)]: 1,
[x = 0]: 1,
};

class C {
[x = 0] = 1;
}
```

[プレイグラウンドのリンク](https://biomejs.dev/playground?enabledLinting=false&code=YQAgAD0AIAB7AAoAIAAgAFsAeAAgAD0AIAAwAF0AOgAgADEALAAKAH0ACgAKAGMAbABhAHMAcwAgAEMAIAB7AAoAIAAgACAAIABbAHgAIAA9ACAAMABdACAAPQAgADEACgB9AAoA)

一貫性を保つために、私たちは Prettier のformatに合わせることなく括弧を省略することにしました。
代替案としては、オブジェクトまたはクラスの計算プロパティでの代入を常に括弧で囲むことができます。

### Prettierは必要ない場合でもアロー関数の型パラメータに末尾のカンマを追加します

特定のケースでは、JSX要素と区別するために、アロー関数の型パラメータリストに末尾のカンマが必要となります。
型パラメータにデフォルト値が提供されている場合、末尾のカンマは必要ありません。
ここでは、必要な場合にのみ末尾のカンマを追加するというPrettierの元々の意図を尊重するために、現在のformatの差分を受け入れました。

入力

```tsx title="example.tsx"
<T = unknown>() => {};
```

差分

```tsx title="example.tsx" del={1} ins={2}
<T = unknown,>() => {};
<T = unknown>() => {};
```

### Prettier は、括弧で囲まれた non-null アサーションを含むオプショナルチェーンに対して一貫性のない動作をします

_TypeScript_ では、non-null アサーション演算子 `!` を使用して、値が null でないことをアサートできます。
オプショナルチェーンに適用される場合、アサーションは括弧の存在に関係なくチェーン全体に適用されます。つまり、`(a.?.b)!` と `a.?.b!` は同じ結果になるはずです。

Prettier は、先のコード例をどちらも適切にformatされているとみなします。つまり、括弧の有無は維持され、コードを正規化しようとしません。

さらに、Prettier は、括弧がnon-null アサーション演算子を囲んでいる場合でもかっこを削除しません。代わりに、演算子を括弧の外に移動します。

入力

```ts title="example.ts"
a.?.b!
(a.?.b)!
(a.?.b!)
```

差分

```ts title="example.ts" del={2, 4} ins={3, 5}
a.?.b!
(a.?.b)!
a.?.b!
(a.?.b)!
a.?.b!
```


### Prettierは無効な構文をformatします

JavaScriptおよびTypeScriptのためにPrettierで利用されているBabel parserの解析は厳密なものではなく、[いくつかの構文エラーを無視](https://github.com/prettier/prettier/blob/e4a74c05f4502dd4ec70495c3130ff08ab088e05/src/language-js/parse/babel.js#L177-L218) することがあります。
Biomeのparserは、Prettierのparserよりも厳密に構文を解析します。
たとえば、以下の構文エラーを正確に識別します:

- 関数には重複する修飾子を持つことはできません
- プロパティの修飾子を無効な順序で指定することはできません
- 関数宣言では関数の処理を定義することができません
- 抽象クラス以外で抽象プロパティを持つことはできません
- オプショナルチェーンに代入することはできません
- インターフェースの型パラメータに `const` 修飾子を設定することはできません
- トップレベルの return

Prettierでは、これらのエラーを構文エラーとして扱わず、適切なノードでASTが "正しく" 構築されます。
そして、これらのノードを通常通り扱い、formatします。

Biomeでは、構文エラーは`Bogus`ノードとして扱います。`Bogus`ノードは、有効なノード、無効なノード、生の文字などを含みます。
format時、Biomeは bogusノードを事実上のプレーンテキストとして扱い、そのまま出力します。これは、formatを試みることでコードの意図を変更してしまう恐れがあるためです。

Prettierのparserは、クラスプロパティの修飾子に対してブール値のフィールドを使用します。これは、各種類の修飾子が1つしか存在できないことを意味します。(アクセス修飾子は単一の文字列として格納されます)。
formatの時には、ブール値のリストを見て、どの修飾子を再び出力するかを決定します。一方、Biomeは修飾子のリストを保持し、重複を含めて解析が可能になります(これが重複修飾子や順序に関する解析エラーを報告できる理由です)。
不正な修飾子を含むbogusノードをformatする際は、修飾子のリストはそのまま維持され、不正なテキストをそのまま出力します。

Biomeでは、この問題に対処するいくつかの方法があります。
その1つとしては、format時にBogus なノードを解釈し、有効なノードを構築する方法があります。
有効なノードが構築できれば通常通りそのノードをformatし、そうでない場合は現在のように不正なテキストをそのまま出力します。
しかし、これを実装するのは少し大変で、formatterに意味のないロジックを導入することになります。

別の方法としては、意味論的なエラー(重複修飾子、抽象クラス以外での抽象プロパティの使用)を受け入れる "syntactically-valid bogus node(文法的に不正確なノード)" をparserに導入する方法もあります。

これにより、通常通りノードを構築しつつ(Prettierの挙動と一致させつつ)、新しい種類のbogusノードに構文解析の情報を含めて格納します。
format時には、特定のbogusノードでは内部ノードをformatしようと試み、エラーが発生した場合はフォールバックします(既存の `format_or_verbatim` ユーティリティがこれを行っています)。
これにより、parserとformatterのロジックを分離しつつ、無効な状態を半有効とみなすような複雑なロジックをparserに実装することが可能になります。

#### クラスプロパティの重複する修飾子

入力

```ts title="example.ts"
// 複数のアクセシビリティ修飾子
class Foo {
private public a = 1;
}

// 処理を持つ関数の宣言
declare function foo ( ) { }

// abstractの不正な使用
class Bar {
abstract foo ;
}

// Readonlyの重複
class Read {
readonly readonly x: number;
}
```

差分

```ts title="example.ts" del={3, 8, 13, 19} ins={4, 9, 14, 20}
// 複数のアクセシビリティ修飾子
class Foo {
private a = 1;
private public a = 1;
}

// 処理を持つ関数の宣言
declare function foo() {};
declare function foo ( ) { }

// abstractの不正な使用
class Bar {
abstract foo;
abstract foo ;
}

// Readonlyの重複
class Read {
readonly x: number;
readonly readonly x: number;
}


#### オプショナルチェーンへの代入

入力

```js title="example.js"
(a?.b) = c;
```

差分

```js title="example.js" del={1} ins={2}
a?.b = c;
(a?.b) = c;
```

#### インターフェイスの型パラメータに対する誤った修飾子

入力

```ts title="example.js"
interface L<in const T> {}
```

差分

```ts title="example.js" del={1} ins={2}
interface L<const in T> {}
interface L<in const T> {}
```

#### トップレベルのreturn

```js title="example.js"
return someVeryLongStringA && someVeryLongStringB && someVeryLongStringC && someVeryLongStringD
```

```js title="example.js" del={1, 2, 3, 4, 5, 6} ins={7}
return (
someVeryLongStringA &&
someVeryLongStringB &&
someVeryLongStringC &&
someVeryLongStringD
);
return someVeryLongStringA && someVeryLongStringB && someVeryLongStringC && someVeryLongStringD
```

#### 誤った self-increment と self-decrement

入力

```js title="example.js"
(1)++;
```

```js title="example.js" del{1} add={2}
1++;
(1)++;
```

#### 抽象クラスでないクラスでの `abstract` 修飾子の使用

入力

```ts title="example.js"
class C {
abstract f() : number;
}
```

差分


```ts title="example.js" del{2} add={3}
class C {
abstract f(): number;
abstract f() : number;
}
```
28 changes: 27 additions & 1 deletion website/src/content/docs/ja/formatter/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import PackageManagerBiomeCommand from "@src/components/PackageManagerBiomeComma
Biomeは、スタイル関する議論に終止符を打つことを目的とした「opinionated」なformatterです。
[Prettierと近い哲学](https://prettier.io/docs/en/option-philosophy.html)を持ち、
スタイルに関する議論がBiomeのオプションに関する議論に発展するのを避けるために、いくつかのオプションのみをサポートしています。
チーム内での[本質的でない議論](https://ja.wikipedia.org/wiki/パーキンソンの凡俗法則)を防ぎ、本当に重要なことに集中できるようにするために、[新しいオプションを意図的に追加しない](https://github.com/prettier/prettier/issues/40)ようにしています。
チーム内での[些細な議論](https://ja.wikipedia.org/wiki/パーキンソンの凡俗法則)を防ぎ、本当に重要なことに集中できるようにするために、[新しいオプションを意図的に追加しない](https://github.com/prettier/prettier/issues/40)ようにしています。

## オプション

Expand Down Expand Up @@ -48,6 +48,7 @@ Biomeがサポートする、言語に依存しないオプションは以下の
"indentStyle": "tab",
"indentWidth": 2,
"lineWidth": 80,
"lineEnding": "lf",
"ignore": []
}
}
Expand Down Expand Up @@ -87,3 +88,28 @@ const expr =
0,
];
```

## 言語ごとの設定

他のツールと違って、Biomeは言語ごとに関するオプションを設定することができます。

### JavaScript

以下は、JavaScript のファイルに適用されるデフォルトの設定です:

```json title="biome.json"
{
"javascript": {
"formatter": {
"arrowParentheses":"always",
"jsxQuoteStyle": "double",
"semicolons": "always",
"trailingComma": "all",
"quoteProperties": "asNeeded",
"bracketSpacing": true,
"bracketSameLine": false
}
}
}
```

38 changes: 38 additions & 0 deletions website/src/content/docs/ja/formatter/option-philosophy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
title: Formatter オプションに対する考え方
description: 独断的なフォーマッターを設定する
---

>💡 Biomeは、[Prettierのオプションに対する考え方](https://prettier.io/docs/en/option-philosophy)と同様のアプローチを採用しています。formatに関する既存のオプションセットは安定しており、新しいオプションが検討される可能性は低いです。
>
>この文書では、Biomeがどのようにして今日の考え方に至ったのか、その歴史と今後の展望について説明しています。
Biomeは*「opinionated」なformatter*です。理想的には、コードをformatする正しい方法は 1 つしかないと想定し、常にそのスタイルを強制することを意味します。プロジェクトに関係なく、セットアップに関係なく、Biomeによってformatされたコードは常に同じように見えるでしょう。別の視点から見ると、Biomeは独自の*自動スタイルガイド*であり、他のスタイルガイドを実装するためのツールではありません。

このように強い意見を持つことは強引に思えるかもしれませんが、採用後すぐにその利点が明らかになります。空白がどこにあるべきか、行が分割されるべきか、行がインデントされるべきかなど、これまでの議論が*消えてなくなります*[些細な議論](https://en.wikipedia.org/wiki/Law_of_triviality)によって、重要なことに集中することが妨げられることはもうありません。コードレビューでは、再formatの要求や繰り返される議論がなくなります。Biomeがきれいで、読みやすく、一貫性のあるコードへformatするという信頼があれば、それだけで十分です。

個々のチームや組織内での利点に加えて、一貫したformatterの採用は、ウェブエコシステム全体に利益をもたらし、プロジェクト間の移動時に熟知を維持しやすくし、新人がパターンをより直感的に学び、認識しやすくすることに役立ちます。

現在のウェブエコシステムでは、Prettierが最も人気のあるformatterです。Biome と同様に「opinionated」であり、[オプションの追加に関する厳格な考え方](https://prettier.io/docs/en/option-philosophy)を持っています。Biomeは、[Prettierとの互換性を大いに重視しています](https://biomejs.dev/blog/biome-wins-prettier-challenge)。そのため、Prettierが実装している多くの意見を採用し、設定もその例外ではありません。

BiomeはPrettierとの高い互換性を誇り、ユーザーの移行プロセスを可能な限り痛みのないものにしていますが、それには同様の注意点も伴っています。

## 既存のオプション

Biomeは、最初はJavaScriptエコシステムで最も一般的で議論の的になっているスタイルガイドラインをターゲットにした設定オプションからスタートしました:インデントスタイル(タブ対スペース)、インデント幅(タブに等しい2スペース、または4スペース?)、セミコロンの強制。これらの点に対するオプションを追加することは、ほとんどの人々のニーズに十分対応すると考えられ、他のオプションを追加することは強く検討されませんでした。

[Prettierのオプションに対する考え方](https://twitter.com/Vjeux/status/1722733472522142022)に基づき、Biomeは新たなスタートを切るチャンスがあり、Prettierが `--bracket-same-line``--arrow-parens` などの既存のオプションで陥った落とし穴を避けることができました:

> ...これらのオプションについては、私たちは保持していることを望んでいません。チーム内で多くの議論を引き起こしており、それを申し訳なく思っています。今では削除するのが難しいため、これらのオプションは歴史的な成果物として存在しており、他のオプションを追加するための動機付けにはなりません(「これらのオプションが存在するなら、なぜこのオプションはダメなのか?」といったような)。
しかし、[Prettier Challengeが発表](https://twitter.com/Vjeux/status/1722733472522142022)された際、Biomeはこのチャレンジを受け入れることにし、Prettierが持つ全ての設定オプションを実装して完全な互換性を達成する必要がありました。

ただ、BiomeはPrettierと同じ考え方を共有しており、これらのオプションは互換性のためのレガシー機能として考えています。これらのオプションは、さらに多くのオプションが追加されることを示すものではなく、将来的な他のオプションの存在を裏付ける根拠として使用されるべきではありません。

## 新しいオプション

Prettierと同様に、Biomeは現在のオプションセットが安定しており、十分であり、追加や変更の余地はないと信じています。追加の設定オプションに関するリクエストは考慮される可能性が低く、議論なしで閉じられることがあります。

それにもかかわらず、Biomeはまだ比較的新しいツールとして確立されつつあり、他では実現不可能と思われる新しいアイデアや進歩への道を切り開く機会がたくさんあります。

Biomeのformatスタイルも比較的安定しており、できる限りPrettierと一致することを目指していますが、[いくつかの意図的な逸脱](https://github.com/biomejs/biome/issues/739)があります。Biomeのスタイルの変更は検討され、実装される可能性がありますが、これらも設定可能なオプションになることはほとんどなく、代わりに将来のBiomeの全バージョンに一律に適用されることになります。

0 comments on commit 582e1c4

Please sign in to comment.