# 機能設計書 72-FSI統合

## 概要

本ドキュメントは、Visual Studio統合におけるF# Interactive（FSI）統合機能の設計を記述する。エディタからF# Interactiveへコードを送信・実行するためのコマンドフィルタリングと、Visual StudioのUIとの連携を提供する。

### 本機能の処理概要

**業務上の目的・背景**：F# Interactiveは、F#コードを対話的に実行できるREPL（Read-Eval-Print Loop）環境であり、開発者がコードの動作を素早く検証したり、プロトタイピングを行うために広く利用される。Visual Studioとの統合により、エディタで編集中のコードを直接F# Interactiveに送信して実行できるようになり、開発ワークフローの効率が大幅に向上する。本機能は、エディタコマンドをインターセプトし、F# Interactiveパッケージと連携してコード実行を実現する。

**機能の利用シーン**：開発者がVisual Studioでf#コードを編集中に、選択したコードブロックまたは現在行をF# Interactiveウィンドウに送信して即座に実行結果を確認する場面で利用される。また、デバッグモードでの選択コード実行にも対応している。

**主要な処理内容**：
1. Visual Studioエディタへのコマンドフィルタのアタッチ
2. 「選択範囲をInteractiveで実行」コマンド（ExecuteSelectionInInteractive）の処理
3. 「行をInteractiveで実行」コマンド（ExecuteLineInInteractive）の処理
4. 「選択範囲をデバッグ実行」コマンド（DebugSelection）の処理
5. F# Interactiveパッケージの遅延ロードとHooksモジュールへのコマンド転送
6. コマンドの可用性状態（QueryStatus）の管理

**関連システム・外部連携**：Visual StudioのOLEコマンドインフラストラクチャ、F# Interactiveパッケージ（FSharp.Interactive）、IVsShellサービス、WPFテキストビューシステムと連携する。

**権限による制御**：デバッグ選択実行コマンドは、デバッガーの状態に応じて可視性が制御される。デバッガーがFSI以外にアタッチされている場合、このコマンドは非表示となる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 7 | F# Interactive ツールウィンドウ | 主画面 | エディタから F# Interactive へコードを送信・実行（選択コード送信、行送信、デバッグ実行） |

## 機能種別

コマンド処理 / エディタ統合 / REPL連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| pguidCmdGroup | Guid | Yes | コマンドグループGUID | VSConstants.VsStd11またはGuids.guidInteractive |
| nCmdId | uint32 | Yes | コマンドID | ExecuteSelectionInInteractive/ExecuteLineInInteractive/cmdIDDebugSelection |
| nCmdexecopt | uint32 | Yes | 実行オプション | - |
| pvaIn | IntPtr | No | 入力パラメータ | - |
| pvaOut | IntPtr | No | 出力パラメータ | - |

### 入力データソース

- Visual Studioエディタからのコマンド入力
- ユーザーのメニュー選択またはキーボードショートカット

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| HRESULT | int | コマンド実行結果（S_OK/E_FAIL） |

### 出力先

- F# Interactive ツールウィンドウへのコード送信
- Visual Studioコマンドチェーンへの結果返却

## 処理フロー

### 処理シーケンス

```
1. テキストビュー作成時にコマンドフィルタをアタッチ
   └─ FsiCommandFilterProviderがTextViewCreatedイベントを処理
2. コマンド実行要求を受信（Exec）
   └─ コマンドグループとコマンドIDを判定
3. F# Interactiveパッケージを遅延ロード
   └─ IVsShell.LoadPackageを呼び出し
4. コマンド種別に応じてHooksモジュールを呼び出し
   └─ OnMLSendメソッドで適切なアクションを実行
5. コマンド状態問い合わせ（QueryStatus）
   └─ デバッガー状態に応じてコマンド可視性を制御
```

### フローチャート

