# 通知設計書 10-ファイル名 + 処理時間

## 概要

本ドキュメントは、Prettierの`--write`オプション使用時にフォーマット完了したファイル名と処理時間を表示するログ通知の設計を記述する。

### 本通知の処理概要

「ファイル名 + 処理時間」通知は、`--write`オプションを使用してファイルをフォーマットした際に、各ファイルの処理完了を示すログメッセージとして表示される。フォーマットされたファイル名と処理にかかった時間（ミリ秒）が出力される。

**業務上の目的・背景**：ユーザーが`--write`オプションでファイルをフォーマットする際、どのファイルが処理されたか、そしてその処理にどれくらいの時間がかかったかを知ることは有用である。特に多数のファイルを処理する場合や、パフォーマンスの問題を診断する場合に、この情報は重要である。処理時間を表示することで、ユーザーはパフォーマンスのボトルネックを特定できる。

**通知の送信タイミング**：`prettier --write`コマンド実行時、各ファイルのフォーマット処理が完了した直後に表示される。`src/cli/format.js`の`formatFiles`関数内でファイル書き込み後に出力される。

**通知の受信者**：CLIを使用しているユーザー。

**通知内容の概要**：フォーマットされたファイルの相対パスと処理時間（ミリ秒単位）。

**期待されるアクション**：特にアクションは不要。処理状況の確認のみ。

## 通知種別

CLIログ出力（標準出力への出力）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 低 |
| リトライ | なし |

### 送信先決定ロジック

`--write`オプション指定時、かつ`--check`および`--list-different`オプションが指定されていない場合、ファイルフォーマット完了後に`context.logger.log()`を通じて出力される。

## 通知テンプレート

### メール通知の場合

該当なし（CLI出力のみ）

### 本文テンプレート

```
{filename} {time}ms
```

例：
```
src/index.js 50ms
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| filename | ファイルの相対パス | path.relative(cwd, filename) | Yes |
| time | 処理時間（ミリ秒） | Math.round(getTimestamp() - start) | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| CLI実行 | prettier --write実行 | ファイルフォーマット完了 | 差分がある場合 |
| CLI実行 | prettier --write実行 | --checkと--list-differentがない | これらがある場合は出力されない |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| --write なし | --writeオプションなしでは表示されない |
| --check あり | --checkオプションがある場合は表示されない |
| --list-different あり | --list-differentオプションがある場合は表示されない |
| パフォーマンステストフラグあり | --debug-benchmark等の場合は処理がスキップされる |
| --log-level silent | ログレベルがsilentの場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[prettier --write実行] --> B[formatFiles開始]
    B --> C[ファイルごとの処理]
    C --> D[処理開始時刻記録]
    D --> E[format処理]
    E --> F{isDifferent?}
    F -->|No| G[unchangedメッセージ]
    F -->|Yes| H{argv.check or argv.listDifferent?}
    H -->|Yes| I[メッセージ出力なし]
    H -->|No| J[ファイル名 + 処理時間出力]
    J --> K[ファイル書き込み]
    G --> L[次のファイルへ]
    I --> L
    K --> L
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし（Prettierはデータベースを使用しない）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| - | この通知ではエラーは発生しない | - |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | - |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

該当なし

### 配信時間帯

該当なし

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

ファイルの相対パスが出力されるが、通常は問題とならない。センシティブなパス情報がある場合は、出力をファイルにリダイレクトするなどの対処が必要。

## 備考

- 処理時間は`Math.round()`で整数に丸められる
- ファイルパスは現在の作業ディレクトリからの相対パスで表示される
- POSIXスタイル（スラッシュ区切り）に正規化される
- 差分がないファイルは別の形式で表示される（「(unchanged)」付き）

---

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

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

### 推奨読解順序

#### Step 1: 時間計測の仕組みを理解する

処理時間の計測方法を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | format.js | `src/cli/format.js` | 処理開始時刻の記録（365行目） |

**読解のコツ**:
- 365行目: `const start = mockable.getTimestamp()` - 処理開始時刻を記録
- 412行目: `const timeToDisplay = \`${Math.round(mockable.getTimestamp() - start)}ms\`` - 経過時間を計算

#### Step 2: 通知出力ロジックを理解する

通知が出力される条件と処理フローを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | format.js | `src/cli/format.js` | --write時の処理（411-440行目） |

**主要処理フロー**:
- **411行目**: `if (context.argv.write)` - --writeオプションが指定されている場合
- **412行目**: 処理時間の計算
- **415行目**: `if (isDifferent)` - 差分がある場合
- **416行目**: `if (!context.argv.check && !context.argv.listDifferent)` - --checkと--list-differentがない場合
- **417行目**: `context.logger.log(\`${fileNameToDisplay} ${timeToDisplay}\`)` - メッセージ出力

#### Step 3: ファイルパスの正規化を理解する

ファイルパスがどのように表示されるかを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | format.js | `src/cli/format.js` | ファイル名の準備（331行目） |

**主要処理フロー**:
- **331行目**: `const fileNameToDisplay = normalizeToPosix(path.relative(cwd, filename))` - 相対パスに変換し、POSIXスタイルに正規化

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

```
prettier --write [files]
    │
    └─ formatFiles() [src/cli/format.js:272]
           │
           ├─ ファイルごとのループ [305行目]
           │      │
           │      ├─ const start = getTimestamp() [365行目]
           │      ├─ format() [379行目]
           │      ├─ isDifferent = output !== input [398行目]
           │      │
           │      └─ if (argv.write && isDifferent && !argv.check && !argv.listDifferent)
           │             │
           │             └─ "{filename} {time}ms" 出力 [417行目]
           │                    └─ context.logger.log()
           │
           └─ 処理完了
```

### データフロー図

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

--write オプション    formatFiles()            ログメッセージ
  │                    │                         │
  v                    v                         │
ファイルリスト      処理開始時刻記録              │
                     │                          │
                     v                          v
              format処理                  context.logger.log()
                     │                          │
                     v                          v
              処理時間計算               stdout出力
              Math.round(end - start)    {filename} {time}ms
                     │
                     v
              条件判定
              ├─ isDifferent?
              ├─ argv.check?
              └─ argv.listDifferent?
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| format.js | `src/cli/format.js` | ソース | formatFiles関数、通知出力ロジック |
| logger.js | `src/cli/logger.js` | ソース | log関数の実装 |
| mockable.js | `src/cli/mockable.js` | ソース | getTimestamp関数 |
| utilities.js | `src/cli/utilities.js` | ソース | normalizeToPosix関数 |
| index.js | `src/cli/index.js` | ソース | CLIエントリーポイント |
