# 通知設計書 6-ReportWorkDoneProgress

## 概要

本ドキュメントは、clangd Language Serverが実装するLSP標準メソッド `$/progress` （WorkDoneProgressReport）の通知仕様を定義する。この通知は、長時間処理の進捗状況（パーセンテージ、メッセージ）をクライアントに通知するために使用される。

### 本通知の処理概要

ReportWorkDoneProgress通知は、バックグラウンドインデックス構築などの長時間処理の進捗状況をエディタに伝え、プログレスバーの更新を行わせる機能である。

**業務上の目的・背景**：大規模なC/C++プロジェクトのインデックス構築は、数分から数十分かかることがある。開発者にとって、処理がどの程度進んでいるかを把握できることは、作業計画を立てる上で重要である。パーセンテージとメッセージ（例：「3/25 files」）を表示することで、開発者は残り時間を推測し、いつコード補完やジャンプ機能が完全に利用可能になるかを予測できる。

**通知の送信タイミング**：バックグラウンドインデックスの処理が進行するたびに送信される。具体的には、`onBackgroundIndexProgress`コールバックでBackgroundQueue::Statsが更新され、まだ処理が完了していない状態（Completed < Enqueued）の時に送信される。

**通知の受信者**：WorkDoneProgress機能をサポートするLSPクライアントが受信者となる。BeginWorkDoneProgressを受信しているセッションに対して送信される。

**通知内容の概要**：プログレストークン、進捗パーセンテージ（0-100）、進捗メッセージ（"3/25"形式）が含まれる。

**期待されるアクション**：クライアントは受信した通知に基づいてプログレスバーを更新する。パーセンテージとメッセージを表示し、ユーザーに進捗を伝える。

## 通知種別

LSP Notification（サーバーからクライアントへの一方向通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期 |
| 優先度 | 低 |
| リトライ | なし（通知は一方向のため） |

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

WorkDoneProgress機能をサポートし、BeginWorkDoneProgressを受信しているLSPクライアントに送信される。

## 通知テンプレート

### LSP Notification形式

| 項目 | 内容 |
|-----|------|
| メソッド名 | `$/progress` |
| 形式 | JSON-RPC 2.0 Notification |

### 本文テンプレート

```json
{
  "jsonrpc": "2.0",
  "method": "$/progress",
  "params": {
    "token": "backgroundIndexProgress",
    "value": {
      "kind": "report",
      "message": "3/25",
      "percentage": 12
    }
  }
}
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| token | プログレス識別トークン | 固定値 "backgroundIndexProgress" | Yes |
| value.kind | 進捗の種類 | 固定値 "report" | Yes |
| value.message | 進捗メッセージ | "{Completed-LastIdle}/{Enqueued-LastIdle}" | No |
| value.percentage | 進捗パーセンテージ（0-100） | 100*(Completed-LastIdle)/(Enqueued-LastIdle) | No |
| value.cancellable | キャンセル可能かどうか | 設定されていない | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 内部処理 | BackgroundQueue進捗更新 | State==Live && Completed < Enqueued | インデックス処理進行中 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| BackgroundIndexProgressState!=Live | プログレスバーがまだ開始されていない場合 |
| Completed >= Enqueued | 処理が完了している場合（Endを送信） |
| サーバー未初期化 | initializeリクエスト完了前は送信されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[BackgroundQueue進捗更新] --> B[onBackgroundIndexProgress コールバック]
    B --> C{State==Live?}
    C -->|No| D[他の状態処理]
    C -->|Yes| E[NotifyProgress]
    E --> F{Completed < Enqueued?}
    F -->|Yes| G[ReportWorkDoneProgress送信]
    F -->|No| H[EndWorkDoneProgress送信]
    G --> I[プログレスバー更新]
```

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

### 参照テーブル一覧

該当なし（LSPサーバーはインメモリで動作）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| Transport失敗 | クライアントとの接続断 | ログ出力、再接続待機 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし（進捗更新駆動） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（リアルタイム配信）

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

- プログレス情報には機密データは含まれない
- LSP通信はローカルプロセス間通信が基本であり、外部ネットワークへの送信は想定していない

## 備考

