# 通知設計書 4-PublishInactiveRegions

## 概要

本ドキュメントは、clangdが実装するclangd拡張メソッド `textDocument/inactiveRegions` の通知仕様を定義する。この通知は、プリプロセッサによる非アクティブ領域（#if 0などで無効化されたコード領域）をクライアントに通知するために使用されるclangd独自の拡張機能である。

### 本通知の処理概要

PublishInactiveRegions通知は、C/C++プリプロセッサの条件コンパイルディレクティブ（#if, #ifdef, #ifndef等）によって無効化されたコード領域をエディタに伝え、視覚的に区別できるようにする機能である。

**業務上の目的・背景**：C/C++開発では、プラットフォーム固有のコードや機能フラグによる条件コンパイルが頻繁に使用される。開発者にとって、現在のビルド設定でどのコードが有効/無効かを即座に把握できることは重要である。非アクティブ領域のグレーアウト表示により、コードの可読性と理解度が向上し、誤って無効なコードを編集するリスクを軽減できる。

**通知の送信タイミング**：AST構築後、セマンティック解析が完了したタイミングで送信される。ドキュメントが開かれたとき、内容が変更されたとき、またはビルド設定が変更されたときに更新される。`onInactiveRegionsReady`コールバックで処理される。

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

**通知内容の概要**：対象ドキュメントのURIと、非アクティブ領域の範囲（Range）のリストが含まれる。各Rangeは開始行/文字と終了行/文字を指定する。

**期待されるアクション**：クライアントは受信した領域をグレーアウトや薄い色で表示し、アクティブなコードと視覚的に区別する。これにより開発者は現在有効なコードを一目で識別できる。

## 通知種別

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

## 送信仕様

### 基本情報

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

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

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

## 通知テンプレート

### LSP Notification形式

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

### 本文テンプレート

```json
{
  "jsonrpc": "2.0",
  "method": "textDocument/inactiveRegions",
  "params": {
    "textDocument": {
      "uri": "file:///path/to/source.cpp"
    },
    "regions": [
      {
        "start": { "line": 10, "character": 0 },
        "end": { "line": 20, "character": 0 }
      },
      {
        "start": { "line": 50, "character": 0 },
        "end": { "line": 55, "character": 0 }
      }
    ]
  }
}
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| textDocument | 対象ドキュメント識別子 | TextDocumentIdentifier | Yes |
| textDocument.uri | 対象ドキュメントのURI | URIForFile::canonicalize() | Yes |
| regions | 非アクティブ領域の配列 | std::vector<Range> | Yes |
| regions[].start | 領域の開始位置 | Position | Yes |
| regions[].end | 領域の終了位置 | Position | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | textDocument/didOpen | Caps.InactiveRegions=true | 新規ドキュメントの初期解析後 |
| 画面操作 | textDocument/didChange | Caps.InactiveRegions=true | ドキュメント変更後の再解析後 |
| 内部処理 | セマンティック解析完了 | Caps.InactiveRegions=true | バックグラウンドでの解析完了時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| Caps.InactiveRegions=false | クライアントがInactiveRegions拡張をサポートしていない場合 |
| PublishInactiveRegionsがnull | バインドされていない場合（条件付きバインド） |
| サーバー未初期化 | initializeリクエスト完了前は送信されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ドキュメント変更] --> B[セマンティック解析]
    B --> C[非アクティブ領域検出]
    C --> D[onInactiveRegionsReady コールバック]
    D --> E{Caps.InactiveRegions?}
    E -->|No| F[処理終了]
    E -->|Yes| G[InactiveRegionsParams構築]
    G --> H[PublishInactiveRegions送信]
    H --> I[クライアントでグレーアウト表示]
```

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

### 参照テーブル一覧

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

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

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

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

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

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

- ファイルパスがURIとして送信されるため、ローカルファイルシステム構造が露出する
- コード構造の一部（非アクティブ領域の位置）が送信される
- LSP通信はローカルプロセス間通信が基本であり、外部ネットワークへの送信は想定していない

## 備考

