# 機能設計書 47-jest-docblock

## 概要

本ドキュメントは、jest-docblockパッケージの機能設計について記載する。jest-docblockは、ファイル先頭のdocblockコメントを解析・生成する機能を提供するパッケージである。

### 本機能の処理概要

jest-docblockは、JavaScript/TypeScriptファイルの先頭に記述されるdocblockコメント（/\*\* ... \*/形式）を解析し、@タグ形式のプラグマ（ディレクティブ）を抽出する。また、プラグマからdocblockを生成する機能も提供する。

**業務上の目的・背景**：Jestでは、テストファイルの先頭にdocblockを記述することで、テストごとの設定をインラインで指定できる。例えば、@jest-environmentでテスト環境を指定したり、@timeoutでタイムアウト値を設定したりできる。jest-docblockは、このようなdocblock形式の設定を解析するための基盤を提供する。

**機能の利用シーン**：テストファイルの読み込み時に@jest-environment等のプラグマを抽出するために使用される。また、jest-hasteでのモジュール名の抽出（@providesModule）にも活用される。

**主要な処理内容**：
1. extract: ファイル内容からdocblock部分を抽出
2. strip: ファイル内容からdocblock部分を削除
3. parse: docblockからプラグマ（キー・値のペア）を抽出
4. parseWithComments: プラグマとコメントの両方を抽出
5. print: プラグマからdocblock文字列を生成

**関連システム・外部連携**：detect-newlineパッケージを使用して改行コードを検出。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | CLIのみで使用される機能のため関連画面なし |

## 機能種別

テキスト解析 / コメント処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| contents | string | Yes | ファイル内容 | - |
| docblock | string | Yes | docblock文字列（parse/parseWithComments/print用） | - |
| options.comments | string | No | コメント部分（print用） | - |
| options.pragmas | Pragmas | No | プラグマオブジェクト（print用） | - |

### 入力データソース

- ソースファイルの内容

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| docblock | string | 抽出されたdocblock文字列（extract） |
| contents | string | docblock除去後の内容（strip） |
| pragmas | Pragmas | プラグマオブジェクト（parse） |
| result | {comments, pragmas} | コメントとプラグマ（parseWithComments） |
| printed | string | 生成されたdocblock文字列（print） |

### 出力先

- 呼び出し元への戻り値

## 処理フロー

### 処理シーケンス

```
1. extract呼び出し
   └─ docblockRe正規表現でdocblock部分をマッチ
2. strip呼び出し
   └─ docblockRe正規表現でdocblock部分を削除
3. parse/parseWithComments呼び出し
   └─ コメント記号を除去
   └─ multilineReでマルチライン@タグを正規化
   └─ propertyReで@タグと値を抽出
4. print呼び出し
   └─ コメントとプラグマを結合してdocblock形式で出力
```

### フローチャート