```mermaid
flowchart TD
    A[開始: TextViewCreated] --> B[FsiCommandFilter生成]
    B --> C[AddCommandFilterでアタッチ]
    C --> D[コマンド待機]
    D --> E{Exec呼び出し}
    E --> F{コマンドグループ判定}
    F -->|VsStd11| G{コマンドID判定}
    F -->|guidInteractive| H[DebugSelection処理]
    F -->|その他| I[次のフィルタへ転送]
    G -->|ExecuteSelection| J[選択範囲実行]
    G -->|ExecuteLine| K[行実行]
    J --> L[Hooks.OnMLSend呼び出し]
    K --> L
    H --> L
    L --> M[S_OK返却]
    I --> N[nextTarget.Exec]
    M --> O[終了]
    N --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-72-01 | パッケージ遅延ロード | F# Interactiveパッケージは最初のコマンド実行時にロード | パッケージ未ロード時 |
| BR-72-02 | デバッグ選択制御 | デバッガーがFSI以外にアタッチ中はDebugSelectionを非表示 | デバッグセッション中 |
| BR-72-03 | コマンドチェーン | 不明なコマンドは次のコマンドフィルタへ転送 | 常時 |
| BR-72-04 | F#コンテンツタイプ | F#ファイルのエディタにのみフィルタをアタッチ | テキストビュー作成時 |

### 計算ロジック

特になし。

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

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| E_FAIL | コマンド失敗 | 次のフィルタがnullで不明コマンドを受信 | E_FAILを返却 |
| - | パッケージロード失敗 | FSIパッケージのロードに失敗 | nullを返却し、コマンドは処理されない |

### リトライ仕様

パッケージロードは遅延評価（lazy）により一度だけ実行される。失敗した場合はnullが保持され、以降のコマンドは無視される。

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

本機能はトランザクション管理を必要としない。

## パフォーマンス要件

- パッケージの遅延ロードにより、起動時のオーバーヘッドを最小化
- コマンド実行は同期的に処理されるため、UIスレッドでの実行時間を最小化すること

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

- F# Interactiveで実行されるコードは、ユーザーの権限で動作する
- デバッグ実行時はデバッガーの権限が適用される

## 備考

- FsiEditorSendActionには ExecuteSelection、ExecuteLine、DebugSelection の3種類がある
- コマンドフィルタはWPFテキストビューの作成時に自動的にアタッチされる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | FsiCommandService.fs | `vsintegration/src/FSharp.Editor/Commands/FsiCommandService.fs` | コマンドフィルタの主実装 |

**主要処理フロー**:
1. **93-105行目**: `FsiCommandFilterProvider`クラス - テキストビュー作成時のフィルタアタッチ
2. **18-27行目**: パッケージ遅延ロード処理
3. **38-61行目**: `Exec`メソッド - コマンド実行処理
4. **63-91行目**: `QueryStatus`メソッド - コマンド状態問い合わせ

**読解のコツ**: F#のMEF（Managed Extensibility Framework）属性に注目。`[<Export>]`、`[<ContentType>]`、`[<TextViewRole>]`属性がVisual Studioとの統合ポイントを定義している。

#### Step 2: コマンド定数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | VSConstants | Microsoft.VisualStudio | VsStd11コマンドグループとコマンドID |
| 2-2 | Guids.fs | `vsintegration/src/FSharp.Editor/` | guidInteractiveとcmdIDDebugSelection定義 |

#### Step 3: F# Interactiveパッケージとの連携を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Hooks.fs | `vsintegration/src/FSharp.Interactive/` | OnMLSendメソッドとGetDebuggerStateメソッド |
| 3-2 | FsiEditorSendAction | `vsintegration/src/FSharp.Interactive/` | 送信アクションの列挙型 |

**読解のコツ**: Hooks.OnMLSendは、エディタからF# Interactiveへのコード送信を実際に行うメソッド。FsiEditorSendActionでアクション種別を指定する。

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

```
Visual Studio Editor Infrastructure
    │
    └─ IWpfTextViewCreationListener.TextViewCreated
           │
           └─ FsiCommandFilterProvider
                  │
                  ├─ IVsEditorAdaptersFactoryService.GetViewAdapter
                  │
                  └─ FsiCommandFilter
                         │
                         ├─ IVsTextView.AddCommandFilter
                         │
                         └─ IOleCommandTarget.Exec / QueryStatus
                                │
                                ├─ IVsShell.LoadPackage (lazy)
                                │      └─ FSharp.Interactive Package
                                │
                                └─ Hooks.OnMLSend
                                       ├─ ExecuteSelection
                                       ├─ ExecuteLine
                                       └─ DebugSelection
```

### データフロー図

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

Menu/Keyboard ──────────▶ IOleCommandTarget.Exec ────────────▶ HRESULT
    │                           │
    │                           ▼
    │                    コマンドグループ判定
    │                           │
    │                           ▼
    │                    パッケージロード（lazy）
    │                           │
    │                           ▼
    │                    Hooks.OnMLSend
    │                           │
    │                           ▼
    └─────────────────────▶ F# Interactive Window ──────────▶ 実行結果
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| FsiCommandService.fs | `vsintegration/src/FSharp.Editor/Commands/FsiCommandService.fs` | ソース | コマンドフィルタとプロバイダの実装 |
| FSharpConstants.fs | `vsintegration/src/FSharp.Editor/Common/FSharpConstants.fs` | ソース | fsiPackageGuidString定義 |
| Guids.fs | `vsintegration/src/FSharp.Interactive/` | ソース | guidInteractive、cmdIDDebugSelection定義 |
| Hooks.fs | `vsintegration/src/FSharp.Interactive/` | ソース | OnMLSend、GetDebuggerState実装 |
| FsiEditorSendAction.fs | `vsintegration/src/FSharp.Interactive/` | ソース | 送信アクション列挙型 |
