# 機能設計書 17-ファイルフォーマット（--write）

## 概要

本ドキュメントは、Prettier CLIにおけるファイルフォーマット機能（--write オプション）について記述する。

### 本機能の処理概要

**業務上の目的・背景**：開発者がソースコードをPrettierの規則に従ってフォーマットし、ファイルを直接上書き保存する必要がある。--writeオプションは、指定されたファイルをフォーマットしてその場で上書きする機能を提供する。これにより、手動でのコピー&ペーストや出力のリダイレクトなしに、効率的にコードをフォーマットできる。

**機能の利用シーン**：
- pre-commitフックでのコード自動フォーマット時
- CI/CDパイプラインでのコード整形時
- 複数ファイルの一括フォーマット時
- プロジェクト全体のコード統一時

**主要な処理内容**：
1. 指定されたファイルパターンの展開（glob）
2. 無視ルール（.prettierignore等）の適用
3. 各ファイルの設定解決と読み込み
4. フォーマット処理の実行
5. フォーマット結果のファイル上書き保存
6. 処理時間とステータスの出力

**関連システム・外部連携**：
- パターン展開システム（expand-patterns.js）
- 無視ファイル処理システム（directory-ignorer.js）
- フォーマットキャッシュシステム（format-results-cache.js）
- 設定解決システム（resolveConfig）

**権限による制御**：ファイル書き込み権限が必要

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 10 | Usage - Install | 主機能 | npm経由でのインストール後のフォーマット実行方法を説明 |
| 13 | Usage - Pre-commit | 主機能 | pre-commitフックでのフォーマット実行方法を説明 |
| 15 | Usage - CLI | 主機能 | CLIでのファイルフォーマット実行方法を説明 |

## 機能種別

ファイル更新処理（CRUD: Update）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| filePatterns | string[] | Yes | フォーマット対象のファイルパターン（glob） | 少なくとも1つ必要 |
| --write / -w | boolean | Yes | ファイル上書きモードを有効化 | - |
| --check / -c | boolean | No | チェックモードと併用可能 | - |
| --list-different / -l | boolean | No | 差分表示と併用可能 | - |
| --cache | boolean | No | キャッシュを使用して変更ファイルのみ処理 | - |
| --ignore-path | string[] | No | 無視パターンファイルのパス | 有効なファイルパス |

### 入力データソース

- ファイルシステムからのソースファイル読み込み

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| formattedFile | file | フォーマットされたファイル（上書き保存） |
| consoleOutput | string | 処理結果のログ出力 |
| exitCode | number | 終了コード（0: 成功、1: フォーマット差分あり、2: エラー） |

### 出力先

- フォーマット対象ファイル（上書き）
- 標準出力（処理ログ）
- 標準エラー出力（エラーメッセージ）

## 処理フロー

### 処理シーケンス

```
1. formatFiles関数が呼び出される
   └─ 無視ルールの読み込み（createIsIgnoredFunction）
2. ファイルパターンの展開
   └─ expandPatterns関数でglobパターンを解決
3. キャッシュの初期化（--cache使用時）
   └─ FormatResultsCacheインスタンス作成
4. 各ファイルに対してループ処理
   └─ ファイル読み込み（fs.readFile）
   └─ 無視判定（isIgnored）
   └─ 設定解決（getOptionsForFile）
   └─ キャッシュ確認（キャッシュ使用時）
   └─ フォーマット実行（format）
   └─ 差分判定（output !== input）
   └─ ファイル上書き（mockable.writeFormattedFile）
   └─ キャッシュ更新
5. 処理結果サマリーの出力
   └─ フォーマット件数、エラー件数の表示
6. 終了コードの設定
```

### フローチャート

