# 機能設計書 54-@babel/plugin-transform-named-capturing-groups-regex

## 概要

本ドキュメントは、Babelプラグイン `@babel/plugin-transform-named-capturing-groups-regex` の機能設計を記載したものである。本プラグインは、ES2018で導入された名前付きキャプチャグループ（`(?<name>...)`）を使用した正規表現をES5互換の正規表現に変換する。

### 本機能の処理概要

**業務上の目的・背景**：従来の正規表現では、キャプチャグループは番号（`$1`, `$2` など）でしか参照できなかった。ES2018で導入された名前付きキャプチャグループを使用すると、`(?<year>\d{4})` のように名前を付けて、`match.groups.year` で参照できるようになる。しかし、古いJavaScript実行環境ではこの構文がサポートされていないため、トランスパイルが必要となる。本プラグインは、名前付きキャプチャグループを使用した正規表現を、番号によるキャプチャグループに変換し、必要に応じてランタイムヘルパーで名前付きアクセスを提供する。

**機能の利用シーン**：
- 日付パターン（`/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/`）のようなデータ抽出
- URLやファイルパスからの部分抽出
- ログ解析などでの構造化データ抽出
- コードの可読性向上（番号より名前の方が理解しやすい）

**主要な処理内容**：
1. AST内のRegExpLiteralノードを検出
2. 名前付きキャプチャグループ（`(?<name>...)`）を含む正規表現を識別
3. `regexpu-core` ライブラリを使用してパターンを変換
4. `runtime` オプションがtrueの場合、`_wrapRegExp` ヘルパーで正規表現をラップし、名前付きアクセスを提供
5. `regexp.test()` の呼び出しではヘルパーラップをスキップ（名前付きアクセス不要なため）

**関連システム・外部連携**：`@babel/helper-create-regexp-features-plugin` を使用して正規表現機能変換の共通処理を実行。`@babel/runtime` の `wrapRegExp` ヘルパーを使用してランタイムでの名前付きアクセスを提供。

**権限による制御**：本プラグインに権限制御の概念は存在しない。

## 関連画面

該当なし（CLIツール/ビルドツールとして動作）

## 機能種別

データ変換処理（ASTトランスフォーム）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| runtime | boolean | No | ランタイムヘルパーを使用して名前付きアクセスを提供するか（デフォルト: true） | boolean型でなければエラー |

### 入力データソース

- Babelコアから渡されるAST（抽象構文木）
- `RegExpLiteral` ノードが処理対象

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 変換後AST | AST Node | 名前付きキャプチャグループが変換された正規表現リテラル、またはwrapRegExp呼び出し |

### 出力先

変換されたASTはBabelコアに返され、最終的にJavaScriptコードとして出力される

## 処理フロー

### 処理シーケンス

```
1. プラグイン初期化
   └─ runtime オプションの検証と取得（デフォルト: true）

2. createRegExpFeaturePlugin 呼び出し
   └─ プラグイン名: "transform-named-capturing-groups-regex"
   └─ 機能フラグ: "namedCaptureGroups"
   └─ options: { runtime }

3. pre フック実行（ファイル処理開始時）
   └─ featuresKey に機能フラグを設定
   └─ runtimeKey にruntime設定を保存

4. RegExpLiteral ノード訪問
   └─ 名前付きキャプチャグループの有無を判定
   └─ regexpu-core でパターン変換
   └─ 名前とインデックスのマッピングを収集
   └─ runtime=true かつ .test() 以外の使用: wrapRegExp でラップ
```

### フローチャート

