# 機能設計書 37-結合（join、fill）

## 概要

本ドキュメントは、PrettierのDocument Builder APIにおける結合機能について記述する。この機能は、要素を区切り文字で結合し、必要に応じて折り返すDocビルダーを提供する。

### 本機能の処理概要

結合機能は、Prettierの中間表現（Doc）において、複数の要素を区切り文字で結合する機能である。`join`関数は単純な区切り文字挿入を行い、`fill`関数は各行をできるだけ多くの内容で埋めながら折り返しを行う。

**業務上の目的・背景**：コードフォーマットでは、配列要素、関数引数、オブジェクトプロパティなどを区切り文字（カンマ、スペースなど）で結合することが頻繁に必要となる。結合機能により、この共通パターンを簡潔に表現でき、プリンターの実装が簡素化される。また、`fill`機能により、テキストを可能な限り1行に詰め込みながら適切に折り返す処理が可能となる。

**機能の利用シーン**：
- 配列要素をカンマと改行で区切る場合
- 関数引数をカンマとスペースで区切る場合
- インポート文の複数項目を結合する場合
- Markdownテキストを単語ごとに折り返す場合

**主要な処理内容**：
1. join: 配列の各要素間に区切り文字を挿入
2. fill: コンテンツと空白を交互に配置し、行を埋めながら折り返し

**関連システム・外部連携**：Document Printer（printDocToString）

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 14 | Usage - Plugins | 主画面 | プラグイン作成時の結合機能を説明 |
| 26 | Misc - Technical Details | 参照画面 | 結合機能の技術的詳細を説明 |

## 機能種別

Document Builder API / フォーマット制御

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| separator | Doc | Yes（join） | 区切り文字として使用するDoc | 有効なDocであること |
| docs | Doc[] | Yes（join） | 結合する要素の配列 | Doc配列であること |
| parts | Doc[] | Yes（fill） | コンテンツと空白を交互に含む配列 | Doc配列であること |

### 入力データソース

- プリンター関数内でDoc構築時に使用
- builders.joinなどとしてインポート

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| join(separator, docs) | Doc[] | 区切り文字で結合された配列 |
| fill(parts) | Fill | 行埋め込み用Doc |

### 出力先

Doc構造としてDocument Printerに渡される

## 処理フロー

### 処理シーケンス

```
1. join関数の処理
   └─ 配列の各要素間にseparatorを挿入した新しい配列を返却
2. fill関数の処理
   └─ partsをFill Docとしてラップして返却
3. printDocToString関数でDoc処理
   ├─ join結果（配列）はDOC_TYPE_ARRAYとして処理
   └─ fill結果はDOC_TYPE_FILLとして処理
4. DOC_TYPE_FILLの処理
   └─ コンテンツと空白を交互に処理
       ├─ コンテンツがFLATで収まるか判定
       ├─ 次のコンテンツも含めて収まるか判定
       └─ 収まり方に応じてFLAT/BREAKモードを選択
```

### フローチャート

