# 機能設計書 46-オブジェクトプロパティのクォート（quoteProps）

## 概要

本ドキュメントは、Prettierのオブジェクトプロパティクォート制御機能（quoteProps）の設計仕様を定義する。

### 本機能の処理概要

quotePropsオプションは、オブジェクトリテラルのプロパティキーをクォートで囲むかどうかを制御する。必要な場合のみクォートを付ける（as-needed）、いずれかのプロパティにクォートが必要な場合は全てのプロパティにクォートを付ける（consistent）、または入力のクォートを維持する（preserve）の3つのモードから選択できる。

**業務上の目的・背景**：
オブジェクトプロパティのクォートスタイルは、コードの可読性と一貫性に影響する。JavaScriptでは、有効な識別子であればクォートなしでプロパティを記述できるが、特殊文字やハイフンを含むキーにはクォートが必要。この機能により、プロジェクト全体で一貫したプロパティキーのスタイルを自動的に適用でき、コードの見た目を統一できる。

**機能の利用シーン**：
1. 簡潔なコードを好み、必要な場合のみクォートを付けたい場合（as-needed）
2. オブジェクト内で統一感を持たせたい場合（consistent）
3. 既存コードのスタイルを維持したい場合（preserve）
4. JSON風のスタイルでプロパティを記述したい場合（consistent）

**主要な処理内容**：
1. quotePropsオプションの値取得（as-needed/consistent/preserve）
2. プロパティキーの解析
3. クォートが必要かどうかの判定（識別子として有効か）
4. 兄弟プロパティとの一貫性チェック（consistent mode）
5. クォートの追加または削除

**関連システム・外部連携**：
- JavaScript/TypeScriptパーサー
- オブジェクトプリンター
- CLI、API、エディタプラグインからの呼び出し

**権限による制御**：
特になし。全てのユーザーが同一の機能を使用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | Playground | 補助機能 | サイドバーからプロパティクォートを設定 |
| 19 | Configuration - Options | 主機能 | quotePropsオプションの詳細説明 |

## 機能種別

設定オプション / フォーマット制御

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| quoteProps | string | No | プロパティキーをクォートするタイミング | "as-needed" / "consistent" / "preserve" のいずれか |

### 入力データソース

- 設定ファイル（.prettierrc、prettier.config.js、package.json等）
- CLI引数（--quote-props）
- API呼び出し時のオプションオブジェクト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| formatted | string | プロパティクォートが適切に制御されたフォーマット済みコード |

### 出力先

- 標準出力（CLIの場合）
- ファイル（--write オプション使用時）
- API戻り値

## 処理フロー

### 処理シーケンス

```
1. オプション解析
   └─ quotePropsオプションの値を取得（デフォルト: "as-needed"）
2. プロパティキー解析
   └─ キーの種類を判定（Identifier/StringLiteral/NumericLiteral）
3. クォート必要性判定
   └─ isKeySafeToUnquote / isKeySafeToQuote関数で判定
4. 兄弟チェック（consistent mode）
   └─ hasSiblingsRequireQuoted関数で一貫性を確認
5. キー出力
   └─ printKey関数でクォート付き/なしで出力
```

### フローチャート