```mermaid
flowchart TD
    A[RegExpLiteral検出] --> B{(?<name>...)あり?}
    B -->|No| Z[スキップ]
    B -->|Yes| C[regexpu-coreで変換]
    C --> D[名前→インデックスマッピング収集]
    D --> E{runtime=true?}
    E -->|No| H[パターン変換のみ]
    E -->|Yes| F{.test呼び出し?}
    F -->|Yes| H
    F -->|No| G[wrapRegExpでラップ]
    G --> I[変換完了]
    H --> I
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 名前付きグループ変換 | `(?<name>...)` を `(...)` に変換 | 名前付きキャプチャグループ使用時 |
| BR-02 | ランタイムラップ | wrapRegExpヘルパーで正規表現をラップ | runtime=true かつ test()以外 |
| BR-03 | testスキップ | regexp.test() 使用時はヘルパーラップをスキップ | test()メソッド呼び出し |
| BR-04 | マッピング生成 | 名前からインデックスへのマッピングオブジェクト生成 | ヘルパーラップ時 |

### 計算ロジック

名前付きキャプチャグループの変換時、`regexpu-core` の `onNamedGroup` コールバックで名前とインデックスのマッピングを収集。同名グループが複数ある場合は配列として管理。

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Error | runtime オプションが boolean 以外 | エラーメッセージ表示、処理中断 |
| - | SyntaxError | 不正な正規表現パターン | Babelコアがエラー報告 |

### リトライ仕様

該当なし

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

該当なし（ステートレスな変換処理）

## パフォーマンス要件

- `canSkipRegexpu` による早期スキップで不要な変換を回避
- `isRegExpTest` による最適化で、test() 呼び出し時のヘルパー追加を回避

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

- 特になし

## 備考

- ES2018以降をネイティブサポートする環境ではこのプラグインは不要
- `@babel/preset-env` 使用時は、ターゲット環境に応じて自動的に適用される
- runtime=false にすると、名前付きアクセス（match.groups.name）は利用不可になるが、コードサイズが削減される

---

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

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

### 推奨読解順序

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

正規表現機能プラグインで使用される機能フラグの定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | features.ts | `packages/babel-helper-create-regexp-features-plugin/src/features.ts` | FEATURESオブジェクトで定義される機能フラグ（namedCaptureGroups = 1 << 3）とruntimeKeyを確認 |

**読解のコツ**: `runtimeKey` は複数のプラグイン間で runtime オプションを共有するために使用される。

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

プラグインの初期化処理とオプション検証を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/babel-plugin-transform-named-capturing-groups-regex/src/index.ts` | プラグイン定義とruntimeオプション処理 |

**主要処理フロー**:
1. **5-7行目**: Options インターフェース定義（runtime?: boolean）
2. **9-13行目**: runtime オプションの検証
3. **15-19行目**: `createRegExpFeaturePlugin` の呼び出し

#### Step 3: ヘルパープラグインのコア処理を理解する

名前付きキャプチャグループの変換ロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.ts | `packages/babel-helper-create-regexp-features-plugin/src/index.ts` | namedCaptureGroupsの変換処理 |
| 3-2 | util.ts | `packages/babel-helper-create-regexp-features-plugin/src/util.ts` | パターンチェックロジック |

**主要処理フロー**:
- **55-65行目（index.ts）**: runtimeオプションの処理とruntimeKeyへの設定
- **86-98行目（index.ts）**: onNamedGroup コールバックで名前とインデックスのマッピング収集
- **110-123行目（index.ts）**: runtime=true時のwrapRegExpヘルパー呼び出し
- **131-137行目（index.ts）**: isRegExpTest関数でtest()メソッド呼び出しを判定
- **69-71行目（util.ts）**: `\(\?<(?![=!])` パターンで名前付きグループを検出

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

```
@babel/plugin-transform-named-capturing-groups-regex
    │
    └─ createRegExpFeaturePlugin (helper)
           │
           ├─ pre(): namedCaptureGroups, runtime設定
           │
           └─ visitor.RegExpLiteral()
                  │
                  ├─ generateRegexpuOptions()
                  │      └─ namedGroups: "transform"
                  │      └─ onNamedGroup: コールバック設定
                  │
                  ├─ canSkipRegexpu(): (?<...>)チェック
                  │
                  ├─ rewritePattern() [regexpu-core]
                  │      └─ パターン変換、名前マッピング収集
                  │
                  ├─ isRegExpTest(): .test()チェック
                  │
                  └─ [runtime=true && !test]
                         └─ wrapRegExp(node, mapping)
```

### データフロー図

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

ソースコード           @babel/parser                     変換後コード
/(?<year>\d{4})/  ───▶  RegExpLiteral AST  ───▶  Visitor  ───▶  _wrapRegExp(
                                                    │              /(\d{4})/,
                                              regexpu-core           {year: 1}
                                           (パターン変換)            )
                                              onNamedGroup
                                           (マッピング収集)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/babel-plugin-transform-named-capturing-groups-regex/src/index.ts` | ソース | プラグインエントリーポイント |
| package.json | `packages/babel-plugin-transform-named-capturing-groups-regex/package.json` | 設定 | パッケージ定義、依存関係 |
| index.ts | `packages/babel-helper-create-regexp-features-plugin/src/index.ts` | ソース | 正規表現機能プラグイン共通処理、wrapRegExp呼び出し |
| features.ts | `packages/babel-helper-create-regexp-features-plugin/src/features.ts` | ソース | 機能フラグ定義、runtimeKey |
| util.ts | `packages/babel-helper-create-regexp-features-plugin/src/util.ts` | ソース | ユーティリティ関数 |