```mermaid
flowchart TD
    A[join/fill呼び出し] --> B{関数は?}
    B -->|join| C[各要素間にseparator挿入]
    B -->|fill| D[Fill Doc生成]
    C --> E[配列を返却]
    D --> F[Fill Doc返却]
    E --> G[printDocToString]
    F --> G
    G --> H{Docタイプは?}
    H -->|DOC_TYPE_ARRAY| I[要素を順に処理]
    H -->|DOC_TYPE_FILL| J[fill処理開始]
    J --> K{残り要素あり?}
    K -->|No| L[処理終了]
    K -->|Yes| M[content取得]
    M --> N[whitespace取得]
    N --> O{contentがFLATで収まる?}
    O -->|Yes| P{content+whitespace+次contentも収まる?}
    O -->|No| Q[contentをBREAKで出力]
    P -->|Yes| R[contentとwhitespaceをFLATで出力]
    P -->|No| S[contentをFLAT、whitespaceをBREAKで出力]
    Q --> K
    R --> K
    S --> K
    I --> L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-37-01 | join配列生成 | 各要素間にseparatorを挿入した配列を生成 | join関数使用時 |
| BR-37-02 | fill構造 | partsはコンテンツと空白を交互に配置 | fill関数使用時 |
| BR-37-03 | fill両方収まる | コンテンツと空白の両方がFLATで収まる場合はFLATで出力 | 両方が残り幅に収まる場合 |
| BR-37-04 | fillコンテンツのみ | コンテンツのみがFLATで収まる場合、コンテンツはFLAT、空白はBREAK | コンテンツのみ収まる場合 |
| BR-37-05 | fill両方収まらない | 両方収まらない場合は両方BREAKで出力 | 両方が収まらない場合 |

### 計算ロジック

join関数:
```javascript
function join(separator, docs) {
  assertDoc(separator);
  assertDocArray(docs);

  const parts = [];
  for (let i = 0; i < docs.length; i++) {
    if (i !== 0) {
      parts.push(separator);
    }
    parts.push(docs[i]);
  }
  return parts;
}
```

fill関数:
```javascript
function fill(parts) {
  assertDocFillParts(parts);
  return { type: DOC_TYPE_FILL, parts };
}
```

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | AssertionError | 不正なseparatorが渡された場合 | 有効なDocを渡す |
| - | AssertionError | 不正なdocs配列が渡された場合 | 有効なDoc配列を渡す |
| - | AssertionError | 不正なparts配列が渡された場合 | 有効なDoc配列（コンテンツと空白を交互）を渡す |

### リトライ仕様

リトライは行わない。

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

本機能はトランザクション管理を必要としない。

## パフォーマンス要件

- join関数は単純な配列操作で軽量
- fill処理は逐次的に収まり判定を行い、必要最小限の計算

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

特になし

## 備考

- joinはDoc配列を返し、fillはFill Docを返す
- fillの partsは「コンテンツ, 空白, コンテンツ, 空白, ...」の形式

---

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

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

### 推奨読解順序

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

結合Docの型定義と構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | join.js | `src/document/builders/join.js` | join関数の実装 |
| 1-2 | fill.js | `src/document/builders/fill.js` | Fill型定義、fill関数 |

**読解のコツ**:
- `join`は配列を返す（DOC_TYPE_ARRAYとして処理される）
- `fill`は`{ type: DOC_TYPE_FILL, parts }`を返す

#### Step 2: ビルダー関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | join.js | `src/document/builders/join.js` | join関数の実装 |
| 2-2 | fill.js | `src/document/builders/fill.js` | fill関数の実装 |

**主要処理フロー**:
1. **join.js 12-27行目**: join関数 - separatorとdocsを検証し、要素間にseparatorを挿入
2. **fill.js 16-19行目**: fill関数 - partsを検証してFill Docを生成

#### Step 3: プリンターでの処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | printer.js | `src/document/printer/printer.js` | DOC_TYPE_FILL処理 |

**主要処理フロー**:
- **343-433行目**: DOC_TYPE_FILL処理
- **346-351行目**: 残り要素の確認と終了条件
- **353-354行目**: contentとwhitespaceの取得
- **359-366行目**: contentFitsの判定（fits関数）
- **368-375行目**: 要素が1つの場合の処理
- **390-397行目**: 要素が2つの場合の処理
- **414-431行目**: 3つ以上の要素の場合 - 次のコンテンツも含めて判定

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

```
builders.join (join.js:12)
    │
    └─ assertDoc / assertDocArray → 配列生成
           │
           └─ printDocToString (printer.js:179)
                  │
                  └─ DOC_TYPE_ARRAY処理 (printer.js:215)
                         │
                         └─ 各要素を順に処理

builders.fill (fill.js:16)
    │
    └─ assertDocFillParts → Fill Doc生成
           │
           └─ printDocToString (printer.js:179)
                  │
                  └─ DOC_TYPE_FILL処理 (printer.js:343)
                         │
                         ├─ content取得
                         │
                         ├─ whitespace取得
                         │
                         ├─ fits関数でcontentFits判定
                         │
                         └─ fits関数でfirstAndSecondContentFits判定
                                │
                                ├─ [両方収まる] → FLAT出力
                                │
                                ├─ [contentのみ] → content FLAT、whitespace BREAK
                                │
                                └─ [両方収まらない] → 両方BREAK
```

### データフロー図

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

separator            join                            Doc配列
docs[] ─────────────▶ separatorを各要素間に挿入 ────▶
                            │
                            ▼
                     printDocToString
                            │
                            ▼
                     DOC_TYPE_ARRAY処理
                            │
                            ▼
                     各要素を順に出力


parts[]              fill                            Fill Doc
 ─────────────────▶ Fill Doc生成 ──────────────────▶
                            │
                            ▼
                     printDocToString
                            │
                            ▼
                     DOC_TYPE_FILL処理
                            │
              ┌─────────────┴─────────────┐
              │                           │
         [content]                  [whitespace]
              │                           │
              ▼                           ▼
         fits判定                    fits判定
              │                           │
              └─────────────┬─────────────┘
                            │
                            ▼
                   モード決定 & 出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| join.js | `src/document/builders/join.js` | ソース | join関数の定義 |
| fill.js | `src/document/builders/fill.js` | ソース | fill関数の定義 |
| types.js | `src/document/builders/types.js` | ソース | DOC_TYPE_FILL定数 |
| index.js | `src/document/builders/index.js` | ソース | ビルダーのエクスポート |
| public.js | `src/document/public.js` | ソース | 公開APIのエクスポート |
| printer.js | `src/document/printer/printer.js` | ソース | DOC_TYPE_FILL処理 |
| assert-doc.js | `src/document/utilities/assert-doc.js` | ソース | Docアサーション関数 |
