# 帳票設計書 2-DirectoryCoverageReport

## 概要

本ドキュメントは、LLVMプロジェクトのディレクトリ別カバレッジレポート機能（DirectoryCoverageReport）の設計仕様を記載する。ソースファイルのディレクトリ構造に基づいたカバレッジサマリーを生成する機能である。

### 本帳票の処理概要

DirectoryCoverageReportは、CoverageReportを拡張し、ソースファイルをディレクトリ階層ごとにグループ化してカバレッジサマリーを生成する抽象クラスである。

**業務上の目的・背景**：大規模なプロジェクトでは、数千のソースファイルが存在するため、単純なファイル一覧では全体像を把握しづらい。ディレクトリ単位でのカバレッジサマリーを提供することで、モジュールやコンポーネント単位でのテストカバレッジ状況を俯瞰的に確認できる。これにより、どのサブシステムのテストが不足しているかを容易に特定できる。

**帳票の利用シーン**：大規模プロジェクトのモジュール別カバレッジ評価、サブディレクトリ単位でのテスト進捗確認、階層的なカバレッジレポートの生成時に利用される。

**主要な出力内容**：
1. ディレクトリ階層別のカバレッジサマリー
2. 各ディレクトリ配下のファイル集計
3. サブディレクトリのカバレッジ情報
4. ディレクトリ内ファイルの個別カバレッジ
5. 最長共通プレフィックス（LCP）による冗長パス削除

**帳票の出力タイミング**：llvm-covコマンドでディレクトリ形式出力を指定した場合に生成される。抽象クラスであるため、具体的な出力形式は派生クラスで実装される。

**帳票の利用者**：プロジェクトマネージャー、アーキテクト、QAリード、モジュール責任者

## 帳票種別

階層型集計表

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | コマンドライン | `llvm-cov show/report` | ディレクトリオプション指定 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | 派生クラス依存（HTML/テキスト等） |
| 用紙サイズ | - |
| 向き | - |
| ファイル名 | 派生クラス依存 |
| 出力方法 | ディレクトリ構造に対応した出力 |
| 文字コード | UTF-8 |

### 階層構造仕様

| 項目 | 内容 |
|-----|------|
| ディレクトリ深度 | 無制限（再帰処理） |
| 単一ファイルディレクトリ | スキップ（親に統合） |
| LCP削除 | 共通プレフィックス自動削除 |

## 帳票レイアウト

### レイアウト概要

ディレクトリ階層構造を反映した入れ子構造でカバレッジ情報を表示する。

```
┌─────────────────────────────────────────────────────────────────┐
│ [RootDirectory/]                                                │
│   ├─ [SubDir1/]                                                 │
│   │    ├─ file1.cpp  (Region/Line/Branch Coverage)            │
│   │    └─ file2.cpp  (Region/Line/Branch Coverage)            │
│   │    └─ [SubTotal]                                           │
│   │                                                             │
│   ├─ [SubDir2/]                                                 │
│   │    └─ ...                                                   │
│   │                                                             │
│   └─ [RootTotal]                                                │
└─────────────────────────────────────────────────────────────────┘
```

### ディレクトリエントリ

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | ディレクトリ名 | ディレクトリパス（LCP除去後） | SubDirReports.key | 文字列 |
| 2 | リージョンカバレッジ | ディレクトリ内合計 | FileCoverageSummary集計 | 数値/% |
| 3 | 行カバレッジ | ディレクトリ内合計 | FileCoverageSummary集計 | 数値/% |
| 4 | ブランチカバレッジ | ディレクトリ内合計 | FileCoverageSummary集計 | 数値/% |

### ファイルエントリ

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | ファイル名 | ファイルパス（LCP除去後） | SubFileReports.key | 文字列 |
| 2 | リージョンカバレッジ | 個別ファイル | FileCoverageSummary | 数値/% |
| 3 | 行カバレッジ | 個別ファイル | FileCoverageSummary | 数値/% |
| 4 | ブランチカバレッジ | 個別ファイル | FileCoverageSummary | 数値/% |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| ソースファイル数 | 2ファイル以上 | Yes |
| プロファイルデータ | .profdataファイル | Yes |
| バイナリ | カバレッジマッピング付きバイナリ | Yes |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | ディレクトリ/ファイル名 | 昇順（std::map使用） |

### 階層化条件

- 単一ファイルのサブディレクトリは親ディレクトリに統合
- trivialディレクトリ（非複数エントリ）はスキップ

## データベース参照仕様

### 参照テーブル一覧

本帳票はデータベースを使用せず、バイナリファイル内のカバレッジマッピング情報を参照する。

