# 機能設計書 39-jest-resolve-dependencies

## 概要

本ドキュメントは、jest-resolve-dependenciesパッケージの機能設計を記載する。jest-resolve-dependenciesは、テストファイルの依存関係を解析し、変更されたファイルに影響を受けるテストを特定するための機能を提供する。

### 本機能の処理概要

jest-resolve-dependenciesは、モジュール間の依存関係を解析し、逆引きマップを構築するライブラリである。

**業務上の目的・背景**：大規模なコードベースでテストを実行する際、すべてのテストを実行するのは非効率である。変更されたファイルに依存するテストのみを実行することで、テスト実行時間を大幅に短縮できる。このパッケージは、ファイル変更からテスト実行対象を特定するための依存関係解析を提供する。

**機能の利用シーン**：
- `--onlyChanged`オプションでの変更影響テスト実行
- `--findRelatedTests`オプションでの関連テスト特定
- ウォッチモードでの変更検知と関連テスト実行
- CI/CDでの差分テスト実行

**主要な処理内容**：
1. DependencyResolverクラス: 依存関係解析の中心クラス
2. resolve: ファイルの直接依存を解決
3. resolveInverseModuleMap: 変更ファイルに依存するモジュールマップを取得
4. resolveInverse: 変更ファイルに依存するファイル一覧を取得
5. スナップショットパスの解決

**関連システム・外部連携**：
- jest-haste-map: ファイルシステム情報と依存情報の提供
- jest-resolve: モジュールパスの解決
- jest-snapshot: スナップショットパスの判定と解決

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | CLI出力 | 情報表示 | 実行対象テストの表示 |

## 機能種別

依存関係解析 / テスト選択 / 基盤ユーティリティ

## 入力仕様

### 入力パラメータ

#### DependencyResolverコンストラクタ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| resolver | Resolver | Yes | jest-resolveのResolverインスタンス | - |
| hasteFS | IHasteFS | Yes | jest-haste-mapのファイルシステム | - |
| snapshotResolver | SnapshotResolver | Yes | スナップショットパス解決 | - |

#### resolve

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| file | string | Yes | 解析対象のファイルパス | - |
| options | ResolveModuleConfig | No | 解決オプション | - |

#### resolveInverseModuleMap / resolveInverse

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| paths | Set<string> | Yes | 変更されたファイルのパスセット | - |
| filter | (file: string) => boolean | Yes | テストファイルのフィルター関数 | - |
| options | ResolveModuleConfig | No | 解決オプション | - |

### 入力データソース

- jest-haste-map: ファイル依存情報（getDependencies）
- jest-resolve: モジュール解決結果
- jest-snapshot: スナップショットパス情報

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| resolve戻り値 | Array<string> | 直接依存するモジュールパスの配列 |
| resolveInverseModuleMap戻り値 | Array<ResolvedModule> | 依存モジュールマップ |
| resolveInverse戻り値 | Array<string> | 依存するファイルパスの配列 |

### ResolvedModule型

| プロパティ名 | 型 | 説明 |
|-------------|-----|------|
| file | string | ファイルパス |
| dependencies | Array<string> | 依存するファイルの配列 |

### 出力先

関数の戻り値として返却

## 処理フロー

### 処理シーケンス

```
1. resolve（直接依存の解決）
   └─ hasteFS.getDependenciesで依存一覧を取得
   └─ 各依存に対して:
      └─ コアモジュールはスキップ
      └─ resolver.resolveModuleでパス解決
      └─ 解決失敗時はgetMockModuleを試行
      └─ __mocks__ディレクトリのモックも追加

2. resolveInverseModuleMap（逆依存の解決）
   └─ 変更パスセットからスタート
   └─ スナップショットパスはテストパスに変換
   └─ 全ファイルの依存関係マップを構築
   └─ collectModulesで変更に依存するモジュールを収集

3. resolveInverse
   └─ resolveInverseModuleMapを呼び出し
   └─ ファイルパスのみを抽出
```

### フローチャート

```mermaid
flowchart TD
    A[resolveInverse開始] --> B[resolveInverseModuleMap呼び出し]
    B --> C{paths.size > 0?}
    C -->|No| D[空配列を返却]
    C -->|Yes| E[変更パスを処理]
    E --> F{スナップショット?}
    F -->|Yes| G[テストパスに変換]
    F -->|No| H[そのまま使用]
    G --> I[changedセットに追加]
    H --> I
    I --> J[全ファイルのモジュールマップ構築]
    J --> K[各ファイルでresolve呼び出し]
    K --> L[collectModulesで依存収集]
    L --> M{依存あり?}
    M -->|Yes| N[結果に追加]
    M -->|No| O[スキップ]
    N --> P[ファイルパス抽出]
    O --> P
    P --> Q[結果を返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | コアモジュール除外 | Node.jsコアモジュールは依存から除外 | isCoreModuleがtrue |
| BR-02 | モック依存の追加 | 解決された依存の__mocks__ディレクトリにあるモックも依存に追加 | モックが存在する場合 |
| BR-03 | スナップショットパス変換 | スナップショットパスはテストパスに変換して処理 | isSnapshotPathがtrue |
| BR-04 | フィルター適用 | テストファイルのみをフィルターで選別 | filter関数で判定 |
| BR-05 | 解決失敗時のフォールバック | resolveModule失敗時はgetMockModuleを試行 | 解決例外発生時 |

### 計算ロジック

**逆依存の収集アルゴリズム**：
```
1. 変更ファイルセット(changed)を初期化
2. 全ファイルの依存マップを構築
3. 依存が変更セットに含まれるモジュールを探索
4. 見つかったモジュールを結果に追加し、changedに追加
5. 新たな変更がなくなるまで繰り返し
```

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 例外キャッチ | resolveModule失敗 | getMockModuleにフォールバック |
| - | 例外キャッチ | getMockModule失敗 | resolvedDependencyをundefinedのまま |

### リトライ仕様

- resolveModule失敗時、getMockModuleで再試行

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

該当なし

## パフォーマンス要件

- 全ファイルの依存マップ構築は1回のみ実行
- 訪問済みモジュールのトラッキングで重複処理を回避

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

- 特になし

## 備考

- このパッケージは主にjest-coreから使用される
- ウォッチモードでのインクリメンタルテスト実行に重要

---

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

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

### 推奨読解順序

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

まず、型定義から理解を始める。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.ts | `packages/jest-resolve-dependencies/src/index.ts` | ResolvedModule型の定義 |

**主要処理フロー**:
1. **13-16行目**: ResolvedModule型
   - `file`: ファイルパス
   - `dependencies`: 依存配列

#### Step 2: DependencyResolverクラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/jest-resolve-dependencies/src/index.ts` | DependencyResolverクラス全体 |

