# 機能設計書 2-インクリメンタルビルド

## 概要

本ドキュメントは、F#コンパイラのインクリメンタルビルド機能の設計を記述する。インクリメンタルビルドは、ソースファイルの依存関係を解析し、変更があった部分のみを再コンパイルすることで、ビルド時間を短縮する機能である。

### 本機能の処理概要

インクリメンタルビルドは、IDE統合（Visual Studio、Visual Studio Code等）において、ソースファイルの変更を検出し、必要最小限のファイルのみを再解析・再型チェックする機能である。

**業務上の目的・背景**：大規模なF#プロジェクトでは、全ファイルを毎回コンパイルすると数分以上かかることがある。開発者の生産性を維持するためには、コード変更後の型チェック結果やIntelliSense情報を数秒以内に提供する必要がある。インクリメンタルビルドは、依存関係グラフを活用して最小限の再計算でこれを実現する。

**機能の利用シーン**：開発者がIDEでF#コードを編集している際、バックグラウンドで自動的にインクリメンタルビルドが実行される。ファイル保存時、IntelliSense呼び出し時、ビルド実行時などにトリガーされる。

**主要な処理内容**：
1. ソースファイルの依存関係解析と依存グラフ構築
2. ファイルタイムスタンプの監視と変更検出
3. 変更されたファイルとその依存ファイルの特定
4. SyntaxTree（構文木）ノードの遅延パース
5. BoundModel（型付きモデル）の増分型チェック
6. 型チェック結果のキャッシュと再利用
7. プロジェクト全体の最終化（FinalizeTypeCheckTask）

**関連システム・外部連携**：FSharpChecker API、BackgroundCompiler、TransparentCompilerと連携する。IDEからはFSharpProjectOptionsを通じてプロジェクト設定を受け取る。

**権限による制御**：特になし。IDE統合設定によりインクリメンタルビルドの動作をカスタマイズ可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 5 | 言語サービスパフォーマンスオプション画面 | 参照画面 | バックグラウンド解決の保持設定 |

## 機能種別

ビルド処理（増分コンパイル）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| sourceFiles | FSharpFile list | Yes | ソースファイル情報（パス、タイムスタンプ） | 有効なファイルパス |
| tcConfig | TcConfig | Yes | コンパイラ設定 | 有効なTcConfig |
| tcGlobals | TcGlobals | Yes | グローバル型情報 | 初期化済み |
| tcImports | TcImports | Yes | インポート済みアセンブリ情報 | 初期化済み |
| referencedAssemblies | ImmutableArray | Yes | 参照アセンブリとタイムスタンプ関数 | 解決済みアセンブリ |

### 入力データソース

- ファイルシステム上のF#ソースファイル
- FSharpProjectOptionsで指定されたプロジェクト設定
- 参照アセンブリのメタデータ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| PartialCheckResults | PartialCheckResults | 部分的な型チェック結果 |
| TcInfo | TcInfo | 型チェック状態情報 |
| TcInfoExtras | TcInfoExtras | 追加の型チェック情報（シンボル使用、解決情報等） |
| BoundModel | BoundModel | 型付きモデル |

### 出力先

- メモリ内キャッシュ（IDE統合用）
- FSharpChecker APIを通じたIDE

## 処理フロー

### 処理シーケンス

```
1. IncrementalBuilder初期化
   ├─ IncrementalBuilderInitialState作成
   ├─ FrameworkImportsCache取得
   ├─ CombineImportedAssembliesTask実行
   └─ IncrementalBuilderState.Create

2. ファイル変更検出
   ├─ TimeStampCache更新
   ├─ computeStampedFileNames実行
   └─ 変更ファイルのSlot.Notified設定

3. 構文木パース（SyntaxTree）
   ├─ SyntaxTree.ParseNode.GetOrComputeValue
   └─ GraphNodeによる遅延評価

4. 型チェック（BoundModel）
   ├─ BoundModel.Next(syntaxTree)
   ├─ CheckOneInput実行
   └─ TcInfo/TcInfoExtras更新

5. プロジェクト最終化
   ├─ FinalizeTypeCheckTask
   ├─ CheckClosedInputSetFinish
   └─ RawFSharpAssemblyData生成
```

### フローチャート

