# 機能設計書 52-アセンブリ参照解決

## 概要

本ドキュメントは、F#コンパイラにおける依存関係マネージャー（DependencyProvider）を介したアセンブリ参照解決機能について記述する。

### 本機能の処理概要

F#コンパイラおよびF# Interactiveにおいて、`#r "..."` ディレクティブで指定された依存関係をプラグイン型の依存関係マネージャーを通じて解決する機能を提供する。

**業務上の目的・背景**：F#スクリプトでは様々な形式の依存関係参照（DLLパス、NuGetパッケージ、パケット等）をサポートする必要がある。本機能は依存関係マネージャーの抽象化レイヤーを提供し、拡張可能な依存関係解決を実現する。これにより、サードパーティの依存関係マネージャー（Paket等）もシームレスに統合可能となる。

**機能の利用シーン**：
- F#コンパイラでの参照アセンブリの解決
- F# Interactiveでの動的なアセンブリロード
- .fsxスクリプトでの依存関係管理
- IDE（Visual Studio）でのプロジェクト参照解決

**主要な処理内容**：
1. 依存関係マネージャープラグインの検出とロード
2. `#r` ディレクティブの解析とマネージャーへの振り分け
3. 解決されたアセンブリパスの収集
4. ソースファイルとスクリプトの展開
5. ネイティブライブラリパスの処理

**関連システム・外部連携**：
- NuGet依存関係マネージャー（FSharp.DependencyManager.Nuget）
- サードパーティ依存関係マネージャー（Paket等）
- .NETアセンブリローダー

**権限による制御**：特になし

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | F# Interactive | 参照画面 | #r ディレクティブの実行 |
| - | プロジェクトプロパティ | 設定画面 | 依存関係マネージャーの設定 |

## 機能種別

データ連携 / プラグイン管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| packageManagerKey | string | Yes | 依存関係マネージャーの識別キー（例："nuget"） | 登録済みマネージャーキー |
| scriptDirectory | string | Yes | スクリプトファイルのディレクトリ | 有効なパス |
| implicitIncludeDir | string | No | 暗黙的なインクルードディレクトリ | - |
| mainSourceFile | string | No | メインソースファイルパス | - |
| fileName | string | Yes | 対象ファイル名 | - |
| targetFramework | string | Yes | ターゲットフレームワーク | 有効なTFM |
| runtimeIdentifier | string | No | ランタイム識別子 | 有効なRID |
| packageManagerTextLines | (string * string) seq | Yes | 参照ディレクティブ行 | - |
| reportError | ErrorReportType -> range -> string -> unit | Yes | エラー報告コールバック | - |

### 入力データソース

- F#ソースファイル内の`#r` ディレクティブ
- コンパイラオプション（--targetprofile等）
- 環境設定（探索パス等）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| success | bool | 解決成功/失敗 |
| resolutions | string list | 解決されたアセンブリパス |
| sourceFiles | string list | 展開されたソースファイル |
| stdout | string list | 標準出力メッセージ |
| disposer | IDisposable | リソース解放用 |

### 出力先

- コンパイラの参照リスト
- F# Interactiveのアセンブリロードキュー

## 処理フロー

### 処理シーケンス

```
1. 依存関係マネージャーの検索
   └─ IDependencyManagerProvider.TryFindDependencyManagerByKeyでキーからマネージャー取得

2. 依存関係の解決
   └─ IDependencyManagerProvider.CreatePackageManagerUnifyingMessagesでメッセージ統一
   └─ ResolveDependenciesで依存関係を解決

3. 解決結果の処理
   └─ ResolvedReferences: アセンブリパスの取得
   └─ SourceFiles: ソースファイルの取得
   └─ Success: 成功/失敗の判定

4. エラー処理
   └─ ResolutionErrors: エラーメッセージの報告
   └─ 無効なパスの警告
```

### フローチャート

