# 機能設計書 24-ドキュメント状態管理

## 概要

本ドキュメントは、F# Language Serverにおけるドキュメント状態管理機能の設計を記述する。この機能は、LSPクライアントからのドキュメント更新を管理し、FSharpWorkspaceの状態を同期する。

### 本機能の処理概要

LSPプロトコルのtextDocument/didOpen、textDocument/didChange、textDocument/didCloseの各通知を処理し、エディタで開かれているドキュメントの最新状態をFSharpWorkspaceに反映する。

**業務上の目的・背景**：LSPサーバーがクライアント（エディタ）で編集中のドキュメントの正確な状態を把握するために必要な機能。ユーザーがファイルを開く、編集する、閉じるといった操作をサーバーに通知することで、コード補完や診断などの言語機能が最新のコード状態に基づいて動作できる。

**機能の利用シーン**：ユーザーがF#ファイルをエディタで開いた時、コードを編集した時、ファイルを閉じた時に自動的に呼び出される。

**主要な処理内容**：
1. didOpen通知の受信時にFSharpWorkspace.Files.Openを呼び出し
2. didChange通知の受信時にFSharpWorkspace.Files.Editを呼び出し
3. didClose通知の受信時にFSharpWorkspace.Files.Closeを呼び出し
4. ContextHolderを通じてワークスペース状態を更新

**関連システム・外部連携**：FSharpWorkspace、ContextHolder、LSPクライアント。

**権限による制御**：特になし。ドキュメント操作はすべて許可される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | エディタのドキュメントタブ | 主画面 | ファイルの開閉操作 |
| - | エディタのテキスト編集領域 | 主画面 | テキスト編集操作 |

## 機能種別

状態管理 / イベント処理

## 入力仕様

### 入力パラメータ

#### didOpen

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| TextDocument.Uri | DocumentUri | Yes | ドキュメントのURI | 有効なURI形式 |
| TextDocument.Text | string | Yes | ドキュメントの全文 | null不可 |

#### didChange

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| TextDocument.Uri | DocumentUri | Yes | ドキュメントのURI | 有効なURI形式 |
| ContentChanges[0].Text | string | Yes | 変更後の全文 | null不可 |

#### didClose

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| TextDocument.Uri | DocumentUri | Yes | ドキュメントのURI | 有効なURI形式 |

### 入力データソース

LSPクライアントからのJSON-RPC通知メッセージ。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| SemanticTokensDeltaPartialResult | SemanticTokensDeltaPartialResult | didOpen/didChangeのレスポンス（空オブジェクト） |
| Task.CompletedTask | Task | didCloseのレスポンス |

### 出力先

LSPクライアントへのレスポンス（通知に対するレスポンスのため、実質的に使用されない）。

## 処理フロー

### 処理シーケンス

