# 機能設計書 65-ファイル変更監視

## 概要

本ドキュメントは、Clojure LSPにおけるファイル変更監視機能（workspace/didChangeWatchedFiles）の設計を定義する。この機能は、ファイルシステム上のファイル変更（作成、変更、削除）を検知し、解析を更新する。

### 本機能の処理概要

**業務上の目的・背景**：開発者がエディタ外でファイルを変更した場合（例：gitでブランチを切り替え、外部ツールでコード生成）、LSPサーバーは自動的にその変更を検知し、解析データを更新する必要がある。この機能は、エディタのファイル監視機能と連携して、プロジェクト全体の解析状態を常に最新に保つ。

**機能の利用シーン**：
- gitでブランチを切り替えた際に、変更されたファイルの解析を更新
- 外部ツール（lein、cljなど）でファイルが生成/変更された場合に解析を更新
- ファイルが削除された場合に解析データをクリーンアップ

**主要な処理内容**：
1. ファイル変更通知を受信し、変更タイプ（created/changed/deleted）ごとに分類
2. 作成・変更されたファイルは非同期で解析キューに追加
3. 削除されたファイルは解析データとドキュメント情報を即座にクリーンアップ
4. 依存関係のあるファイルにも通知を伝播

**関連システム・外部連携**：LSPクライアント（エディタ）がファイル監視を行い、変更を通知する。clj-kondoで再解析を実行する。

**権限による制御**：特に権限制御は存在しない。全ファイルが監視対象となる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 該当なし | 該当なし | 該当なし | 本機能はLSPプロトコルを通じてエディタから呼び出される |

## 機能種別

イベント処理 / 非同期処理 / 解析更新

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| changes | array | Yes | ファイル変更リスト | 各要素は {uri, type} 形式 |
| changes[].uri | string | Yes | 変更されたファイルのURI | 有効なファイルURI |
| changes[].type | enum | Yes | 変更タイプ | created, changed, deleted のいずれか |

### 入力データソース

- LSPクライアントからの workspace/didChangeWatchedFiles 通知

## 出力仕様

### 出力データ

本機能は通知（notification）であり、直接の戻り値はない。
副作用として以下が発生する：

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 解析更新 | - | 変更されたファイルの再解析 |
| 診断更新 | - | 診断情報の再発行 |
| テストツリー更新 | - | テストツリーのリフレッシュ |

### 出力先

- 内部DB（解析結果）
- LSPクライアント（診断情報、テストツリー）

## 処理フロー

### 処理シーケンス

```
1. LSPクライアントから workspace/didChangeWatchedFiles 通知を受信
   └─ handlers.clj の did-change-watched-files ハンドラが呼び出される
2. 変更タイプごとにファイルを分類
   └─ created, changed, deleted にグループ化
3. 作成/変更されたファイルを非同期キューに追加
   └─ watched-files-chan に送信
4. 削除されたファイルを同期処理
   └─ 解析データ、ドキュメント情報、診断をクリーンアップ
5. 非同期ワーカーが解析を実行
   └─ analyze-watched-files! で clj-kondo 解析
6. 診断情報とテストツリーを更新
   └─ publish-all-diagnostics!, refresh-test-tree
```

### フローチャート