- LSP標準メソッドの一部（$/progress）
- パーセンテージは(Completed - LastIdle) / (Enqueued - LastIdle) * 100で計算
- メッセージは「完了数/総数」形式（例：「3/25」）
- LastIdleはインデックス処理が最後にアイドル状態だった時点の完了数

---

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

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

### 推奨読解順序

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

WorkDoneProgressReport構造体の定義を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Protocol.h | `clang-tools-extra/clangd/Protocol.h` | WorkDoneProgressReport構造体定義（行692-721） |
| 1-2 | Protocol.cpp | `clang-tools-extra/clangd/Protocol.cpp` | toJSON(WorkDoneProgressReport)実装（行600-610） |

**読解のコツ**: percentage, message, cancellableがオプショナルフィールド。kindは"report"固定。

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

ReportWorkDoneProgress通知の送信箇所を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ClangdLSPServer.h | `clang-tools-extra/clangd/ClangdLSPServer.h` | ReportWorkDoneProgress通知のバインド宣言（行202-203） |
| 2-2 | ClangdLSPServer.cpp | `clang-tools-extra/clangd/ClangdLSPServer.cpp` | ReportWorkDoneProgressバインド（行1741） |
| 2-3 | ClangdLSPServer.cpp | `clang-tools-extra/clangd/ClangdLSPServer.cpp` | NotifyProgress内のReport送信（行1870-1878） |

**主要処理フロー**:
1. **行1741**: `Bind.outgoingNotification("$/progress")`でバインド
2. **行1870-1871**: Completed < Enqueuedの条件確認
3. **行1872-1877**: WorkDoneProgressReport構築
4. **行1878**: `ReportWorkDoneProgress({ProgressToken, std::move(Report)})`で送信

#### Step 3: 進捗計算ロジックを理解する

パーセンテージとメッセージの計算方法を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ClangdLSPServer.cpp | `clang-tools-extra/clangd/ClangdLSPServer.cpp` | 進捗計算（行1873-1877） |

**主要処理フロー**:
- **行1873-1874**: `percentage = 100 * (Stats.Completed - Stats.LastIdle) / (Stats.Enqueued - Stats.LastIdle)`
- **行1875-1876**: `message = formatv("{0}/{1}", Stats.Completed - Stats.LastIdle, Stats.Enqueued - Stats.LastIdle)`

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

```
BackgroundQueue (インデックス処理)
    │
    └─ ClangdServer::Callbacks::onBackgroundIndexProgress()
           │
           └─ ClangdLSPServer::onBackgroundIndexProgress()
                  │
                  └─ NotifyProgress(Stats)
                         │
                         ├─ [Completed < Enqueued]
                         │      ├─ percentage計算
                         │      ├─ message構築
                         │      └─ ReportWorkDoneProgress送信
                         │
                         └─ [Completed >= Enqueued]
                                └─ EndWorkDoneProgress送信
```

### データフロー図

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

BackgroundQueue::Stats ───▶ 進捗計算 ───▶ ProgressParams<WorkDoneProgressReport>
    │                           │                        │
    │ Completed                 ▼                        ▼
    │ Enqueued         percentage = 100 * (C-L)/(E-L)  toJSON()
    │ LastIdle         message = "{C-L}/{E-L}"           │
    │                                                    ▼
    └──────────────────────────────────────▶ JSON-RPC通知
                                                         │
                                                         ▼
                                                   [LSPクライアント]
                                                   プログレスバー更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Protocol.h | `clang-tools-extra/clangd/Protocol.h` | ヘッダ | WorkDoneProgressReport定義 |
| Protocol.cpp | `clang-tools-extra/clangd/Protocol.cpp` | ソース | JSON変換実装 |
| ClangdLSPServer.h | `clang-tools-extra/clangd/ClangdLSPServer.h` | ヘッダ | ReportWorkDoneProgress通知宣言 |
| ClangdLSPServer.cpp | `clang-tools-extra/clangd/ClangdLSPServer.cpp` | ソース | Progress送信ロジック |
| LSPBinder.h | `clang-tools-extra/clangd/LSPBinder.h` | ヘッダ | LSPメソッドバインディング |
| Transport.h | `clang-tools-extra/clangd/Transport.h` | ヘッダ | 通信層インターフェース |
