# 機能設計書 34-行制御（line、softline、hardline）

## 概要

本ドキュメントは、PrettierのDocument Builder APIにおける行制御機能について記述する。この機能は、フォーマット出力における行の折り返しと改行を制御するDocビルダーを提供する。

### 本機能の処理概要

行制御は、Prettierの中間表現（Doc）において、行の折り返しと改行を制御する機能である。`line`、`softline`、`hardline`、`literalline`の4種類の行制御Docを提供し、それぞれ異なる改行動作を実現する。これらは、グループ内でのモード（FLAT/BREAK）に応じて動作が変化する。

**業務上の目的・背景**：コードフォーマットでは、1行に収まる場合と複数行に分割する場合で異なる出力が必要となる。例えば、短い配列は1行で`[1, 2, 3]`と出力し、長い配列は複数行に分割する。行制御機能はこの動的な出力切り替えを可能にし、printWidth内に収まる最適なフォーマットを実現する。

**機能の利用シーン**：
- 配列やオブジェクトの要素間に改行を入れる場合
- 関数引数リストを複数行に分割する場合
- ブロック文の開始・終了時に改行を強制する場合
- 文字列リテラル内の改行を保持する場合

**主要な処理内容**：
1. line: グループがBREAKモードの場合は改行、FLATモードの場合はスペース
2. softline: グループがBREAKモードの場合は改行、FLATモードの場合は何も出力しない
3. hardline: 常に改行を出力し、親グループをBREAKモードに強制
4. literalline: 常に改行を出力し、インデントをリセット

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

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 14 | Usage - Plugins | 主画面 | プラグイン作成時のDocビルダー使用方法を説明 |
| 26 | Misc - Technical Details | 参照画面 | Docビルダーの技術的詳細を説明 |

## 機能種別

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

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| - | - | - | line、softline、hardline、literallineは定数として提供され、パラメータ不要 | - |

### 入力データソース

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

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| line | Line | 通常の行区切りDoc |
| softline | SoftLine | ソフトな行区切りDoc |
| hardline | HardLine | 強制改行Doc（breakParent付き） |
| literalline | Literalline | リテラル改行Doc（breakParent付き） |
| hardlineWithoutBreakParent | HardlineWithoutBreakParent | breakParentなし強制改行Doc |
| literallineWithoutBreakParent | LiterallineWithoutBreakParent | breakParentなしリテラル改行Doc |

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. プリンター関数でDoc構築時にline/softline/hardline/literallineを使用
2. printDocToString関数でDoc処理時に行制御を評価
3. モード（FLAT/BREAK）に応じて出力を決定
   ├─ line: FLATモード→スペース、BREAKモード→改行
   ├─ softline: FLATモード→空文字、BREAKモード→改行
   ├─ hardline: 常に改行（親グループをBREAKに強制）
   └─ literalline: 常に改行（インデントリセット）
4. 必要に応じてインデントを適用
5. 出力文字列に書き込み
```

### フローチャート

```mermaid
flowchart TD
    A[Doc処理開始] --> B{Docタイプは?}
    B -->|DOC_TYPE_LINE| C{hard属性あり?}
    C -->|Yes| D{literal属性あり?}
    C -->|No| E{モードは?}
    D -->|Yes| F[literalline処理]
    D -->|No| G[hardline処理]
    E -->|FLAT| H{soft属性あり?}
    E -->|BREAK| I[改行出力]
    H -->|Yes| J[何も出力しない]
    H -->|No| K[スペース出力]
    F --> L[改行出力+インデントリセット]
    G --> L2[改行出力+インデント適用]
    I --> L2
    J --> M[次のDoc処理]
    K --> M
    L --> M
    L2 --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-34-01 | FLATモード時line動作 | lineはスペースを出力 | グループがFLATモードの場合 |
| BR-34-02 | BREAKモード時line動作 | lineは改行を出力 | グループがBREAKモードの場合 |
| BR-34-03 | FLATモード時softline動作 | softlineは何も出力しない | グループがFLATモードの場合 |
| BR-34-04 | hardline強制 | hardlineは常に改行し、親グループをBREAKに強制 | 常に |
| BR-34-05 | literallineインデント | literallineは改行後にインデントをリセット | 常に |
| BR-34-06 | breakParent伝播 | hardline/literallineはbreakParentを含み、親グループに伝播 | 常に |

### 計算ロジック

