# 通知設計書 1-textDocument/didOpen

## 概要

本ドキュメントは、LSP(Language Server Protocol)におけるtextDocument/didOpen通知の設計仕様を記載する。クライアントからサーバーへ送信される通知であり、テキストドキュメントが開かれたことをサーバーに通知する。

### 本通知の処理概要

textDocument/didOpen通知は、エディタやIDEでClojure/ClojureScriptファイルが開かれた際に、クライアントからclojure-lspサーバーへ送信される通知である。この通知を受信すると、サーバーはドキュメントの内容を内部状態に登録し、即座に静的解析を実行して診断情報(エラー、警告等)を生成する。

**業務上の目的・背景**：エディタでファイルを開いた瞬間から、コード補完、定義ジャンプ、リファクタリングなどの言語機能を提供するために、サーバーはドキュメントの内容を把握する必要がある。この通知により、サーバーはドキュメントの同期状態を管理し、リアルタイムでコード解析を行える状態となる。

**通知の送信タイミング**：ユーザーがエディタでClojure/ClojureScript/EDNファイルを開いた直後に、エディタ(LSPクライアント)がこの通知を自動的に送信する。ファイルを開くたびに1回送信される。

**通知の受信者**：clojure-lspサーバープロセスがこの通知を受信する。サーバーは単一プロセスとして動作し、接続されたクライアントからの通知を処理する。

**通知内容の概要**：通知には、開かれたドキュメントのURI、言語識別子(clojure等)、バージョン番号(初期値0)、およびドキュメントの全テキスト内容が含まれる。

**期待されるアクション**：サーバーは受信後、ドキュメントをメモリに登録し、clj-kondoによる静的解析を実行する。解析結果として検出された問題(未解決シンボル、構文エラー等)は、textDocument/publishDiagnostics通知としてクライアントへ返送される。また、新規ファイルの場合は自動的に名前空間宣言を追加する機能も提供する。

## 通知種別

LSP通知 (クライアント → サーバー)

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期(通知受信後即座に処理開始) |
| 優先度 | 高(ドキュメント同期の起点) |
| リトライ | なし(通知のため応答なし) |

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

クライアントからサーバーへの一方向通知のため、送信先決定ロジックは不要。

## 通知テンプレート

### パラメータ構造

| 項目 | 内容 |
|-----|------|
| メソッド名 | textDocument/didOpen |
| パラメータ型 | DidOpenTextDocumentParams |
| プロトコル | JSON-RPC 2.0 over stdio |

### パラメータ定義

```json
{
  "textDocument": {
    "uri": "file:///path/to/file.clj",
    "languageId": "clojure",
    "version": 0,
    "text": "(ns example.core)\n\n(defn hello [name]\n  (str \"Hello, \" name))"
  }
}
```

### 添付ファイル

該当なし(LSP通知にファイル添付機能なし)

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| textDocument.uri | ドキュメントのURI | クライアント(エディタ) | Yes |
| textDocument.languageId | 言語識別子 | クライアント(エディタ) | Yes |
| textDocument.version | ドキュメントバージョン | クライアント(初期値0) | Yes |
| textDocument.text | ドキュメント全文 | クライアント(ファイル内容) | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | ファイルを開く | ファイル拡張子が.clj/.cljs/.cljc/.cljd/.edn/.bb/.clj_kondo | ユーザーがエディタでファイルを開いた時 |
| API | LSPクライアント初期化後 | サーバーとの接続確立済み | クライアントがサーバーに接続している状態 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| サーバー未接続 | LSPサーバーが起動していない/接続されていない場合 |
| 非対象ファイル | 対象外の拡張子(Clojure以外)のファイル |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ファイルを開く] --> B[textDocument/didOpen通知送信]
    B --> C[サーバーで受信]
    C --> D[URIを正規化]
    D --> E[ドキュメントをDBに登録]
    E --> F[clj-kondo解析実行]
    F --> G[clj-depend解析実行]
    G --> H[組み込み診断解析]
    H --> I[カスタム診断解析]
    I --> J[診断情報公開]
    J --> K{空ファイルか?}
    K -->|Yes| L[名前空間自動追加]
    K -->|No| M[テストツリー更新]
    L --> M
    M --> N[終了]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| db/documents | 既存ドキュメント情報の参照 | アトムで管理される状態 |
| db/analysis | 解析結果の参照 | clj-kondoの解析結果 |
| db/settings | 設定情報の参照 | auto-add-ns-to-new-files?等 |

### テーブル別参照項目詳細

#### db/documents

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| [uri :v] | バージョン番号 | キー: uri |
| [uri :text] | ドキュメントテキスト | キー: uri |
| [uri :saved-on-disk] | ディスク保存状態 | キー: uri |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| db/documents | INSERT/UPDATE | ドキュメント情報の登録・更新 |
| db/analysis | UPDATE | 解析結果の更新 |
| db/diagnostics | UPDATE | 診断情報の更新 |