```mermaid
flowchart TD
    A[プロパティキー検出] --> B{quotePropsの値}
    B -->|as-needed| C{クォートなしでOK?}
    B -->|consistent| D{兄弟にクォート必須あり?}
    B -->|preserve| E[入力のまま維持]
    C -->|Yes| F[クォートを削除]
    C -->|No| G[クォートを維持]
    D -->|Yes| H[全てクォート付き]
    D -->|No| I{クォートなしでOK?}
    I -->|Yes| F
    I -->|No| G
    F --> J[出力]
    G --> J
    H --> J
    E --> J
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-46-01 | デフォルト設定 | デフォルトでは"as-needed"（必要時のみクォート） | quoteProps未指定 |
| BR-46-02 | 必要時のみ | "as-needed"ではクォートが必要な場合のみ付ける | quoteProps: "as-needed" |
| BR-46-03 | 一貫性 | "consistent"では1つでもクォートが必要なら全てに付ける | quoteProps: "consistent" |
| BR-46-04 | 保持 | "preserve"では入力のクォートをそのまま維持 | quoteProps: "preserve" |
| BR-46-05 | 識別子判定 | ES5識別子として有効な場合はクォートなしでOK | 常に適用 |
| BR-46-06 | TypeScript制限 | TypeScriptではプロパティのクォート/アンクォートは型に影響 | parser: typescript |

### 計算ロジック

クォート必要性判定:
```javascript
// クォートを外せるか判定
function isKeySafeToUnquote(node, options) {
  // JSON/JSONCではクォート除去不可
  if (options.parser === "json" || options.parser === "jsonc") {
    return false;
  }
  // StringLiteralキーで、printString後の値が元の値と同じ
  // かつ、ES5識別子として有効
  return isEs5IdentifierName(value);
}
```

## データベース操作仕様

### 操作別データベース影響一覧

該当なし（本機能はデータベース操作を行わない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | バリデーションエラー | quotePropsに不正な値が指定された場合 | "as-needed"/"consistent"/"preserve"のいずれかを指定する |

### リトライ仕様

該当なし

## トランザクション仕様

該当なし

## パフォーマンス要件

- 処理時間への影響は軽微
- 兄弟プロパティのキャッシュにWeakMapを使用（needQuoteKeysCache）

## セキュリティ考慮事項

特になし

## 備考

- TypeScriptでは型推論に影響するため、プロパティのクォート/アンクォートに制限がある
- JSON/JSONCでは常にダブルクォートを使用
- 数値キーのクォート/アンクォートはパーサーによって制限あり

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

オプション定義を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | options.js | `src/language-js/options.js` | quotePropsオプションの定義（72-92行目） |

**読解のコツ**: quotePropsはchoice型で、"as-needed"、"consistent"、"preserve"の3つの選択肢がある。デフォルトは"as-needed"。

#### Step 2: キー出力ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | key.js | `src/language-js/print/key.js` | printKey関数（195-227行目） |

**主要処理フロー**:
1. **199-200行目**: computed keyの場合は`[key]`形式で出力
2. **203-214行目**: shouldQuoteKeyがtrueなら識別子/数値キーをクォート
3. **216-224行目**: shouldUnquoteKeyがtrueなら文字列キーをアンクォート

#### Step 3: 判定ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | key.js | `src/language-js/print/key.js` | isKeySafeToUnquote関数（80-131行目） |
| 3-2 | key.js | `src/language-js/print/key.js` | hasSiblingsRequireQuoted関数（133-149行目） |
| 3-3 | key.js | `src/language-js/print/key.js` | shouldQuoteKey / shouldUnquoteKey関数（151-168行目） |

**主要処理フロー**:
- **151-159行目**: shouldQuoteKey - JSON/JSONCまたはconsistent & 兄弟にクォート必須ありの場合
- **161-168行目**: shouldUnquoteKey - as-needed または consistent & 兄弟にクォート必須なしの場合

### プログラム呼び出し階層図

```
format() / formatWithCursor()
    │
    ├─ core.formatWithCursor()
    │      └─ printToDoc()
    │             └─ printer.print()
    │                    │
    │                    └─ printProperty() [property.js]
    │                           │
    │                           └─ printKey() [key.js]
    │                                  │
    │                                  ├─ shouldQuoteKey()
    │                                  │      └─ hasSiblingsRequireQuoted()
    │                                  │
    │                                  ├─ shouldUnquoteKey()
    │                                  │      └─ isKeySafeToUnquote()
    │                                  │
    │                                  └─ isKeySafeToQuote()
```

### データフロー図

```
[入力]               [処理]                      [出力]

options.quoteProps ──▶ printKey() ─────────────▶ key or "key"
                     │
propertyKey ─────────┘
                     │
                     ├─ shouldQuoteKey()
                     │      └─ hasSiblingsRequireQuoted()
                     │
                     ├─ shouldUnquoteKey()
                     │      └─ isKeySafeToUnquote()
                     │
                     └─ isKeySafeToQuote()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| options.js | `src/language-js/options.js` | ソース | quotePropsオプション定義 |
| key.js | `src/language-js/print/key.js` | ソース | プロパティキー出力処理 |
| print-string.js | `src/utilities/print-string.js` | ソース | 文字列出力（quoteProps連携） |