**主要処理フロー**:
1. **22-35行目**: DependencyResolverクラス定義とコンストラクタ
   - **23行目**: `_hasteFS`（ファイルシステム）
   - **24行目**: `_resolver`（モジュールリゾルバー）
   - **25行目**: `_snapshotResolver`（スナップショットリゾルバー）
   - **27-35行目**: コンストラクタで依存を注入

2. **37-103行目**: resolveメソッド（直接依存の解決）
   - **38行目**: `getDependencies`で依存一覧取得
   - **44-102行目**: 依存の解決ループ
   - **45-47行目**: コアモジュールのスキップ
   - **51-67行目**: モジュール解決（フォールバック付き）
   - **77-99行目**: モック依存の追加処理
   - **88-91行目**: `__mocks__`ディレクトリの確認

3. **105-169行目**: resolveInverseModuleMapメソッド（逆依存マップ）
   - **110-112行目**: 空チェック
   - **114-146行目**: collectModules内部関数
   - **119行目**: visitedModulesで重複回避
   - **121-141行目**: 変更依存の探索ループ
   - **148-160行目**: 変更パスの前処理
   - **152-154行目**: スナップショットパスの変換
   - **161-167行目**: 全ファイルのモジュールマップ構築
   - **168行目**: collectModules呼び出し

4. **171-179行目**: resolveInverseメソッド
   - **176-178行目**: resolveInverseModuleMapからファイルパス抽出

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

```
DependencyResolver (index.ts)
    │
    ├─ resolve (直接依存解決)
    │      │
    │      ├─ IHasteFS.getDependencies (jest-haste-map)
    │      │
    │      ├─ Resolver.isCoreModule (jest-resolve)
    │      │
    │      ├─ Resolver.resolveModule (jest-resolve)
    │      │
    │      └─ Resolver.getMockModule (jest-resolve)
    │
    ├─ resolveInverseModuleMap (逆依存マップ)
    │      │
    │      ├─ isSnapshotPath (jest-snapshot)
    │      │
    │      ├─ SnapshotResolver.resolveTestPath (jest-snapshot)
    │      │
    │      ├─ IHasteFS.exists (jest-haste-map)
    │      │
    │      ├─ IHasteFS.getAbsoluteFileIterator (jest-haste-map)
    │      │
    │      └─ resolve (内部呼び出し)
    │
    └─ resolveInverse (逆依存ファイル一覧)
           │
           └─ resolveInverseModuleMap
```

### データフロー図

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

変更ファイルパスセット ───▶ resolveInverse()
                                  │
フィルター関数 ─────────▶        │
                                  │
                                  ├─ スナップショットパス判定
                                  │      │
jest-snapshot ─────────────▶     │      └─ テストパスに変換
                                  │
                                  ├─ 全ファイル依存マップ構築
                                  │      │
jest-haste-map ────────────▶     │      ├─ getAbsoluteFileIterator
(IHasteFS)                        │      │
                                  │      └─ resolve (各ファイル)
                                  │             │
                                  │             ├─ getDependencies
                                  │             │
jest-resolve ─────────────────▶  │             ├─ resolveModule
(Resolver)                        │             │
                                  │             └─ getMockModule
                                  │
                                  ├─ collectModules
                                  │      │
                                  │      └─ 変更に依存するモジュール収集
                                  │
                                  └─ ファイルパス抽出
                                         │
                                         ▼
                                  影響を受けるテストファイル配列
                                  (例: ['src/__tests__/foo.test.ts',
                                        'src/__tests__/bar.test.ts'])

例：
変更: ['src/utils.ts']
    │
    ├─ utils.tsをimportしているファイルを探索
    │
    └─ フィルター適用（テストファイルのみ）
           │
           ▼
    ['src/__tests__/utils.test.ts',
     'src/__tests__/helpers.test.ts']
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/jest-resolve-dependencies/src/index.ts` | ソース | DependencyResolverクラス（唯一のソースファイル） |
| package.json | `packages/jest-resolve-dependencies/package.json` | 設定 | パッケージ定義 |