#### db/documents更新詳細

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| ASSOC | [:documents uri :v] | 0 | 初期バージョン |
| ASSOC | [:documents uri :text] | テキスト内容 | ドキュメント全文 |
| ASSOC | [:documents uri :saved-on-disk] | false | 新規オープン時はfalse |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| clj-kondo解析エラー | 不正な構文のClojureコード | エラーを診断情報として公開 |
| URI解決エラー | 無効なファイルパス | ログ出力して処理継続 |
| メモリ不足 | 大規模ファイル | JVMヒープ設定で対応 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0(通知のためリトライなし) |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし |
| 1日あたり上限 | なし |

### 配信時間帯

制限なし(常時処理可能)

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

- ファイルパス(URI)はユーザーのローカルファイルシステム上のパスを含む
- ドキュメント内容はメモリ上に保持され、ログには記録されない
- 外部依存ライブラリのソースコード解析時もローカルキャッシュを使用

## 備考

- LSP仕様: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_didOpen
- この通知は応答を返さない(notification)
- ドキュメント同期モードはサーバー初期化時に設定される

---

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

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

### 推奨読解順序

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

まず、プログラム間で受け渡されるデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | db.clj | `lib/src/clojure_lsp/db.clj` | initial-db定義、:documents構造 |
| 1-2 | coercer.clj | `lib/src/lsp4clj/coercer.clj` | LSPパラメータのspec定義 |

**読解のコツ**: Clojureのatomとmapの入れ子構造を理解すること。`:documents`は`{uri {:v version :text text}}`の形式。

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

処理の起点となるファイル・関数を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | server.clj | `cli/src/clojure_lsp/server.clj` | receive-notification multimethod定義 |

**主要処理フロー**:
1. **254-255行目**: `textDocument/didOpen`メソッドのdefmethod定義
2. **255行目**: `handler/did-open`への委譲、URI正規化処理

#### Step 3: ハンドラー層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | handlers.clj | `lib/src/clojure_lsp/handlers.clj` | did-open関数の定義 |

**主要処理フロー**:
- **224-231行目**: did-open関数本体
- **227-228行目**: URIとtextの取得
- **229行目**: f.file-management/did-openへの委譲
- **230行目**: テストツリーのリフレッシュ

#### Step 4: ファイル管理機能層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | file_management.clj | `lib/src/clojure_lsp/feature/file_management.clj` | did-open関数の実装 |

**主要処理フロー**:
- **37-38行目**: load-document!でドキュメント登録
- **40-61行目**: did-open関数本体
- **42-43行目**: clj-kondoとclj-dependの並列解析
- **46-51行目**: 解析結果のDB更新
- **52行目**: 診断情報の公開
- **53-55行目**: 新規ファイルへの名前空間自動追加

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

```
jsonrpc.server/receive-notification "textDocument/didOpen"
    |
    +-- server.clj (254-255行目)
           |
           +-- handler/did-open (handlers.clj 224-231行目)
                  |
                  +-- f.file-management/did-open (file_management.clj 40-61行目)
                  |      |
                  |      +-- load-document! (37-38行目)
                  |      +-- lsp.kondo/run-kondo-on-text! (42行目)
                  |      +-- lsp.depend/analyze-uri! (43行目)
                  |      +-- f.diagnostic/publish-diagnostics! (52行目)
                  |      +-- create-ns-changes (53-55行目)
                  |
                  +-- producer/refresh-test-tree (230行目)
```

### データフロー図

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

DidOpenTextDocumentParams
    |
    +-- uri --------+
    |               |
    +-- text -------+---> normalize-doc-uri
                    |            |
                    |            v
                    +---> load-document! -----> db* [:documents uri]
                    |            |
                    |            v
                    +---> run-kondo-on-text! -> db* [:analysis uri]
                    |            |
                    |            v
                    +---> publish-diagnostics! -> textDocument/publishDiagnostics
                                 |
                                 v
                    +---> refresh-test-tree -> clojure/textDocument/testTree
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| server.clj | `cli/src/clojure_lsp/server.clj` | ソース | LSPサーバーのエントリーポイント、通知受信 |
| handlers.clj | `lib/src/clojure_lsp/handlers.clj` | ソース | 各種LSPメッセージのハンドラー |
| file_management.clj | `lib/src/clojure_lsp/feature/file_management.clj` | ソース | ファイル管理機能の実装 |
| db.clj | `lib/src/clojure_lsp/db.clj` | ソース | データベース(アトム)の定義 |
| kondo.clj | `lib/src/clojure_lsp/kondo.clj` | ソース | clj-kondo連携 |
| diagnostics.clj | `lib/src/clojure_lsp/feature/diagnostics.clj` | ソース | 診断情報の公開 |
| producer.clj | `lib/src/clojure_lsp/producer.clj` | ソース | サーバーからクライアントへの通知送信 |
| fixture.clj | `cli/integration-test/integration/fixture.clj` | テスト | 統合テスト用フィクスチャ |
