# 通知設計書 5-BeginWorkDoneProgress

## 概要

本ドキュメントは、clangd Language Serverが実装するLSP標準メソッド `$/progress` （WorkDoneProgressBegin）の通知仕様を定義する。この通知は、長時間処理（インデックス作成等）の開始をクライアントに通知するために使用される。

### 本通知の処理概要

BeginWorkDoneProgress通知は、バックグラウンドインデックス構築などの長時間処理が開始されたことをエディタに伝え、プログレスバーの表示を開始させる機能である。

**業務上の目的・背景**：大規模なC/C++プロジェクトでは、初回起動時やプロジェクト変更時にバックグラウンドインデックスの構築が行われる。この処理には時間がかかることがあり、開発者に進捗状況を可視化することで、「clangdが動作しているのか」「いつ準備が完了するのか」という不安を解消できる。プログレスバー表示により、開発者はclangdの処理状況を把握し、適切なタイミングでコード補完やジャンプ機能を利用できる。

**通知の送信タイミング**：バックグラウンドインデックスが開始されたタイミングで送信される。具体的には、`onBackgroundIndexProgress`コールバックで処理キューにアイテムが追加され、プログレスバーがまだ表示されていない状態（BackgroundIndexProgress::Empty）の時に送信される。

**通知の受信者**：WorkDoneProgress機能をサポートするLSPクライアントが受信者となる。クライアントはcapabilities.window.workDoneProgress=trueを設定することでこの機能を有効化する。

**通知内容の概要**：プログレストークン、処理のタイトル（"indexing"）、キャンセル可能かどうか、パーセンテージ表示の有無が含まれる。

**期待されるアクション**：クライアントは受信した通知に基づいてプログレスバーを表示開始する。タイトル「indexing」と共に、進捗表示UIを初期化する。

## 通知種別

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

## 送信仕様

### 基本情報

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

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

WorkDoneProgress機能をサポートするLSPクライアントに送信される。クライアントのcapabilitiesで有効化が必要。

## 通知テンプレート

### LSP Notification形式

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

### 本文テンプレート

```json
{
  "jsonrpc": "2.0",
  "method": "$/progress",
  "params": {
    "token": "backgroundIndexProgress",
    "value": {
      "kind": "begin",
      "title": "indexing",
      "cancellable": false,
      "percentage": 0
    }
  }
}
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| token | プログレス識別トークン | 固定値 "backgroundIndexProgress" | Yes |
| value.kind | 進捗の種類 | 固定値 "begin" | Yes |
| value.title | 処理のタイトル | 固定値 "indexing" | Yes |
| value.cancellable | キャンセル可能かどうか | false（デフォルト） | No |
| value.percentage | パーセンテージ表示の有無 | true（0で初期化） | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 内部処理 | BackgroundQueue進捗更新 | BackgroundIndexProgressState==Live && 未開始 | インデックス処理開始時 |
| 内部処理 | window/workDoneProgress/create完了 | CreateWorkDoneProgress成功後 | プログレスバー作成完了後 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| BackgroundIndexProgressState==Unsupported | クライアントがWorkDoneProgressをサポートしていない場合 |
| BackgroundIndexSkipCreate=true かつ State==Empty | 暗黙的プログレス作成がサポートされている場合は直接Report送信 |
| サーバー未初期化 | initializeリクエスト完了前は送信されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[BackgroundQueue進捗更新] --> B[onBackgroundIndexProgress コールバック]
    B --> C{State確認}
    C -->|Unsupported| D[処理終了]
    C -->|Creating| E[PendingProgressにキャッシュ]
    C -->|Empty| F{BackgroundIndexSkipCreate?}
    F -->|Yes| G[直接NotifyProgress]
    F -->|No| H[CreateWorkDoneProgress送信]
    H --> I[State=Creating]
    I --> J[Create成功コールバック]
    J --> K[BeginWorkDoneProgress送信]
    K --> L[State=Live]
    G --> K
```

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

### 参照テーブル一覧

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

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| CreateWorkDoneProgress失敗 | クライアントがプログレスバー作成を拒否 | State=Unsupportedに設定、以後通知しない |
| Transport失敗 | クライアントとの接続断 | ログ出力、再接続待機 |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし（イベント駆動） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

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

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

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

## 備考

