# 機能設計書 63-インデントサイズ計算

## 概要

本ドキュメントは、Prettierのコードフォーマッタにおける「インデントサイズ計算」機能の設計を記述する。この機能は、タブ幅を考慮したインデントサイズを計算するための2つのユーティリティ関数（getAlignmentSize、getIndentSize）を提供する。

### 本機能の処理概要

**業務上の目的・背景**：コードフォーマットにおいて、インデントの正確な計算は非常に重要である。特にタブ文字を含む場合、タブは固定幅ではなく次のタブストップまでの幅として計算される必要がある。getAlignmentSizeとgetIndentSizeは、このタブの特殊な挙動を考慮した正確なインデント幅計算を提供し、範囲フォーマットやインデント保持機能を支える基盤となる。

**機能の利用シーン**：
- 範囲フォーマット時のインデント保持（rangeFormat処理）
- タブとスペースの混在したインデントの正規化
- インデントレベルの算出
- Documentのalign機能でのインデント計算
- プリンターでのインデント幅計算

**主要な処理内容**：
1. **getAlignmentSize**: 文字列とタブ幅を受け取り、タブストップを考慮した累積幅を計算
2. **getIndentSize**: 最後の改行以降の先頭空白部分のインデント幅を計算

**関連システム・外部連携**：
- core.js: formatRange関数でインデント計算に使用
- Documentプリンター: align計算で使用

**権限による制御**：特になし（内部ユーティリティ関数）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 26 | Misc - Technical Details | 補助機能 | インデントサイズ計算の技術的詳細を説明 |

## 機能種別

計算処理 / ユーティリティ

## 入力仕様

### 入力パラメータ

#### getAlignmentSize

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| text | string | Yes | インデント文字列 | タブとスペースを含む文字列 |
| tabWidth | number | Yes | タブ幅 | 正の整数 |
| startIndex | number | No | 開始位置 | デフォルト: 0 |

#### getIndentSize

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| value | string | Yes | 解析対象文字列 | 改行を含む可能性のある文字列 |
| tabWidth | number | Yes | タブ幅 | 正の整数 |

### 入力データソース

- フォーマット処理中の文字列
- 範囲フォーマット時のインデント文字列

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| size | number | 計算されたインデント幅（スペース換算） |

### 出力先

- 呼び出し元への戻り値

## 処理フロー

### 処理シーケンス

#### getAlignmentSize

```
1. サイズを0で初期化
2. startIndexから文字列末尾までループ
   └─ タブ文字の場合
      └─ サイズを次のタブストップ位置に調整（tabWidth - (size % tabWidth)を加算）
   └─ その他の文字の場合
      └─ サイズを1増加
3. 最終サイズを返す
```

#### getIndentSize

```
1. 最後の改行位置を検索
   └─ 改行がない場合は0を返す
2. 改行以降の先頭空白部分を正規表現で抽出
3. 抽出した空白にgetAlignmentSizeを適用
4. 結果を返す
```

### フローチャート

