# 機能設計書 50-リソース埋め込み

## 概要

本ドキュメントは、F#ビルドシステムにおけるリソースファイル埋め込みタスク（FSharpEmbedResourceText）の機能設計を記述する。

### 本機能の処理概要

FSharpEmbedResourceTextタスクは、テキストリソースファイル（.txt）からリソースファイル（.resx）とF#ソースファイル（.fs/.fsi）を自動生成するMSBuildタスクである。エラーメッセージや文字列リソースを型安全にアクセスできるようにする。

**業務上の目的・背景**：F#コンパイラ自体のエラーメッセージや警告メッセージは、リソースファイルとして管理される。このタスクは、人間が編集しやすいテキスト形式（.txt）から、.NETリソースシステムで使用できる.resxファイルと、型安全なアクセスを提供するSRクラスを含む.fsファイルを生成する。

**機能の利用シーン**：
- F#コンパイラのエラーメッセージリソース生成
- ローカライズ対応のための文字列リソース管理
- 型安全なリソースアクセスコードの自動生成
- ビルド時のリソースファイル自動更新

**主要な処理内容**：
1. テキストリソースファイルの読み込みとパース
2. 識別子と文字列の一意性検証
3. フォーマット文字列のホール（%d, %s等）解析
4. .resxファイルの生成
5. SRクラスを含む.fs/.fsiファイルの生成

**関連システム・外部連携**：MSBuild、.NETリソースシステム

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

## 関連画面

本機能はビルドシステム機能のため、直接関連する画面はない。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | - |

## 機能種別

ビルドタスク / リソース生成

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| EmbeddedText | ITaskItem[] | Yes | 処理対象のテキストリソースファイル | - |
| IntermediateOutputPath | string | Yes | 出力先ディレクトリパス | - |

### 入力データソース

テキストリソースファイル（.txt）形式：
```
# コメント行（#で開始）
識別子,"文字列リソース"
エラー番号,識別子,"文字列リソース"
```

フォーマット指定子：
| 指定子 | 型 | 説明 |
|-------|-----|------|
| %d | System.Int32 | 整数 |
| %x | System.UInt32 | 16進数 |
| %X | System.UInt32 | 16進数（大文字） |
| %f | System.Double | 浮動小数点数 |
| %s | System.String | 文字列 |
| %% | - | %のエスケープ |

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| GeneratedSource | ITaskItem[] | 生成されたF#ソースファイル（.fs, .fsi） |
| GeneratedResx | ITaskItem[] | 生成されたリソースファイル（.resx） |

### 出力先

中間出力パス（IntermediateOutputPath）配下に以下を生成：
- `{ファイル名}.fs` - SRクラス実装
- `{ファイル名}.fsi` - SRクラスシグネチャ
- `{ファイル名}.resx` - リソースファイル

## 処理フロー

### 処理シーケンス

```
1. MSBuildからタスク呼び出し
   └─ Execute()メソッドが呼ばれる
2. 各テキストファイルを処理
   └─ generateResxAndSourceを呼び出し
3. 更新チェック
   └─ 既存ファイルが最新なら生成をスキップ
4. テキストファイルの読み込み
   └─ コメント行を除外して読み込み
5. 行のパース
   └─ ParseLineで各行を解析
6. 検証
   └─ 識別子と文字列の一意性を確認
7. ソースファイル生成
   └─ SRクラスを含む.fsと.fsiを生成
8. リソースファイル生成
   └─ XML形式の.resxファイルを生成
9. 結果の返却
   └─ 生成されたファイル情報をMSBuildに返す
```

### フローチャート