```mermaid
flowchart TD
    A[ファイル変更検出] --> B[TimeStampCache更新]
    B --> C{変更あり?}
    C -->|No| D[キャッシュ結果返却]
    C -->|Yes| E[SyntaxTree.Invalidate]
    E --> F[影響スロット特定]
    F --> G[BoundModel再計算]
    G --> H[型チェック実行]
    H --> I[TcInfo更新]
    I --> J[結果キャッシュ]
    J --> K[PartialCheckResults返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 依存順序保持 | ファイルは定義順に型チェックされる | 常時 |
| BR-002 | シグネチャ分離 | .fsiファイル変更は実装ファイルに影響しない | .fsi存在時 |
| BR-003 | 参照アセンブリ変更 | 参照変更時は全ファイル再チェック | 参照タイムスタンプ変更時 |
| BR-004 | キャッシュ有効性 | タイムスタンプ一致でキャッシュ有効 | 常時 |

### 計算ロジック

依存関係は線形順序で管理される。ファイルNが変更された場合、ファイルN以降のすべてのBoundModelが無効化される。ただし、シグネチャファイル（.fsi）が存在する場合、実装ファイルの変更はシグネチャを変えない限り後続に影響しない。

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ファイル読み取りエラー | ファイルアクセス失敗 | 前回のキャッシュを使用 |
| - | 参照解決エラー | アセンブリ参照解決失敗 | 警告を記録し続行 |
| - | 型チェックエラー | 型エラー検出 | 診断情報として報告 |

### リトライ仕様

エラー発生時は前回の有効なキャッシュを使用。ファイル変更通知を受けて再試行。

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

該当なし（メモリ内キャッシュのみ）

## パフォーマンス要件

- 単一ファイル変更時の型チェック更新：1秒以内
- IntelliSense応答：200ms以内（キャッシュヒット時）
- プロジェクト全体の初回ビルド後、増分ビルドは最大90%高速化

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

- キャッシュはプロセスメモリ内に保持
- 型プロバイダー呼び出しは元のセキュリティコンテキストを維持

## 備考

IncrementalBuilderはGraphNodeを活用した遅延評価パターンを採用しており、必要になるまで計算を遅延させる。これにより、IDE応答性とメモリ効率を両立している。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | IncrementalBuild.fs | `src/Compiler/Service/IncrementalBuild.fs` | TcInfo、TcInfoExtras、BoundModel、Slotの定義 |
| 1-2 | IncrementalBuild.fs | `src/Compiler/Service/IncrementalBuild.fs` | IncrementalBuilderInitialState、IncrementalBuilderStateの定義 |

**読解のコツ**:
- TcInfoは型チェック状態の最小情報（tcState、tcEnvAtEndOfFile等）
- TcInfoExtrasは追加情報（シンボル使用、解決情報、ItemKeyStore等）
- SlotはファイルごとのSyntaxTree、BoundModel、タイムスタンプを保持

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | IncrementalBuild.fs | `src/Compiler/Service/IncrementalBuild.fs` | IncrementalBuilderクラス定義（1114-1380行目） |

**主要処理フロー**:
1. **1383-1672行目**: TryCreateIncrementalBuilderForProjectOptions - ビルダー作成
2. **1219-1225行目**: PopulatePartialCheckingResults - 全ファイル型チェック
3. **1261-1271行目**: GetCheckResultsBeforeSlotInProject - スロット前までの結果取得

#### Step 3: SyntaxTree（構文木）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | IncrementalBuild.fs | `src/Compiler/Service/IncrementalBuild.fs` | SyntaxTreeクラス（111-183行目） |

**主要処理フロー**:
- **138-170行目**: parse関数 - ソースファイルのパース
- **173行目**: ParseNode - GraphNodeによる遅延パース
- **175-176行目**: Invalidate - 構文木の無効化と再作成

#### Step 4: BoundModel（型付きモデル）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | IncrementalBuild.fs | `src/Compiler/Service/IncrementalBuild.fs` | BoundModelクラス（236-482行目） |

**主要処理フロー**:
- **250-299行目**: getTypeCheck - 型チェック実行
- **422-438行目**: Next - 次のBoundModel作成
- **440-459行目**: Finish - 最終化

#### Step 5: 状態管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | IncrementalBuild.fs | `src/Compiler/Service/IncrementalBuild.fs` | IncrementalBuilderStateHelpers（966-1112行目） |

**主要処理フロー**:
- **992-1029行目**: computeStampedFileNames - ファイルタイムスタンプ計算と変更検出
- **1031-1054行目**: computeStampedReferencedAssemblies - 参照アセンブリタイムスタンプ計算

#### Step 6: 最終化処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | IncrementalBuild.fs | `src/Compiler/Service/IncrementalBuild.fs` | FinalizeTypeCheckTask（762-861行目） |

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

```
IncrementalBuilder.TryCreateIncrementalBuilderForProjectOptions
    │
    ├─ FrameworkImportsCache.Get
    │      └─ TcImports.BuildFrameworkTcImports
    │
    ├─ CombineImportedAssembliesTask
    │      ├─ TcImports.BuildNonFrameworkTcImports
    │      ├─ GetInitialTcEnv
    │      └─ BoundModel.Create
    │
    └─ IncrementalBuilderState.Create
           ├─ SyntaxTree作成（ファイルごと）
           └─ createBoundModelGraphNode（ファイルごと）

IncrementalBuilder.GetCheckResultsBeforeSlotInProject
    │
    ├─ checkFileTimeStamps
    │      └─ computeStampedFileNames
    │
    └─ evalUpToTargetSlot
           └─ BoundModel.GetOrComputeValue
                  ├─ SyntaxTree.ParseNode.GetOrComputeValue
                  └─ CheckOneInput
```

### データフロー図

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

FSharpFile               ──▶  SyntaxTree.parse            ──▶  ParsedInput
(ソースファイル)                    │
                                    ▼
ParsedInput              ──▶  BoundModel.getTypeCheck     ──▶  TcInfo
+ 前ファイルTcInfo                  │
                                    ▼
TcInfo                   ──▶  getTcInfoExtras             ──▶  TcInfoExtras
                                    │                         (シンボル使用、
                                    │                          ItemKeyStore等)
                                    ▼
全BoundModel             ──▶  FinalizeTypeCheckTask       ──▶  ILAssemblyRef
                                                              + ProjectAssemblyData
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| IncrementalBuild.fs | `src/Compiler/Service/IncrementalBuild.fs` | ソース | インクリメンタルビルドのメイン実装 |
| service.fs | `src/Compiler/Service/service.fs` | ソース | FSharpChecker API |
| BackgroundCompiler.fs | `src/Compiler/Service/BackgroundCompiler.fs` | ソース | バックグラウンドコンパイラ |
| TransparentCompiler.fs | `src/Compiler/Service/TransparentCompiler.fs` | ソース | 透過コンパイラ |
| BuildGraph.fs | `src/Compiler/Facilities/BuildGraph.fs` | ソース | GraphNodeの定義 |
| ParseAndCheckInputs.fs | `src/Compiler/Driver/ParseAndCheckInputs.fs` | ソース | パース・型チェック関数 |
| CheckDeclarations.fs | `src/Compiler/Checking/CheckDeclarations.fs` | ソース | 宣言の型チェック |