- LSP標準メソッドの一部（$/progress）
- WorkDoneProgressBegin, WorkDoneProgressReport, WorkDoneProgressEndの3種類の通知がある
- clangdではバックグラウンドインデックス用に使用
- BackgroundIndexSkipCreate拡張により、暗黙的なプログレスバー作成をサポートするクライアント向けに最適化

---

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

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

### 推奨読解順序

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

WorkDoneProgressBegin構造体とProgressParamsの定義を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Protocol.h | `clang-tools-extra/clangd/Protocol.h` | ProgressParams<T>テンプレート定義（行655-664） |
| 1-2 | Protocol.h | `clang-tools-extra/clangd/Protocol.h` | WorkDoneProgressBegin構造体定義（行667-689） |
| 1-3 | Protocol.cpp | `clang-tools-extra/clangd/Protocol.cpp` | toJSON(WorkDoneProgressBegin)実装（行586-598） |

**読解のコツ**: ProgressParams<T>はtoken+valueのジェネリック構造。valueの型がBegin/Report/Endで異なる。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ClangdLSPServer.h | `clang-tools-extra/clangd/ClangdLSPServer.h` | BeginWorkDoneProgress通知のバインド宣言（行200-201） |
| 2-2 | ClangdLSPServer.cpp | `clang-tools-extra/clangd/ClangdLSPServer.cpp` | BeginWorkDoneProgressバインド（行1740） |
| 2-3 | ClangdLSPServer.cpp | `clang-tools-extra/clangd/ClangdLSPServer.cpp` | onBackgroundIndexProgressコールバック（行1852-1922） |

**主要処理フロー**:
1. **行1740**: `Bind.outgoingNotification("$/progress")`でバインド
2. **行1861-1867**: NotifyProgress内でBegin送信
3. **行1863-1866**: WorkDoneProgressBegin構築（percentage=true, title="indexing"）

#### Step 3: 状態管理を理解する

BackgroundIndexProgressStateの遷移を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ClangdLSPServer.h | `clang-tools-extra/clangd/ClangdLSPServer.h` | BackgroundIndexProgress enum定義（行312-323） |
| 3-2 | ClangdLSPServer.cpp | `clang-tools-extra/clangd/ClangdLSPServer.cpp` | 状態遷移ロジック（行1886-1921） |

**主要処理フロー**:
- **行1886-1888**: Unsupportedの場合は処理終了
- **行1893-1900**: Emptyの場合、CreateWorkDoneProgress送信またはSkipCreate
- **行1918-1919**: Liveの場合、NotifyProgress実行

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

```
BackgroundQueue (インデックス処理)
    │
    └─ ClangdServer::Callbacks::onBackgroundIndexProgress()
           │
           └─ ClangdLSPServer::onBackgroundIndexProgress()
                  │
                  ├─ [State管理]
                  │      ├─ Unsupported → 処理終了
                  │      ├─ Creating → キャッシュ
                  │      ├─ Empty → CreateWorkDoneProgress or NotifyProgress
                  │      └─ Live → NotifyProgress
                  │
                  └─ NotifyProgress()
                         ├─ [State != Live] BeginWorkDoneProgress送信
                         │      └─ State = Live
                         └─ [State == Live] ReportWorkDoneProgress送信
```

### データフロー図

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

BackgroundQueue::Stats ───▶ State確認 ───▶ ProgressParams<WorkDoneProgressBegin>
    │                           │                        │
    │                           ▼                        ▼
    │               WorkDoneProgressBegin構築         toJSON()
    │               title = "indexing"                   │
    │               percentage = true                    ▼
    │               cancellable = false          JSON-RPC通知
    │                                                    │
    └──────────────────────────────────────▶ "$/progress"
                                                         │
                                                         ▼
                                                   [LSPクライアント]
                                                   プログレスバー表示開始
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Protocol.h | `clang-tools-extra/clangd/Protocol.h` | ヘッダ | WorkDoneProgressBegin, ProgressParams定義 |
| Protocol.cpp | `clang-tools-extra/clangd/Protocol.cpp` | ソース | JSON変換実装 |
| ClangdLSPServer.h | `clang-tools-extra/clangd/ClangdLSPServer.h` | ヘッダ | BeginWorkDoneProgress通知宣言、状態enum定義 |
| 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` | ヘッダ | 通信層インターフェース |
