# 機能設計書 68-未使用参照検出

## 概要

本ドキュメントは、Roslyn IDE機能の一つである「未使用参照検出（UnusedReferences）」機能の設計を記述する。この機能は、プロジェクトが参照しているが実際には使用されていないプロジェクト参照、パッケージ参照、アセンブリ参照を検出し、削除を提案する機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：開発の過程で追加した参照が、リファクタリングや機能削除によって不要になることがある。不要な参照はビルド時間の増加やパッケージ復元時間の増加を招く。本機能は、実際にコンパイルで使用されていない参照を特定し、プロジェクトのスリム化を支援する。

**機能の利用シーン**：Visual Studioのソリューションエクスプローラーから「未使用の参照を削除」コマンドを実行した際に、未使用の参照一覧をダイアログで表示し、削除操作を提供する。

**主要な処理内容**：
1. コンパイル情報から使用されているアセンブリを特定
2. プロジェクトの参照一覧と比較して未使用参照を検出
3. プロジェクト参照→パッケージ参照→アセンブリ参照の順で処理
4. 直接使用と推移的使用の両方を考慮
5. IReferenceCleanupServiceを通じて参照の更新・削除を実行

**関連システム・外部連携**：IReferenceCleanupService、project.assets.jsonファイルと連携。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 19 | 未使用参照削除ダイアログ | 主機能 | 未使用プロジェクト・パッケージ参照の一覧表示と削除操作 |

## 機能種別

分析 / 参照管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| solution | Solution | Yes | 対象ソリューション | null不可 |
| projectFilePath | string | Yes | 対象プロジェクトファイルパス | 空でないこと |
| references | ImmutableArray&lt;ReferenceInfo&gt; | Yes | 参照情報一覧 | - |

### 入力データソース

- プロジェクトのコンパイル情報
- プロジェクトの参照一覧（ReferenceInfo）
- project.assets.json（NuGetパッケージの依存関係）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| unusedReferences | ImmutableArray&lt;ReferenceInfo&gt; | 未使用参照一覧 |

### 出力先

未使用参照削除ダイアログ

## 処理フロー

### 処理シーケンス

```
1. GetUnusedReferencesAsync呼び出し
   └─ Solution、プロジェクトパス、参照情報を受け取る
2. コンパイル情報取得
   └─ GetUsedAssemblyReferencesで使用アセンブリ取得
3. 使用アセンブリパスとファイル名を収集
   └─ PortableExecutableReferenceとCompilationReference
4. 参照タイプ別に処理（2パス）
   ├─ Pass 1: 直接使用参照を除外
   └─ Pass 2: 推移的使用参照を除外
5. 残った参照を未使用として返却
```

### フローチャート