```mermaid
flowchart TD
    A[開始: formatFiles] --> B[無視ルール読み込み]
    B --> C[ファイルパターン展開]
    C --> D{キャッシュ使用?}
    D -->|Yes| E[キャッシュ初期化]
    D -->|No| F[ファイルループ開始]
    E --> F
    F --> G{ファイル残り?}
    G -->|No| P[サマリー出力]
    G -->|Yes| H[ファイル読み込み]
    H --> I{無視対象?}
    I -->|Yes| F
    I -->|No| J[設定解決]
    J --> K{キャッシュヒット?}
    K -->|Yes| L[スキップ]
    K -->|No| M[フォーマット実行]
    M --> N{差分あり?}
    N -->|No| O[unchanged出力]
    N -->|Yes| Q[ファイル上書き]
    Q --> R[ログ出力]
    L --> F
    O --> F
    R --> F
    P --> S[終了コード設定]
    S --> T[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-017-01 | 差分時のみ上書き | フォーマット結果が元と異なる場合のみ上書き（mtime保持） | 常時 |
| BR-017-02 | キャッシュ更新 | 成功時はキャッシュを更新、失敗時はキャッシュ削除 | --cache使用時 |
| BR-017-03 | 並行処理 | for awaitで逐次処理（並列ではない） | 常時 |
| BR-017-04 | エラー継続 | 1ファイルのエラーで全体を停止しない | 常時 |
| BR-017-05 | 終了コード | エラー時は2、差分ありは1（--check/--list-different併用時） | 常時 |

### 計算ロジック

特になし

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

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

データベース操作なし（ファイルシステムのみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 2 | UndefinedParserError | パーサーが不明 | エラーメッセージ出力、処理継続 |
| 2 | SyntaxError | パースエラー | エラー位置出力、処理継続 |
| 2 | ConfigError | 設定エラー | エラーメッセージ出力、即時終了 |
| 2 | IOError | ファイル読み書きエラー | エラーメッセージ出力、処理継続 |

### リトライ仕様

リトライは行わない（エラーファイルはスキップして継続）

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

ファイル単位での処理（ファイル間のトランザクションなし）

## パフォーマンス要件

- 単一ファイル処理: 100ms以下（ファイルサイズ依存）
- 大量ファイル処理: --cacheオプション使用推奨

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

- 指定されたファイルのみ上書き
- シンボリックリンクの取り扱いに注意

## 備考

- --checkや--list-differentと併用可能
- --debug-checkと併用不可

---

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

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

### 推奨読解順序

#### Step 1: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.js | `src/cli/index.js` | CLIエントリーポイント、formatFiles呼び出し |
| 1-2 | format.js | `src/cli/format.js` | formatFiles関数の実装 |

**主要処理フロー**:
1. **111-113行目（index.js）**: hasFilePatternsでformatFiles呼び出し
2. **272-504行目（format.js）**: formatFiles関数本体

#### Step 2: ファイル処理ループを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | format.js | `src/cli/format.js` | ファイル処理ループ |

**主要処理フロー**:
- **305-323行目**: ファイル読み込みと無視判定
- **340-357行目**: ファイル読み込み（fs.readFile）
- **365-396行目**: フォーマット実行とエラーハンドリング
- **411-440行目**: --write時のファイル上書き処理

#### Step 3: ファイル上書き処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | format.js | `src/cli/format.js` | writeFormattedFile呼び出し |
| 3-2 | mockable.js | `src/cli/mockable.js` | writeFormattedFile実装 |

**主要処理フロー**:
- **421行目**: mockable.writeFormattedFile(filename, output)
- テスト時のモック可能性を考慮した設計

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

```
prettier [files] --write
    │
    └─ run() [index.js]
           │
           └─ main(context)
                  │
                  └─ formatFiles(context) [format.js]
                         │
                         ├─ createIsIgnoredFromContextOrDie()
                         │
                         ├─ findCacheFile() [--cache時]
                         │      └─ FormatResultsCache
                         │
                         └─ for await (expandPatterns())
                                │
                                ├─ fs.readFile(filename)
                                │
                                ├─ getOptionsForFile(context, filename)
                                │
                                ├─ format(context, input, options)
                                │      └─ prettier.formatWithCursor()
                                │
                                └─ mockable.writeFormattedFile()
```

### データフロー図

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

filePatterns ───▶ expandPatterns() ───▶ filenames[]
                          │
                          ▼
               for each filename
                          │
    file ───▶ fs.readFile() ───▶ input
                          │
                          ▼
   config ◀── getOptionsForFile()
                          │
                          ▼
   input ───▶ format() ───▶ output
                          │
                          ▼
              {input !== output?}
                          │
                          ▼
              writeFormattedFile() ───▶ file (上書き)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.js | `src/cli/index.js` | ソース | CLIエントリーポイント |
| format.js | `src/cli/format.js` | ソース | formatFiles関数実装 |
| expand-patterns.js | `src/cli/expand-patterns.js` | ソース | ファイルパターン展開 |
| mockable.js | `src/cli/mockable.js` | ソース | ファイル書き込み（モック可能） |
| format-results-cache.js | `src/cli/format-results-cache.js` | ソース | フォーマットキャッシュ |
| directory-ignorer.js | `src/cli/directory-ignorer.js` | ソース | 無視ファイル処理 |
| context.js | `src/cli/context.js` | ソース | CLIコンテキスト |
| cli-options.evaluate.js | `src/cli/cli-options.evaluate.js` | ソース | --writeオプション定義 |
| options/get-options-for-file.js | `src/cli/options/get-options-for-file.js` | ソース | ファイル別設定取得 |