```mermaid
flowchart TD
    subgraph getAlignmentSize
        A1[開始] --> B1[size = 0, i = startIndex]
        B1 --> C1{i < text.length?}
        C1 -->|Yes| D1{text[i] === '\t'?}
        D1 -->|Yes| E1[size += tabWidth - size % tabWidth]
        D1 -->|No| F1[size += 1]
        E1 --> G1[i++]
        F1 --> G1
        G1 --> C1
        C1 -->|No| H1[return size]
    end

    subgraph getIndentSize
        A2[開始] --> B2[lastNewlineIndex = value.lastIndexOf'\n']
        B2 --> C2{lastNewlineIndex === -1?}
        C2 -->|Yes| D2[return 0]
        C2 -->|No| E2[indentString = 改行後の先頭空白を抽出]
        E2 --> F2[return getAlignmentSize indentString, tabWidth]
    end
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-63-01 | タブストップ計算 | タブは次のtabWidth倍数位置まで移動する | タブ文字が含まれる場合 |
| BR-63-02 | スペース幅 | スペースは常に1幅 | 全角スペースも1幅として扱う |
| BR-63-03 | 改行なしの場合 | getIndentSizeは0を返す | 改行が存在しない場合 |
| BR-63-04 | 先頭空白のみ対象 | getIndentSizeは先頭のタブ/スペースのみ計算 | 改行後の文字列に対して |

### 計算ロジック

#### タブストップ計算例（tabWidth=4の場合）

```
位置 0: タブ → サイズ 4 (0 + 4 - 0%4 = 4)
位置 4: タブ → サイズ 8 (4 + 4 - 4%4 = 8)
位置 1: タブ → サイズ 4 (1 + 4 - 1%4 = 4)
位置 2: タブ → サイズ 4 (2 + 4 - 2%4 = 4)
位置 3: タブ → サイズ 4 (3 + 4 - 3%4 = 4)
```

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

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

本機能はデータベース操作を伴わない。

### テーブル別操作詳細

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | - | 本機能では例外を発生させない | - |

### リトライ仕様

該当なし

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

該当なし（データベース操作なし）

## パフォーマンス要件

- 線形時間（O(n)）で処理を完了する
- 余分なメモリ割り当てを最小限に抑える

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

- 特別なセキュリティ要件なし
- 入力文字列に対する副作用なし

## 備考

- getAlignmentSizeはgetIndentSizeの内部で使用される
- 両関数ともプラグイン開発者向けにutilモジュールから公開されている

---

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

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

### 推奨読解順序

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

関数シグネチャを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | get-alignment-size.js | `src/utilities/get-alignment-size.js` | getAlignmentSize関数のシグネチャ |
| 1-2 | get-indent-size.js | `src/utilities/get-indent-size.js` | getIndentSize関数のシグネチャ |

**読解のコツ**: JSDocコメントで型情報が明記されている。startIndexはオプションパラメータ。

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

公開APIとしてのエクスポート構造を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | public.js | `src/utilities/public.js` | エクスポート定義 |

**主要処理フロー**:
- **141行目**: `export { default as getAlignmentSize } from "./get-alignment-size.js";`
- **142行目**: `export { default as getIndentSize } from "./get-indent-size.js";`

#### Step 3: getAlignmentSizeの実装を理解する

タブストップ計算のロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | get-alignment-size.js | `src/utilities/get-alignment-size.js` | タブストップ計算ロジック |

**主要処理フロー**:
- **7行目**: 関数定義、startIndexのデフォルト値0
- **8-18行目**: メインループ
- **10-15行目**: タブ文字の場合の計算（次のタブストップへ）
- **16-17行目**: その他の文字の場合（+1）

#### Step 4: getIndentSizeの実装を理解する

改行後のインデント計算ロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | get-indent-size.js | `src/utilities/get-indent-size.js` | インデント抽出ロジック |

**主要処理フロー**:
- **1行目**: getAlignmentSizeのインポート
- **9行目**: lastIndexOfで最後の改行を検索
- **11-13行目**: 改行がない場合は0を返す
- **15-18行目**: 改行後の先頭空白を抽出してgetAlignmentSizeを呼び出す

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

```
getIndentSize (get-indent-size.js)
    │
    └─ getAlignmentSize (get-alignment-size.js)
           └─ タブストップ計算ループ

formatRange (core.js)
    │
    └─ getAlignmentSize (get-alignment-size.js)
           └─ インデント幅計算
```

### データフロー図

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

getAlignmentSize:
text ─────────────────▶ ループ処理 ────────────────────▶ size (number)
tabWidth                    │
startIndex                  └── タブ/スペース判定

getIndentSize:
value ────────────────▶ 改行検索 ──────────────────────▶ 0 (改行なし)
tabWidth                    │
                            └── 空白抽出
                                   │
                                   └── getAlignmentSize ─▶ size (number)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| get-alignment-size.js | `src/utilities/get-alignment-size.js` | ソース | タブストップ計算 |
| get-indent-size.js | `src/utilities/get-indent-size.js` | ソース | インデントサイズ計算 |
| public.js | `src/utilities/public.js` | ソース | 公開エクスポート |
| core.js | `src/main/core.js` | ソース | formatRangeでの使用例 |
| index.js | `src/index.js` | ソース | API公開（util経由） |