```mermaid
flowchart TD
    A[MSBuildからの呼び出し] --> B[Execute]
    B --> C[各EmbeddedTextを処理]
    C --> D[generateResxAndSource]
    D --> E{ファイルは最新?}
    E -->|Yes| F[スキップ]
    E -->|No| G[テキストファイル読み込み]
    G --> H[ParseLineで各行解析]
    H --> I[識別子の一意性検証]
    I --> J[文字列の一意性検証]
    J --> K[.fs/.fsiファイル生成]
    K --> L[.resxファイル生成]
    L --> M[完了]
    F --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | ファイル名制限 | ファイル名は英数字のみ | 常時 |
| BR-02 | 識別子一意性 | 同一ファイル内で識別子は一意 | 常時 |
| BR-03 | 文字列一意性 | 同一ファイル内で文字列は一意 | 常時 |
| BR-04 | 更新チェック | 入力が出力より古い場合はスキップ | 常時 |

### 計算ロジック

フォーマット文字列の変換：
| 入力形式 | .NET形式 |
|---------|---------|
| %d | {0} |
| %x | {0:x} |
| %s | {1} |
| {{ | { |
| }} | } |

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| TaskFailed | 実行時エラー | パースエラー、検証エラー | 入力ファイルを修正 |
| - | 解析エラー | 不正なフォーマット指定子 | %d, %x, %X, %f, %s, %%のみ使用 |
| - | 解析エラー | 識別子が文字で始まらない | 識別子は文字で開始 |
| - | 検証エラー | 識別子の重複 | 識別子を一意に修正 |
| - | 検証エラー | 文字列の重複 | 文字列を一意に修正 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- インクリメンタルビルド対応（更新チェックによるスキップ）
- ファイル単位での独立処理

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

- 生成されるコードは信頼されたビルド環境内で実行される
- 入力ファイルの内容検証を行う

## 備考

FSharpEmbedResourceTextは、F#コンパイラ自体のビルドで使用される重要なタスクである。生成されるSRクラスは、GetStringFunc関数を通じてprintf形式の型安全なリソースアクセスを提供する。

---

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

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

### 推奨読解順序

#### Step 1: クラス構造を理解する

FSharpEmbedResourceTextタスクの全体構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | FSharpEmbedResourceText.fs | `src/FSharp.Build/FSharpEmbedResourceText.fs` | **14-19行目**: クラス定義とフィールド |
| 1-2 | FSharpEmbedResourceText.fs | `src/FSharp.Build/FSharpEmbedResourceText.fs` | **615-629行目**: プロパティ定義 |

**読解のコツ**: Taskを継承し、EmbeddedText（入力）とGeneratedSource/GeneratedResx（出力）のプロパティを持つシンプルな構造。

#### Step 2: テキストパース処理を理解する

テキストリソースファイルの解析処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | FSharpEmbedResourceText.fs | `src/FSharp.Build/FSharpEmbedResourceText.fs` | **159-197行目**: ComputeHoles関数 |
| 2-2 | FSharpEmbedResourceText.fs | `src/FSharp.Build/FSharpEmbedResourceText.fs` | **205-258行目**: ParseLine関数 |

**主要処理フロー**:
- **159行目**: ComputeHolesで%d, %sなどのホールを検出
- **166-172行目**: ホールタイプに応じて{0}形式に変換
- **205行目**: ParseLineで行全体をパース
- **206-222行目**: オプショナルなエラー番号をパース
- **224-239行目**: 識別子をパース
- **244-258行目**: 文字列をパースしてホールを解析

#### Step 3: 検証処理を理解する

識別子と文字列の一意性検証を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FSharpEmbedResourceText.fs | `src/FSharp.Build/FSharpEmbedResourceText.fs` | **454-468行目**: 識別子一意性検証 |
| 3-2 | FSharpEmbedResourceText.fs | `src/FSharp.Build/FSharpEmbedResourceText.fs` | **471-488行目**: 文字列一意性検証 |

#### Step 4: ソースコード生成を理解する

SRクラスを含むF#ソースファイルの生成を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | FSharpEmbedResourceText.fs | `src/FSharp.Build/FSharpEmbedResourceText.fs` | **260-273行目**: stringBoilerPlatePrefix |
| 4-2 | FSharpEmbedResourceText.fs | `src/FSharp.Build/FSharpEmbedResourceText.fs` | **275-384行目**: StringBoilerPlate関数 |
| 4-3 | FSharpEmbedResourceText.fs | `src/FSharp.Build/FSharpEmbedResourceText.fs` | **490-578行目**: SRクラスメソッド生成 |

**主要処理フロー**:
- **275行目**: StringBoilerPlateでリソースアクセス基盤を生成
- **286-296行目**: GetString関数でリソース取得
- **339-366行目**: createMessageStringでprintf形式サポート
- **510-578行目**: 各リソースに対応するメソッドを生成

#### Step 5: リソースファイル生成を理解する

.resxファイルの生成を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | FSharpEmbedResourceText.fs | `src/FSharp.Build/FSharpEmbedResourceText.fs` | **36-156行目**: xmlBoilerPlateString |
| 5-2 | FSharpEmbedResourceText.fs | `src/FSharp.Build/FSharpEmbedResourceText.fs` | **594-608行目**: .resx生成 |

#### Step 6: 実行処理を理解する

タスク全体の実行フローを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | FSharpEmbedResourceText.fs | `src/FSharp.Build/FSharpEmbedResourceText.fs` | **631-671行目**: Execute()メソッド |
| 6-2 | FSharpEmbedResourceText.fs | `src/FSharp.Build/FSharpEmbedResourceText.fs` | **395-613行目**: generateResxAndSource |

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

```
MSBuild (FSharpEmbedResourceTextタスク呼び出し)
    │
    ├─ FSharpEmbedResourceText.Execute()
    │      │
    │      └─ Array.choose generateResxAndSource
    │             │
    │             ├─ 更新チェック (condition1-5)
    │             │      └─ File.GetLastWriteTimeUtc比較
    │             │
    │             ├─ File.ReadAllLines
    │             │      └─ コメント行フィルタリング
    │             │
    │             ├─ Array.map ParseLine
    │             │      │
    │             │      ├─ エラー番号パース (optional)
    │             │      │
    │             │      ├─ 識別子パース
    │             │      │
    │             │      ├─ 文字列パース
    │             │      │      └─ Unquote
    │             │      │
    │             │      └─ ComputeHoles
    │             │             └─ ホール検出 (%d→System.Int32等)
    │             │
    │             ├─ 識別子一意性検証
    │             │      └─ Dictionary<string, int>
    │             │
    │             ├─ 文字列一意性検証
    │             │      └─ Dictionary<string, (int*string)>
    │             │
    │             ├─ .fs/.fsi生成
    │             │      ├─ stringBoilerPlatePrefix
    │             │      ├─ StringBoilerPlate
    │             │      └─ 各リソースメソッド生成
    │             │
    │             └─ .resx生成
    │                    ├─ XmlDocument.LoadXml(xmlBoilerPlateString)
    │                    └─ data要素追加
    │
    └─ GeneratedSource, GeneratedResx設定