```
1. LSPクライアントから通知を受信
   └─ Methods.TextDocumentDidOpen/DidChange/DidCloseName
2. FSharpRequestContextからContextHolderを取得
   └─ context.LspServices.GetRequiredService<ContextHolder>()
3. ContextHolder.UpdateWorkspaceを呼び出し
   └─ ワークスペースの状態を更新
4. FSharpWorkspace.Filesの対応メソッドを実行
   └─ Open/Edit/Close
5. レスポンスを返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始: LSP通知受信] --> B{通知の種類}
    B -->|didOpen| C[HandleRequestAsync - didOpen]
    B -->|didChange| D[HandleRequestAsync - didChange]
    B -->|didClose| E[HandleNotificationAsync - didClose]
    C --> F[ContextHolder取得]
    D --> F
    E --> F
    F --> G[UpdateWorkspace呼び出し]
    G --> H{操作の種類}
    H -->|Open| I[Files.Open]
    H -->|Edit| J[Files.Edit]
    H -->|Close| K[Files.Close]
    I --> L[レスポンス返却]
    J --> L
    K --> L
    L --> M[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | MutatesSolutionState | ドキュメント状態の変更はソリューション状態を変更する | 常時 |
| BR-02 | 全文同期 | didChangeは変更後の全文を受け取る（インクリメンタル変更は未対応） | didChange時 |
| BR-03 | ファイルライフサイクル | Open→Edit→Closeの順序で状態遷移 | 常時 |

### 計算ロジック

特になし。状態更新のみ。

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

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

該当なし。インメモリでの状態管理のみ。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ArgumentException | 無効なURIが指定された場合 | エラーをログに記録 |
| - | InvalidOperationException | 閉じていないファイルを再度開こうとした場合 | 既存状態を上書き |

### リトライ仕様

リトライは不要。同期処理で即座に完了。

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

該当なし。各操作は独立してアトミックに実行される。

## パフォーマンス要件

- 各操作は数ミリ秒以内に完了
- 大きなファイル（数万行）でも即座に応答

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

- ドキュメントの内容はメモリ上で管理
- ファイルシステムへの永続化は行わない
- 機密情報を含む可能性のあるコードは適切に破棄される

## 備考

- ContentChanges配列は現在1要素のみ対応（全文同期モード）
- 将来的にインクリメンタル変更（TextDocumentSyncKind.Incremental）への対応を検討

---

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

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

### 推奨読解順序

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

まず、DocumentStateHandlerが実装するインターフェースを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | DocumentStateHandler.fs | `src/FSharp.Compiler.LanguageServer/Handlers/DocumentStateHandler.fs` | IMethodHandler実装（12-14行目） |
| 1-2 | DocumentStateHandler.fs | `src/FSharp.Compiler.LanguageServer/Handlers/DocumentStateHandler.fs` | IRequestHandler/INotificationHandler実装（16-47行目） |

**読解のコツ**: MutatesSolutionState = trueに注目。このハンドラはソリューション状態を変更することを宣言している。

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

各LSP通知の処理エントリーポイントを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | DocumentStateHandler.fs | `src/FSharp.Compiler.LanguageServer/Handlers/DocumentStateHandler.fs` | didOpen処理（16-25行目） |
| 2-2 | DocumentStateHandler.fs | `src/FSharp.Compiler.LanguageServer/Handlers/DocumentStateHandler.fs` | didChange処理（27-36行目） |
| 2-3 | DocumentStateHandler.fs | `src/FSharp.Compiler.LanguageServer/Handlers/DocumentStateHandler.fs` | didClose処理（38-47行目） |

**主要処理フロー**:
1. **17行目**: LanguageServerEndpoint属性でLSPメソッド名を指定
2. **21行目**: ContextHolderをサービスから取得
3. **23行目**: UpdateWorkspaceでワークスペース状態を更新
4. **25行目**: 空のSemanticTokensDeltaPartialResultを返却

#### Step 3: ワークスペース更新を理解する

ContextHolderを通じたワークスペース更新の仕組みを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FSharpRequestContext.fs | `src/FSharp.Compiler.LanguageServer/Common/FSharpRequestContext.fs` | ContextHolderの定義 |
| 3-2 | DocumentStateHandler.fs | `src/FSharp.Compiler.LanguageServer/Handlers/DocumentStateHandler.fs` | UpdateWorkspaceの呼び出しパターン（23, 34, 45行目） |

**主要処理フロー**:
- **23行目**: `_.Files.Open(uri, text)`でファイルを開く
- **34行目**: `_.Files.Edit(uri, text)`でファイル内容を更新
- **45行目**: `_.Files.Close(uri)`でファイルを閉じる

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

```
DocumentStateHandler
    │
    ├─ HandleRequestAsync (DidOpenTextDocumentParams)
    │      └─ ContextHolder.UpdateWorkspace
    │             └─ FSharpWorkspace.Files.Open
    │
    ├─ HandleRequestAsync (DidChangeTextDocumentParams)
    │      └─ ContextHolder.UpdateWorkspace
    │             └─ FSharpWorkspace.Files.Edit
    │
    └─ HandleNotificationAsync (DidCloseTextDocumentParams)
           └─ ContextHolder.UpdateWorkspace
                  └─ FSharpWorkspace.Files.Close
```

### データフロー図

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

DidOpenParams ───▶ DocumentStateHandler ───▶ FSharpWorkspace
    │                      │                       │
    ├─ Uri                 ├─ ContextHolder取得    ├─ Files.Open
    └─ Text                └─ UpdateWorkspace      └─ ファイル状態更新

DidChangeParams ───▶ DocumentStateHandler ───▶ FSharpWorkspace
    │                      │                       │
    ├─ Uri                 ├─ ContextHolder取得    ├─ Files.Edit
    └─ ContentChanges      └─ UpdateWorkspace      └─ コンテンツ更新

DidCloseParams ───▶ DocumentStateHandler ───▶ FSharpWorkspace
    │                      │                       │
    └─ Uri                 ├─ ContextHolder取得    ├─ Files.Close
                           └─ UpdateWorkspace      └─ ファイル状態クリア
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| DocumentStateHandler.fs | `src/FSharp.Compiler.LanguageServer/Handlers/DocumentStateHandler.fs` | ソース | ドキュメント状態管理のメイン実装 |
| FSharpRequestContext.fs | `src/FSharp.Compiler.LanguageServer/Common/FSharpRequestContext.fs` | ソース | リクエストコンテキストとContextHolder |
| FSharpLanguageServer.fs | `src/FSharp.Compiler.LanguageServer/FSharpLanguageServer.fs` | ソース | ハンドラの登録 |
