# 通知設計書 9-workspace/didChangeWatchedFiles

## 概要

本ドキュメントは、LSPクライアントからserve-dサーバーへ送信される `workspace/didChangeWatchedFiles` 通知の設計を記述する。この通知はLSP標準仕様に準拠し、監視対象ファイルの変更をサーバーに通知するために使用される。

### 本通知の処理概要

`workspace/didChangeWatchedFiles` 通知は、クライアントが監視しているファイルの作成・変更・削除を検出した際にserve-dサーバーに送信される通知である。サーバー側では2つのハンドラが登録されている。rename_listener.dのmarkRecentlyChangedFileではファイル作成の検知（リネーム・新規作成の追跡）を行い、profilegc.dのonChangeProfileGCではprofilegc.logファイルの変更検知を行う。

**業務上の目的・背景**：エディタ外でのファイル変更やファイルシステムイベントを検知するために、LSPクライアントがファイルウォッチャーを設定し、変更をサーバーに通知する。serve-dでは、新規ファイル作成の検知（モジュール名の自動挿入のため）と、profilegc.logファイルの変更検知（GCプロファイリング結果のCodeLens表示のため）に使用される。

**通知の送信タイミング**：クライアントがファイルウォッチャーに登録されたパターンに一致するファイルの変更を検知したときに送信される。動的に登録されたファイルウォッチャー（profilegc.logの監視）も対象。

**通知の受信者**：serve-d LSPサーバーが受信する。

**通知内容の概要**：ファイル変更イベントの配列（URI + 変更タイプ: created/changed/deleted）で構成される。

**期待されるアクション**：サーバーがファイル変更に応じた処理を実行する（ファイル作成の追跡、profilegc.logの解析更新）。

## 通知種別

LSP標準通知（クライアント -> サーバー）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（JSON-RPC通知） |
| 優先度 | 中 |
| リトライ | 無し |

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

クライアントがファイルウォッチャーで変更を検知した際に自動的にserve-dサーバーへ送信される。

## 通知テンプレート

### LSP通知の場合

| 項目 | 内容 |
|-----|------|
| メソッド名 | `workspace/didChangeWatchedFiles` |
| パラメータ型 | `DidChangeWatchedFilesParams` |
| 形式 | JSON-RPC 2.0 通知 |

### 本文テンプレート

```json
{
  "jsonrpc": "2.0",
  "method": "workspace/didChangeWatchedFiles",
  "params": {
    "changes": [
      {
        "uri": "file:///path/to/file.d",
        "type": 1
      }
    ]
  }
}
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| changes | ファイル変更イベントの配列 | クライアントのファイルウォッチャー | Yes |
| changes[].uri | 変更されたファイルのURI | ファイルシステム | Yes |
| changes[].type | 変更タイプ（1=created, 2=changed, 3=deleted） | ファイルシステムイベント | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ファイルシステム | ファイルの作成 | ウォッチャー登録済みパターンに一致 | type=1(created) |
| ファイルシステム | ファイルの変更 | ウォッチャー登録済みパターンに一致 | type=2(changed) |
| ファイルシステム | ファイルの削除 | ウォッチャー登録済みパターンに一致 | type=3(deleted) |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| ファイルウォッチャー未登録 | クライアントがdidChangeWatchedFilesの動的登録に対応していない場合 |

## 処理フロー

### 受信フロー

```mermaid
flowchart TD
    A[workspace/didChangeWatchedFiles通知受信] --> B[ハンドラ1: markRecentlyChangedFile]
    A --> C[ハンドラ2: onChangeProfileGC]
    B --> D{type == created?}
    D -->|Yes| E[markRecentFileCreated]
    D -->|No| F[スキップ]
    E --> G[RecentFilesに追跡記録]
    G --> H{created + opened?}
    H -->|Yes| I[onFullyCreate実行]
    H -->|No| J[待機]
    C --> K{URI末尾がprofilegc.log?}
    K -->|No| L[スキップ]
    K -->|Yes| M{type判定}
    M -->|created/changed| N[profileGCCache.update]
    M -->|deleted| O[profileGCCache.clear]