```

### データフロー図

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

テキストファイル    ───▶  ReadAllLines        ───▶  行配列
  .txt                     (コメント除外)            (lineNum, text)
    │
    ▼
行配列           ───▶  ParseLine           ───▶  stringInfos
                       (各行解析)                 (lineNum, (errNum,ident),
    │                                              str, holes, netFormat)
    ▼
stringInfos      ───▶  検証処理            ───▶  検証済み情報
                       (一意性確認)
    │
    ├──────────────────────────────────────────────────────────┐
    ▼                                                          ▼
SRクラス生成      ───▶  StreamWriter        ───▶  .fs/.fsiファイル
  ボイラープレート +                              (型安全アクセス)
  リソースメソッド
    │
    ▼
XmlDocument      ───▶  data要素追加        ───▶  .resxファイル
  ボイラープレート                                 (リソース定義)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| FSharpEmbedResourceText.fs | `src/FSharp.Build/FSharpEmbedResourceText.fs` | ソース | タスク実装 |
| FSComp.txt | `src/Compiler/FSComp.txt` | リソース | コンパイラエラーメッセージ定義 |
| FSStrings.txt | `src/Compiler/FSStrings.txt` | リソース | コンパイラ文字列リソース定義 |
| FSharp.Build.fsproj | `src/FSharp.Build/FSharp.Build.fsproj` | プロジェクト | ビルドプロジェクト |