```mermaid
flowchart TD
    A[プロジェクト参照取得] --> B[コンパイル取得]
    B --> C[GetUsedAssemblyReferences]
    C --> D[使用アセンブリパス収集]
    D --> E[参照タイプ別にグループ化]
    E --> F[Pass 1: 直接使用チェック]
    F --> G{直接使用?}
    G -->|Yes| H[参照から除外]
    G -->|No| I[次の参照へ]
    H --> J[使用アセンブリパスから削除]
    I --> K[Pass 2: 推移的使用チェック]
    K --> L{推移的使用?}
    L -->|Yes| M[参照から除外]
    L -->|No| N[未使用として追加]
    M --> O[使用アセンブリパスから削除]
    N --> P[結果返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-68-01 | 処理順序 | プロジェクト→パッケージ→アセンブリの順で処理 | 常時 |
| BR-68-02 | 推移的参照優先 | 推移的に参照されるパッケージを優先して使用済みとする | 常時 |
| BR-68-03 | 2パス処理 | 直接使用と推移的使用を別パスで判定 | 常時 |
| BR-68-04 | アナライザーパッケージ | コンパイルアセンブリを持たないパッケージは使用済みとする | 常時 |
| BR-68-05 | TreatAsUsed属性 | ユーザーが明示的に使用済みとマークした参照は除外しない | TreatAsUsed時 |

### 計算ロジック

処理順序定数:
```csharp
s_processingOrder = [ReferenceType.Project, ReferenceType.Package, ReferenceType.Assembly]
```

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

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

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

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | コンパイル取得失敗 | プロジェクトのコンパイルがnull | スキップして次へ |

### リトライ仕様

特になし

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

該当なし

## パフォーマンス要件

- コンパイル情報のキャッシュを活用

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

特になし

## 備考

project.assets.jsonからNuGetパッケージの依存関係を読み取るためProjectAssetsReaderを使用

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ReferenceInfo.cs | `src/Features/Core/Portable/UnusedReferences/ReferenceInfo.cs` | 参照情報構造 |
| 1-2 | ReferenceType.cs | `src/Features/Core/Portable/UnusedReferences/ReferenceType.cs` | 参照タイプ列挙 |
| 1-3 | ReferenceUpdate.cs | `src/Features/Core/Portable/UnusedReferences/ReferenceUpdate.cs` | 参照更新情報 |
| 1-4 | UpdateAction.cs | `src/Features/Core/Portable/UnusedReferences/UpdateAction.cs` | 更新アクション列挙 |

**読解のコツ**: ReferenceInfoはCompilationAssembliesとDependenciesを持ち、推移的な依存関係を表現。

#### Step 2: メインロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | UnusedReferencesRemover.cs | `src/Features/Core/Portable/UnusedReferences/UnusedReferencesRemover.cs` | 未使用参照検出のメインロジック |

**主要処理フロー**:
1. **23行目**: s_processingOrder定数（処理順序）
2. **25-62行目**: GetUnusedReferencesAsync（非同期エントリーポイント）
3. **64-126行目**: GetUnusedReferences（静的メソッド、メインロジック）
4. **86-107行目**: Pass 1 - 直接使用参照の除外
5. **110-123行目**: Pass 2 - 推移的使用参照の除外

#### Step 3: 直接使用チェックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | RemoveDirectlyUsedReferences | UnusedReferencesRemover.cs内 | 直接使用チェックロジック |

**主要処理フロー**:
- **128-182行目**: RemoveDirectlyUsedReferences
- **143-163行目**: プロジェクト参照の処理（ファイル名比較）
- **165-175行目**: その他参照の処理（パス比較）

#### Step 4: 推移的使用チェックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | RemoveTransitivelyUsedReferences | UnusedReferencesRemover.cs内 | 推移的使用チェック |

**主要処理フロー**:
- **184-224行目**: RemoveTransitivelyUsedReferences
- **204-209行目**: コンパイルアセンブリなしの参照は使用済み扱い
- **211-216行目**: 推移的に使用されていない場合は未使用

#### Step 5: 参照更新を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | UpdateReferencesAsync | UnusedReferencesRemover.cs内 | 参照更新処理 |
| 5-2 | IReferenceCleanupService.cs | `src/Features/Core/Portable/UnusedReferences/IReferenceCleanupService.cs` | クリーンアップサービス |

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

```
UnusedReferencesRemover.GetUnusedReferencesAsync
    │
    ├─ solution.Projects.Where(p => p.FilePath == projectFilePath)
    │
    ├─ project.GetCompilationAsync
    │      │
    │      └─ compilation.GetUsedAssemblyReferences
    │             │
    │             ├─ PortableExecutableReference.FilePath → usedAssemblyFilePaths
    │             └─ CompilationReference.Compilation.SourceModule.MetadataName → usedProjectFileNames
    │
    └─ GetUnusedReferences
           │
           ├─ references.GroupBy(ReferenceType)
           │
           ├─ RemoveDirectlyUsedReferences (Pass 1)
           │      │
           │      ├─ プロジェクト参照: ファイル名で比較
           │      └─ その他参照: パスで比較
           │
           └─ RemoveTransitivelyUsedReferences (Pass 2)
                  │
                  ├─ HasAnyCompilationAssembly
                  └─ ContainsAnyCompilationAssembly（再帰的）

UnusedReferencesRemover.UpdateReferencesAsync
    │
    └─ IReferenceCleanupService.TryUpdateReferenceAsync
```

### データフロー図

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

Solution            ───▶  UnusedReferencesRemover
projectFilePath                   │
references                        ▼
                         compilation.GetUsedAssemblyReferences
                                  │
                                  ▼
usedAssemblyFilePaths ◀─── PortableExecutableReference
usedProjectFileNames  ◀─── CompilationReference
                                  │
                                  ▼
                         GetUnusedReferences
                                  │
                    ┌─────────────┴─────────────┐
                    ▼                           ▼
        RemoveDirectlyUsed          RemoveTransitivelyUsed
                    │                           │
                    └───────────┬───────────────┘
                                ▼
                    ImmutableArray<ReferenceInfo>  ───▶  未使用参照ダイアログ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| UnusedReferencesRemover.cs | `src/Features/Core/Portable/UnusedReferences/UnusedReferencesRemover.cs` | ソース | 未使用参照検出ロジック |
| ReferenceInfo.cs | `src/Features/Core/Portable/UnusedReferences/ReferenceInfo.cs` | ソース | 参照情報データ構造 |
| ReferenceType.cs | `src/Features/Core/Portable/UnusedReferences/ReferenceType.cs` | ソース | 参照タイプ列挙 |
| ReferenceUpdate.cs | `src/Features/Core/Portable/UnusedReferences/ReferenceUpdate.cs` | ソース | 参照更新情報 |
| UpdateAction.cs | `src/Features/Core/Portable/UnusedReferences/UpdateAction.cs` | ソース | 更新アクション列挙 |
| IReferenceCleanupService.cs | `src/Features/Core/Portable/UnusedReferences/IReferenceCleanupService.cs` | ソース | クリーンアップサービスインターフェース |
| IUnusedReferenceAnalysisService.cs | `src/Features/Core/Portable/UnusedReferences/IUnusedReferenceAnalysisService.cs` | ソース | 分析サービスインターフェース |
| ProjectAssetsReader.cs | `src/Features/Core/Portable/UnusedReferences/ProjectAssets/ProjectAssetsReader.cs` | ソース | project.assets.json読み取り |
| ProjectAssetsModel.cs | `src/Features/Core/Portable/UnusedReferences/ProjectAssets/ProjectAssetsModel.cs` | ソース | project.assets.jsonモデル |