| データソース | 用途 | 取得方法 |
|-------------|------|---------|
| CoverageMapping | カバレッジマッピング情報 | coverage::CoverageMapping |
| SourceFiles | ソースファイル一覧 | getUniqueSourceFiles() |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| ディレクトリカバレッジ | SubFiles + SubDirs の累積 | 小数点2桁 | 再帰的に集計 |
| LCP長 | getRedundantPrefixLen() | - | 共通パス長 |
| サブLCP | getRedundantPrefixLen(Files, LCP) | - | サブディレクトリ用 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[prepareDirectoryReports呼出] --> B[LCPStack初期化]
    B --> C[prepareSubDirectoryReports開始]
    C --> D{ファイルをグループ化}
    D --> E[直接ファイル: SubFiles]
    D --> F[サブディレクトリ: SubDirs]
    E --> G[prepareSingleFileReport非同期実行]
    F --> H{サブディレクトリ内ファイル数}
    H -->|1ファイル| I[親に統合]
    H -->|複数| J[再帰呼出]
    J --> C
    G --> K[ThreadPool待機]
    I --> K
    K --> L[CurrentTotals計算]
    L --> M[generateSubDirectoryReport呼出]
    M --> N[LCPStack.pop_back]
    N --> O{処理完了?}
    O -->|No| C
    O -->|Yes| P[RootTotals返却]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| ファイル不足 | ソースファイル1以下 | - | CoverageReport使用推奨 |
| 再帰エラー | generateSubDirectoryReport失敗 | Error returned | 処理中断 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 数千〜数万ファイル |
| 目標出力時間 | 数秒〜数十秒 |
| 同時出力数上限 | マルチスレッド対応（ThreadPool） |

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

- ディレクトリ構造がレポートに露出する
- 機密性の高いモジュール構造が可視化される可能性

## 備考

- DirectoryCoverageReportは抽象クラスであり、generateSubDirectoryReport()を派生クラスで実装する必要がある
- テンプレートメソッドパターンを使用

---

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

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

### 推奨読解順序

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

DirectoryCoverageReportで使用されるデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | CoverageReport.h | `llvm/tools/llvm-cov/CoverageReport.h` | SubFileReports, SubDirReportsの型定義（行117-120）を確認 |

**読解のコツ**: SubFileReportsはstd::map<StringRef, FileCoverageSummary>、SubDirReportsはstd::map<StringRef, pair<FileCoverageSummary, SmallVector<StringRef>>>という複雑な型であることを理解する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | CoverageReport.h | `llvm/tools/llvm-cov/CoverageReport.h` | DirectoryCoverageReportクラス（行78-135）の継承関係と仮想関数を確認 |

**主要処理フロー**:
1. **行94-95**: prepareDirectoryReports()がエントリーポイント
2. **行107**: TPoolでスレッドプール参照保持
3. **行114**: LCPStackでディレクトリ深度管理
4. **行128-130**: generateSubDirectoryReport()が純粋仮想関数

#### Step 3: 再帰処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | CoverageReport.cpp | `llvm/tools/llvm-cov/CoverageReport.cpp` | prepareDirectoryReports(), prepareSubDirectoryReports()の実装 |

**主要処理フロー**:
- **行592-612**: prepareDirectoryReports()でルートLCP計算とスレッドプール初期化
- **行618-682**: prepareSubDirectoryReports()の再帰処理
- **行628-647**: ファイルをSubFilesとSubDirsに分類
- **行650-665**: サブディレクトリの再帰処理（単一ファイルは統合）
- **行669-674**: CurrentTotals計算
- **行676-678**: generateSubDirectoryReport()呼出

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

```
DirectoryCoverageReport::prepareDirectoryReports()
    │
    ├─ getRedundantPrefixLen() [LCP計算]
    │
    ├─ ThreadPool初期化
    │
    └─ prepareSubDirectoryReports() [再帰]
           │
           ├─ ファイル/ディレクトリ分類
           │
           ├─ CoverageReport::prepareSingleFileReport() [非同期]
           │
           ├─ prepareSubDirectoryReports() [再帰呼出]
           │
           ├─ TPool->wait()
           │
           ├─ CurrentTotals集計
           │
           └─ generateSubDirectoryReport() [純粋仮想関数]
                  │
                  └─ 派生クラスで実装
```

### データフロー図

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

SourceFiles[] ───────▶ グループ化
                           │
                    ┌──────┴──────┐
                    ▼             ▼
              SubFiles       SubDirs
                    │             │
                    ▼             ▼
          prepareSingleFile   再帰処理
          Report()            prepareSubDirectory
                    │         Reports()
                    │             │
                    └──────┬──────┘
                           ▼
                    CurrentTotals
                           │
                           ▼
              generateSubDirectoryReport()
                           │
                           ▼
              [派生クラスによる出力]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| CoverageReport.h | `llvm/tools/llvm-cov/CoverageReport.h` | ヘッダ | DirectoryCoverageReportクラス定義（行78-135） |
| CoverageReport.cpp | `llvm/tools/llvm-cov/CoverageReport.cpp` | ソース | prepareDirectoryReports, prepareSubDirectoryReportsの実装（行592-682） |
| CoverageSummaryInfo.h | `llvm/tools/llvm-cov/CoverageSummaryInfo.h` | ヘッダ | FileCoverageSummary構造体定義 |
| CoverageFilters.h | `llvm/tools/llvm-cov/CoverageFilters.h` | ヘッダ | CoverageFiltersMatchAllクラス |