- clangd独自の拡張機能であり、LSP標準には含まれない
- サーバーcapabilitiesで「inactiveRegionsProvider: true」としてアドバタイズ
- 非アクティブ領域の検出はClangのプリプロセッサ解析に基づく
- VSCode等のエディタでは、非アクティブ領域はグレーアウト表示される

---

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

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

### 推奨読解順序

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

InactiveRegionsParams構造体の定義を確認。

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

**読解のコツ**: TextDocumentとInactiveRegions（Range配列）の2フィールドで構成される。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ClangdLSPServer.h | `clang-tools-extra/clangd/ClangdLSPServer.h` | PublishInactiveRegions通知のバインド宣言（行197） |
| 2-2 | ClangdLSPServer.cpp | `clang-tools-extra/clangd/ClangdLSPServer.cpp` | PublishInactiveRegionsバインド（行1735-1736） |
| 2-3 | ClangdLSPServer.cpp | `clang-tools-extra/clangd/ClangdLSPServer.cpp` | onInactiveRegionsReadyコールバック（行1843-1850） |

**主要処理フロー**:
1. **行1735-1736**: 条件付きバインド `if (Caps.InactiveRegions)`
2. **行1843**: `onInactiveRegionsReady`コールバック開始
3. **行1845-1847**: InactiveRegionsParams構築
4. **行1849**: `PublishInactiveRegions(Notification)`で送信

#### Step 3: 有効化条件を理解する

InactiveRegions機能の有効化フローを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Protocol.h | `clang-tools-extra/clangd/Protocol.h` | ClientCapabilities::InactiveRegions（行567-570） |
| 3-2 | ClangdLSPServer.cpp | `clang-tools-extra/clangd/ClangdLSPServer.cpp` | onInitializeでのOpts.PublishInactiveRegions設定（行550） |
| 3-3 | ClangdLSPServer.cpp | `clang-tools-extra/clangd/ClangdLSPServer.cpp` | ServerCaps設定（行650） |

**主要処理フロー**:
- **行550**: `Opts.PublishInactiveRegions = Params.capabilities.InactiveRegions`
- **行650**: サーバーcapabilitiesで`"inactiveRegionsProvider", true`を設定

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

```
ClangdServer (セマンティック解析)
    │
    └─ ClangdServer::Callbacks::onInactiveRegionsReady()
           │
           └─ ClangdLSPServer::onInactiveRegionsReady()
                  │
                  ├─ InactiveRegionsParams構築
                  │      ├─ TextDocument設定
                  │      └─ InactiveRegions設定
                  │
                  └─ PublishInactiveRegions() [条件付きバインド]
                         └─ ClangdLSPServer::notify()
                                └─ Transport::notify()
```

### データフロー図

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

std::vector<Range> ───▶ InactiveRegionsParams構築 ───▶ InactiveRegionsParams
(非アクティブ領域)               │                        │
    │                           ▼                        ▼
    │               TextDocument = URI設定            toJSON()
    │               InactiveRegions = Range配列          │
    │                                                    ▼
    └──────────────────────────────────────▶ JSON-RPC通知
                                                         │
                                                         ▼
                                                   [LSPクライアント]
                                                   グレーアウト表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Protocol.h | `clang-tools-extra/clangd/Protocol.h` | ヘッダ | InactiveRegionsParams, ClientCapabilities定義 |
| Protocol.cpp | `clang-tools-extra/clangd/Protocol.cpp` | ソース | JSON変換実装 |
| ClangdLSPServer.h | `clang-tools-extra/clangd/ClangdLSPServer.h` | ヘッダ | PublishInactiveRegions通知宣言 |
| ClangdLSPServer.cpp | `clang-tools-extra/clangd/ClangdLSPServer.cpp` | ソース | InactiveRegions送信ロジック |
| SemanticHighlighting.h | `clang-tools-extra/clangd/SemanticHighlighting.h` | ヘッダ | セマンティック解析関連 |
| SemanticHighlighting.cpp | `clang-tools-extra/clangd/SemanticHighlighting.cpp` | ソース | 非アクティブ領域検出 |
| LSPBinder.h | `clang-tools-extra/clangd/LSPBinder.h` | ヘッダ | LSPメソッドバインディング |
| Transport.h | `clang-tools-extra/clangd/Transport.h` | ヘッダ | 通信層インターフェース |