```mermaid
flowchart TD
    A[ファイル内容] --> B{extract?}
    B -->|Yes| C[docblockRe マッチ]
    C --> D[docblock返却]
    B -->|No| E{strip?}
    E -->|Yes| F[docblockRe 削除]
    F --> G[残りの内容返却]
    E -->|No| H{parse/parseWithComments?}
    H -->|Yes| I[コメント記号除去]
    I --> J[multilineRe 正規化]
    J --> K[propertyRe 抽出]
    K --> L[pragmas返却]
    H -->|No| M{print?}
    M -->|Yes| N[コメント整形]
    N --> O[プラグマ整形]
    O --> P[docblock生成]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-47-01 | 複数値対応 | 同じ@タグが複数ある場合は配列として返却 | parse時 |
| BR-47-02 | 行コメント除去 | @タグの値から//以降のコメントを除去 | parse時 |
| BR-47-03 | 単一プラグマ短縮 | プラグマが1つでコメントがない場合は1行形式で出力 | print時 |
| BR-47-04 | 改行コード保持 | 入力の改行コードを検出して出力に使用 | parse/print時 |

### 計算ロジック

docblock抽出正規表現:
```
docblockRe = /^\s*(\/\*\*?(.|\r?\n)*?\*\/)/
```

プラグマ抽出正規表現:
```
propertyRe = /(?:^|\r?\n) *@(\S+) *([^\n\r]*)/g
```

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

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

該当なし（データベース操作は行わない）

## エラー処理

### エラーケース一覧

該当なし（エラーは発生しない、不正な入力は空文字列/空オブジェクトを返却）

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- 解析処理: ミリ秒以下

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

- ファイル内容をパースするのみで、外部への通信や副作用はない

## 備考

- docblockは/\*\*で始まり\*/で終わる形式
- シングル\*のコメント(/\* ... \*/)もサポート

---

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

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

### 推奨読解順序

#### Step 1: 正規表現を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.ts | `packages/jest-docblock/src/index.ts` | 正規表現定義（13-21行目） |

**読解のコツ**: 各正規表現の役割を理解することが解析ロジックの理解に重要。

**主要な正規表現**:
- **13行目**: commentEndRe - コメント終端検出
- **14行目**: commentStartRe - コメント開始検出
- **15行目**: docblockRe - docblock全体マッチ
- **16行目**: lineCommentRe - 行コメント検出
- **18-19行目**: multilineRe - マルチライン@タグ正規化
- **20行目**: propertyRe - @タグ抽出

#### Step 2: extract/stripを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/jest-docblock/src/index.ts` | extract/strip関数（24-33行目） |

**主要処理フロー**:
- **24-27行目**: extract - docblockReでマッチしてtrimStart()
- **29-33行目**: strip - マッチ部分をslice()で除去

#### Step 3: parse/parseWithCommentsを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.ts | `packages/jest-docblock/src/index.ts` | parse関数（35-83行目） |

**主要処理フロー**:
- **35-37行目**: parse - parseWithCommentsを呼び出してpragmasのみ返却
- **39-83行目**: parseWithComments - 詳細な解析処理
- **45-48行目**: コメント記号と*の除去
- **51-55行目**: マルチライン@タグの正規化ループ
- **65-81行目**: @タグの抽出と複数値対応

#### Step 4: print関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | index.ts | `packages/jest-docblock/src/index.ts` | print関数（85-128行目） |

**主要処理フロー**:
- **92-95行目**: ヘッダ/開始/終端の定数
- **97-102行目**: プラグマの整形
- **104-111行目**: 空または単一プラグマの短縮形式
- **114-127行目**: 完全形式のdocblock生成

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

```
extract(contents)
    └─ contents.match(docblockRe)

strip(contents)
    └─ contents.match(docblockRe)
           └─ contents.slice(match.length)

parse(docblock)
    └─ parseWithComments(docblock).pragmas

parseWithComments(docblock)
    ├─ detectNewline(docblock) → 改行コード検出
    ├─ docblock.replace(commentStartRe, '') → コメント開始除去
    ├─ docblock.replace(commentEndRe, '') → コメント終端除去
    ├─ docblock.replaceAll(stringStartRe, '$1') → *除去
    ├─ docblock.replaceAll(multilineRe, ...) → マルチライン正規化
    └─ propertyRe.exec(docblock) → @タグ抽出ループ

print({comments, pragmas})
    ├─ printKeyValues(key, value) → @キー 値 形式
    └─ コメント整形 + プラグマ整形 → docblock文字列
```

### データフロー図

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

ファイル内容 ────────────▶ extract() ─────────────────▶ docblock文字列
                              │
                              └─ docblockRe.match()

ファイル内容 ────────────▶ strip() ──────────────────▶ docblock除去後の内容
                              │
                              └─ docblockRe.match()
                                     └─ contents.slice()

docblock文字列 ──────────▶ parseWithComments() ──────▶ {comments, pragmas}
                              │
                              ├─ コメント記号除去
                              ├─ マルチライン正規化
                              └─ @タグ抽出

{comments, pragmas} ─────▶ print() ──────────────────▶ docblock文字列
                              │
                              ├─ printKeyValues()
                              └─ フォーマット結合
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/jest-docblock/src/index.ts` | ソース | メイン処理 |
| __tests__/index.test.ts | `packages/jest-docblock/src/__tests__/index.test.ts` | テスト | ユニットテスト |