```

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

該当なし（インメモリ管理）

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| RecentFiles.infos | UPDATE | ファイル作成イベントの追跡（最大8ファイル） |
| ProfileGCCache.caches | UPDATE/DELETE | profilegc.logの解析結果キャッシュ |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| profilegc.log読み込みエラー | ファイルが存在しないまたは読み込み不可 | FileExceptionをキャッチしキャッシュをクリア |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0 |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし |

## 配信設定

### レート制限

該当なし

### 配信時間帯

制限なし

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

ファイルURIが送信される。ファイルパスの情報が含まれるが、セキュリティリスクは低い。

## 備考

- profilegc.logの監視は動的ケーパビリティ登録（client/registerCapability）で設定される。setupProfileGCWatchers()がonRegisteredComponentsイベントで呼び出される
- 監視パターンは `**/profilegc.log`
- ファイル作成の追跡はRecentFiles構造体（最大8ファイル、5秒タイムアウト）で管理され、didOpen通知との組み合わせで新規ファイル作成を検出する
- onFullyCreate()はD言語ファイルの場合にモジュール名を自動生成し、dub.json/dub.sdlの場合にテンプレートを挿入する

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | protocol.d | `lsp/source/served/lsp/protocol.d` | DidChangeWatchedFilesParams、FileEvent、FileChangeType列挙値の定義 |
| 1-2 | rename_listener.d | `source/served/workers/rename_listener.d` | FileOpenInfo構造体（17行目〜47行目）、RecentFiles構造体（50行目〜91行目） |
| 1-3 | profilegc.d | `source/served/workers/profilegc.d` | ProfileGCCache構造体（24行目〜95行目） |

#### Step 2: ハンドラ1を理解する - ファイル作成追跡

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | rename_listener.d | `source/served/workers/rename_listener.d` | markRecentlyChangedFile（95行目〜101行目）。type==createdのイベントのみ処理し、markRecentFileCreated()を呼び出す |
| 2-2 | rename_listener.d | `source/served/workers/rename_listener.d` | onFullyCreate（116行目〜127行目）。D言語ファイル / dub.json / dub.sdlに応じた処理分岐 |

**主要処理フロー**:
1. **98行目〜100行目**: changesをイテレートし、type==createdのものだけmarkRecentFileCreated
2. **103行目〜106行目**: RecentFilesに記録し、setCreated()を呼び出す
3. **116行目〜127行目**: created+openedが揃った場合にonFullyCreate実行

#### Step 3: ハンドラ2を理解する - profilegc.log監視

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | profilegc.d | `source/served/workers/profilegc.d` | onChangeProfileGC（158行目〜172行目）。profilegc.logのURI判定とtype別の処理 |
| 3-2 | profilegc.d | `source/served/workers/profilegc.d` | setupProfileGCWatchers（131行目〜150行目）。動的ケーパビリティ登録 |

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

```
[クライアント: workspace/didChangeWatchedFiles送信]
    |
    v
[serverbase.d: processNotify]
    |
    +-- markRecentlyChangedFile(params)             [rename_listener.d:95]
    |       +-- markRecentFileCreated(uri)           (created only)
    |               +-- recentFiles.get(uri).setCreated()
    |               +-- onFullyCreate(uri)           (if opened)
    |                       +-- onFullyCreateDSource(uri)
    |                       +-- onFullyCreateDubJson(uri)
    |                       +-- onFullyCreateDubSdl(uri)
    |
    +-- onChangeProfileGC(params)                    [profilegc.d:158]
            +-- profileGCCache.update(uri)           (created/changed)
            +-- profileGCCache.clear(uri)            (deleted)
```

### データフロー図

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

DidChangeWatchedFilesParams    -->  markRecentlyChangedFile()    -->  RecentFiles更新
  changes[].uri                -->  onFullyCreate()              -->  workspace/applyEdit送信
  changes[].type               -->  onChangeProfileGC()          -->  ProfileGCCache更新
                                                                      CodeLens情報更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| rename_listener.d | `source/served/workers/rename_listener.d` | ソース | ファイル作成追跡ハンドラ |
| profilegc.d | `source/served/workers/profilegc.d` | ソース | profilegc.log変更検知ハンドラ |
| protocol.d | `lsp/source/served/lsp/protocol.d` | ソース | DidChangeWatchedFilesParams等のLSPプロトコル型定義 |
| serverbase.d | `serverbase/source/served/serverbase.d` | ソース | processNotify |