```mermaid
flowchart TD
    A[didChangeWatchedFiles 通知受信] --> B[変更タイプで分類]
    B --> C{created/changed?}
    C -->|Yes| D[watched-files-chan に送信]
    B --> E{deleted?}
    E -->|Yes| F[files-deleted 処理]
    F --> G[解析データ削除]
    G --> H[空の診断を発行]
    H --> I[依存ファイルに通知]
    D --> J[非同期ワーカー]
    J --> K[analyze-watched-files!]
    K --> L[診断・テストツリー更新]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 変更監視設定 | compute-external-file-changes 設定で変更ファイルの監視可否を制御 | changed タイプ |
| BR-02 | 無視パターン | source-paths-ignore-regex で特定パスを無視 | 常時 |
| BR-03 | ディレクトリ展開 | ディレクトリURIは内部のファイルに展開 | 常時 |
| BR-04 | デバウンス | 連続する変更をまとめて処理（1000ms） | 常時 |

### 計算ロジック

**無視パターンマッチング**:
```clojure
(some #(re-matches (re-pattern %) relative-source-path) source-paths-ignore-regexs)
```

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 解析削除 | db[:analysis][uri] | DELETE | 削除されたファイルの解析データを削除 |
| ドキュメント削除 | db[:documents][uri] | DELETE | 削除されたファイルのドキュメント情報を削除 |
| 診断削除 | db[:diagnostics][:clj-kondo][uri] | DELETE | 削除されたファイルの診断情報を削除 |
| 依存グラフ更新 | db[:dep-graph] | UPDATE | ファイル削除に伴う依存関係の更新 |

### テーブル別操作詳細

#### db-without-uri 関数による削除

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | dep-graph | uri = 指定URI | dep-graph/remove-doc |
| DELETE | documents | uri = 指定URI | dissoc-in |
| DELETE | analysis | uri = 指定URI | dissoc-in |
| DELETE | diagnostics:clj-kondo | uri = 指定URI | dissoc-in |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 無視 | ファイルが存在しない（既に削除済み） | スキップして続行 |
| - | ログ出力 | 解析中にエラー発生 | エラーログ出力後続行 |

### リトライ仕様

リトライは実装されていない。非同期キューによる遅延処理で対応。

## トランザクション仕様

- ファイル削除時のDB更新はアトミック（swap!）
- 非同期解析は別スレッドで実行

## パフォーマンス要件

- デバウンスにより1000ms以内の連続変更をまとめて処理
- 大量ファイルの変更でもUIをブロックしない（非同期処理）

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

- 監視対象はプロジェクト内のファイルに限定される（グロブパターン）

## 備考

- LSPプロトコル仕様: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_didChangeWatchedFiles
- 監視対象パターン: `**/*.{clj,cljs,cljc,cljd,edn,bb,clj_kondo}`

---

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

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

### 推奨読解順序

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

変更通知のデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | server.clj | `cli/src/clojure_lsp/server.clj` | known-files-pattern 定数（46行目） |

**読解のコツ**: 変更通知は {:uri string :type keyword} の形式。type は :created, :changed, :deleted のいずれか。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | server.clj | `cli/src/clojure_lsp/server.clj` | workspace/didChangeWatchedFiles ハンドラ（458-465行目） |
| 2-2 | handlers.clj | `lib/src/clojure_lsp/handlers.clj` | did-change-watched-files ハンドラ（251-252行目） |

**主要処理フロー**:
1. **458-465行目（server.clj）**: URI正規化とハンドラ委譲
2. **251-252行目（handlers.clj）**: file-management関数に委譲

#### Step 3: コア機能を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | file_management.clj | `lib/src/clojure_lsp/feature/file_management.clj` | did-change-watched-files（342-358行目） |
| 3-2 | file_management.clj | `lib/src/clojure_lsp/feature/file_management.clj` | files-deleted（319-323行目） |
| 3-3 | file_management.clj | `lib/src/clojure_lsp/feature/file_management.clj` | analyze-watched-files!（293-310行目） |
| 3-4 | file_management.clj | `lib/src/clojure_lsp/feature/file_management.clj` | db-without-uri（312-317行目） |

**主要処理フロー**:
- **342-358行目**: did-change-watched-files
  - compute-external-file-changes 設定を確認
  - 変更タイプでグループ化
  - created/changed は watched-files-chan に送信
  - deleted は files-deleted を同期実行
- **319-323行目**: files-deleted
  - db-without-uri で各URIを削除
  - 空の診断を発行
  - 依存ファイルに通知
- **293-310行目**: analyze-watched-files!
  - 存在するファイルのみフィルタリング
  - clj-kondo で再解析
  - 診断・テストツリー更新

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

```
server.clj (workspace/didChangeWatchedFiles 通知受信)
    │
    └─ handlers.clj::did-change-watched-files
           │
           └─ file_management.clj::did-change-watched-files
                  │
                  ├─ group-by :type (分類)
                  │
                  ├─ watched-files-chan (created/changed)
                  │      │
                  │      └─ [非同期] analyze-watched-files!
                  │              │
                  │              ├─ kondo.clj::run-kondo-on-paths!
                  │              │
                  │              ├─ diagnostics.clj::publish-all-diagnostics!
                  │              │
                  │              └─ producer::refresh-test-tree
                  │
                  └─ files-deleted (deleted)
                         │
                         ├─ db-without-uri
                         │      │
                         │      └─ dep-graph/remove-doc
                         │
                         ├─ publish-empty-diagnostics!
                         │
                         └─ notify-references
```

### データフロー図

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

FileChangeEvent[]  ───▶  did-change-watched-files
                               │
                               ▼
                         group-by :type
                               │
              ┌────────────────┼────────────────┐
              ▼                ▼                ▼
         :created          :changed         :deleted
              │                │                │
              ▼                ▼                ▼
         watched-files-chan    │           files-deleted
              │                │                │
              ▼                ▼                ▼
         [debounce 1000ms]                 db-without-uri
              │                                 │
              ▼                                 ▼
         analyze-watched-files!            空診断発行
              │                                 │
              ▼                                 ▼
         kondo 再解析                     notify-references
              │
              ▼
         診断・テストツリー更新  ───▶  LSPクライアント
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| file_management.clj | `lib/src/clojure_lsp/feature/file_management.clj` | ソース | ファイル変更処理のコアロジック |
| handlers.clj | `lib/src/clojure_lsp/handlers.clj` | ソース | LSPリクエストハンドラ |
| server.clj | `cli/src/clojure_lsp/server.clj` | ソース | LSPサーバーエントリーポイント |
| kondo.clj | `lib/src/clojure_lsp/kondo.clj` | ソース | clj-kondo解析実行 |
| dep_graph.clj | `lib/src/clojure_lsp/dep_graph.clj` | ソース | 依存グラフ管理 |
| file_management_test.clj | `lib/test/clojure_lsp/feature/file_management_test.clj` | テスト | ユニットテスト |