Docタイプの定義:
```javascript
const line = { type: DOC_TYPE_LINE };
const softline = { type: DOC_TYPE_LINE, soft: true };
const hardlineWithoutBreakParent = { type: DOC_TYPE_LINE, hard: true };
const hardline = [hardlineWithoutBreakParent, breakParent];
const literallineWithoutBreakParent = { type: DOC_TYPE_LINE, hard: true, literal: true };
const literalline = [literallineWithoutBreakParent, breakParent];
```

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | InvalidDocError | 不正なDocが渡された場合 | Docの構造を確認 |

### リトライ仕様

リトライは行わない。

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

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

## パフォーマンス要件

- 行制御Docは事前定義されたオブジェクト定数として提供され、生成コストなし
- hardline/literallineはbreakParentとの配列として事前構築済み

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

特になし

## 備考

- hardlineWithoutBreakParent/literallineWithoutBreakParentは特殊なケースで使用
- breakParentは親グループをBREAKモードに強制するDoc

---

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

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

### 推奨読解順序

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

行制御Docの型定義と構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | line.js | `src/document/builders/line.js` | Line、SoftLine、HardLine等の型定義と定数 |
| 1-2 | types.js | `src/document/builders/types.js` | DOC_TYPE_LINE定数 |

**読解のコツ**:
- `line`は最もシンプルな形式で`{ type: DOC_TYPE_LINE }`
- `softline`は`soft: true`プロパティを持つ
- `hardline`は`hard: true`プロパティを持ち、`breakParent`との配列

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | public.js | `src/document/public.js` | buildersオブジェクトでのエクスポート |

**主要処理フロー**:
1. **39-66行目**: buildersオブジェクトで各行制御Docをエクスポート
2. **41-44行目**: line、softline、hardline、literallineのエクスポート

#### Step 3: 行制御Docの定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | line.js | `src/document/builders/line.js` | 各行制御Docの定義 |

**主要処理フロー**:
- **21行目**: `line`定数の定義
- **23行目**: `softline`定数の定義（soft: true）
- **25行目**: `hardlineWithoutBreakParent`定数の定義（hard: true）
- **27行目**: `hardline`定数の定義（breakParentとの配列）
- **29-33行目**: `literallineWithoutBreakParent`定数の定義（hard: true, literal: true）
- **35行目**: `literalline`定数の定義（breakParentとの配列）

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | printer.js | `src/document/printer/printer.js` | printDocToString関数でのDOC_TYPE_LINE処理 |

**主要処理フロー**:
- **148-155行目**: fits関数でのline処理（BREAKモード/hardの場合true返却）
- **472-516行目**: printDocToString関数でのDOC_TYPE_LINE処理
- **474-482行目**: FLATモードでのline処理（hardでなければスペースまたは空文字）
- **493-514行目**: BREAKモードでのline処理（改行とインデント出力）

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

```
builders.line / builders.softline / builders.hardline / builders.literalline
    │
    └─ プリンター関数内でDoc構築
           │
           └─ printDocToString (printer.js:179)
                  │
                  └─ DOC_TYPE_LINE処理 (printer.js:472)
                         │
                         ├─ [FLAT + !hard]
                         │      │
                         │      ├─ [!soft] → スペース出力 (477-478行目)
                         │      └─ [soft] → 何も出力しない
                         │
                         ├─ [FLAT + hard] → shouldRemeasure = true (489行目)
                         │
                         └─ [BREAK]
                                │
                                ├─ [lineSuffixあり] → lineSuffix処理 (494-497行目)
                                │
                                ├─ [literal] → 改行 + rootインデント (500-508行目)
                                │
                                └─ [!literal] → trim + 改行 + インデント (510-512行目)
```

### データフロー図

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

line/softline        printDocToString                  フォーマット文字列
hardline/literalline ────▶ DOC_TYPE_LINE処理 ────────▶
                              │
                    ┌─────────┴─────────┐
                    │                   │
               [FLATモード]         [BREAKモード]
                    │                   │
            ┌───────┴───────┐           │
            │               │           │
         [line]         [softline]      │
            │               │           │
            ▼               ▼           ▼
         スペース          空文字      改行+インデント
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| line.js | `src/document/builders/line.js` | ソース | 行制御Docの定義 |
| break-parent.js | `src/document/builders/break-parent.js` | ソース | breakParent Docの定義 |
| types.js | `src/document/builders/types.js` | ソース | Doc型定数の定義 |
| index.js | `src/document/builders/index.js` | ソース | ビルダーのエクスポート |
| public.js | `src/document/public.js` | ソース | 公開APIのエクスポート |
| printer.js | `src/document/printer/printer.js` | ソース | Doc処理とフォーマット出力 |