```mermaid
flowchart TD
    A[開始: #r ディレクティブ] --> B[キーから依存関係マネージャー検索]
    B --> C{マネージャー発見?}
    C -->|No| D[標準アセンブリ参照として処理]
    C -->|Yes| E[依存関係マネージャーに解決を依頼]
    E --> F{解決成功?}
    F -->|Yes| G[解決済みアセンブリを追加]
    F -->|No| H[エラーを報告]
    G --> I[ソースファイルを展開]
    I --> J[終了]
    D --> J
    H --> J
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-52-01 | ネイティブパス検証 | ネイティブライブラリパスが存在しない場合は警告 | path.Exists = false |
| BR-52-02 | マネージャーの優先順位 | 組み込みマネージャー > ユーザー定義マネージャー | 複数候補時 |
| BR-52-03 | キャッシュ | ReflectionOnlyAssemblyLoaderを使用したアセンブリ情報のキャッシュ | 常時 |

### 計算ロジック

特になし

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

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| FSComp.SR.packageManagerUnknown | 警告 | 不明な依存関係マネージャーキー | 有効なキーを使用 |
| FSComp.SR.packageManagerError | エラー | 依存関係解決の失敗 | パッケージ参照を確認 |
| FSComp.SR.packageManagerRequiresRecoverableError | エラー | 回復可能なエラー | 再試行またはパッケージ確認 |

### リトライ仕様

本機能に自動リトライ機構はない。

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

該当なし

## パフォーマンス要件

- ReflectionOnlyAssemblyLoaderによるアセンブリメタデータのキャッシュ
- 解決結果のメモリ内キャッシュ

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

- プラグインDLLは信頼されたパスからのみロード
- アセンブリのリフレクション専用ロードで安全性確保

## 備考

- IDependencyManagerProvider インターフェースは拡張ポイント
- 複数の依存関係マネージャーを同時に使用可能

---

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

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

### 推奨読解順序

#### Step 1: インターフェースを理解する

まず、依存関係マネージャーの契約（インターフェース）を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | DependencyProvider.fs | `src/Compiler/DependencyManager/DependencyProvider.fs` | IDependencyManagerProviderインターフェース（75-111行目）で公開APIを理解 |
| 1-2 | DependencyProvider.fs | `src/Compiler/DependencyManager/DependencyProvider.fs` | IResolveDependenciesResultインターフェース（40-55行目）で解決結果の構造を理解 |

**読解のコツ**: F#のインターフェースは `abstract` メンバーで定義される。`inherit` でベースインターフェースを継承。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | DependencyProvider.fs | `src/Compiler/DependencyManager/DependencyProvider.fs` | DependencyProviderクラス（365-554行目）がメインエントリーポイント |

**主要処理フロー**:
1. **385-400行目**: CreatePackageManagerUnifyingMessagesForGivenCacheメソッド
2. **401-420行目**: TryFindDependencyManagerByKeyメソッド
3. **452-505行目**: Resolveメソッド（依存関係解決の中核）

#### Step 3: マネージャー検出を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | DependencyProvider.fs | `src/Compiler/DependencyManager/DependencyProvider.fs` | ReflectionDependencyManagerProviderクラス（172-364行目）でリフレクションベースの検出 |

**主要処理フロー**:
- **183-200行目**: アセンブリ探索パスの構築
- **230-280行目**: CreateDependencyManagerProviderメソッドでマネージャーインスタンス化
- **323-356行目**: TryFindDependencyManagerInPathメソッド

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

```
DependencyProvider
    │
    ├─ TryFindDependencyManagerByKey
    │      └─ ReflectionDependencyManagerProvider.TryFindDependencyManagerByKey
    │             └─ TryFindDependencyManagerInPath
    │                    └─ CreateDependencyManagerProvider
    │
    └─ Resolve
           │
           ├─ packageManager.ResolveDependencies
           │      └─ (各依存関係マネージャーの実装)
           │
           ├─ result.ResolvedReferences (アセンブリパス取得)
           │
           └─ result.SourceFiles (ソースファイル取得)
```

### データフロー図

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

#r "nuget:..."            ──▶  パースと振り分け           ──▶  packageManagerKey
       │
       ▼
packageManagerKey         ──▶  TryFindDependencyManager   ──▶  IDependencyManager
       │
       ▼
IDependencyManager        ──▶  ResolveDependencies        ──▶  IResolveDependenciesResult
       │
       ▼
IResolveDependenciesResult ──▶ ResolvedReferences          ──▶  アセンブリパスリスト
       │
       ▼
アセンブリパスリスト       ──▶  コンパイラ参照リスト      ──▶  コンパイル/実行
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| DependencyProvider.fs | `src/Compiler/DependencyManager/DependencyProvider.fs` | ソース | 依存関係プロバイダーの中核実装 |
| DependencyProvider.fsi | `src/Compiler/DependencyManager/DependencyProvider.fsi` | シグネチャ | 公開インターフェース定義 |
| AssemblyReaderReflectOnlyLoader.fs | `src/Compiler/DependencyManager/AssemblyReaderReflectOnlyLoader.fs` | ソース | アセンブリメタデータのリフレクション読み込み |
| FSharp.DependencyManager.fs | `src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fs` | ソース | NuGet依存関係マネージャー実装 |
