# 機能設計書 48-演算子位置（experimentalOperatorPosition）

## 概要

本ドキュメントは、Prettierの実験的演算子位置機能（experimentalOperatorPosition）の設計仕様を定義する。

### 本機能の処理概要

experimentalOperatorPositionオプションは、二項演算子（+、-、&&、||等）が行をまたぐ際に、演算子を行の先頭に配置するか末尾に配置するかを制御する。従来は演算子が行末に配置されていたが、このオプションにより行頭への配置も選択できるようになった。

**業務上の目的・背景**：
二項演算子が複数行にわたる式では、演算子の位置がコードの可読性に影響する。行頭に演算子を配置することで、演算子が視覚的に揃い、各行の関係が明確になるという意見がある一方、行末に配置することで式の継続が自然に見えるという意見もある。この機能により、プロジェクトやチームの好みに応じた演算子配置を選択できる。実験的機能として提供されている。

**機能の利用シーン**：
1. 演算子を行頭に揃えて可読性を向上させたい場合（start）
2. 従来通り演算子を行末に配置したい場合（end）
3. 長い論理式やパイプラインの可読性を向上させたい場合
4. チームの演算子配置スタイルを統一したい場合

**主要な処理内容**：
1. experimentalOperatorPositionオプションの値取得（start/end）
2. BinaryExpression/LogicalExpressionノードの検出
3. 複数行にわたるかどうかの判定
4. 演算子と改行の配置順決定
5. コメント位置の調整

**関連システム・外部連携**：
- JavaScript/TypeScriptパーサー
- 二項演算子プリンター
- CLI、API、エディタプラグインからの呼び出し

**権限による制御**：
特になし。全てのユーザーが同一の機能を使用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | Playground | 補助機能 | サイドバーから演算子位置を設定 |
| 19 | Configuration - Options | 主機能 | experimentalOperatorPositionオプションの詳細説明 |

## 機能種別

設定オプション / フォーマット制御

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| experimentalOperatorPosition | string | No | 演算子の配置位置 | "start" / "end" のいずれか |

### 入力データソース

- 設定ファイル（.prettierrc、prettier.config.js、package.json等）
- CLI引数（--experimental-operator-position）
- API呼び出し時のオプションオブジェクト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| formatted | string | 演算子位置が制御されたフォーマット済みコード |

### 出力先

- 標準出力（CLIの場合）
- ファイル（--write オプション使用時）
- API戻り値

## 処理フロー

### 処理シーケンス

```
1. オプション解析
   └─ experimentalOperatorPositionオプションの値を取得（デフォルト: "end"）
2. BinaryExpression検出
   └─ 二項演算子ノードを特定
3. 複数行判定
   └─ 式が複数行にわたるかどうかを判定
4. 演算子配置決定
   └─ start: 改行 → 演算子 → スペース → 右辺
   └─ end: 演算子 → 改行 → 右辺
5. コメント位置調整
   └─ 演算子位置に応じてコメントを適切に配置
```

### フローチャート

```mermaid
flowchart TD
    A[BinaryExpression検出] --> B{複数行にわたる?}
    B -->|No| C[単一行出力]
    B -->|Yes| D{experimentalOperatorPosition?}
    D -->|end| E[演算子を行末に]
    D -->|start| F[演算子を行頭に]
    E --> G[operator + line + right]
    F --> H[line + operator + space + right]
    C --> I[出力]
    G --> I
    H --> I
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-48-01 | デフォルト設定 | デフォルトでは"end"（演算子を行末に配置） | experimentalOperatorPosition未指定 |
| BR-48-02 | 行末配置 | "end"では演算子を前の行の末尾に配置 | experimentalOperatorPosition: "end" |
| BR-48-03 | 行頭配置 | "start"では演算子を新しい行の先頭に配置 | experimentalOperatorPosition: "start" |
| BR-48-04 | コメント調整 | 演算子位置に応じてコメントを適切に移動 | 常に適用 |
| BR-48-05 | 実験的機能 | 将来変更される可能性あり | 常に適用 |

### 計算ロジック

演算子位置決定ロジック:
```javascript
if (options.experimentalOperatorPosition === "start") {
  // コメントがある場合の処理
  right = [line, comment, operator, " ", rightContent, rightSuffix];
} else {
  // end (デフォルト)
  right = [
    lineBeforeOperator ? line : "",
    operator,
    lineBeforeOperator ? " " : line,
    rightContent,
    rightSuffix,
  ];
}
```

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | バリデーションエラー | experimentalOperatorPositionに不正な値が指定された場合 | "start"/"end"のいずれかを指定する |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- 処理時間への影響は軽微
- 既存の二項演算子処理に統合されている

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

特になし

## 備考

- 実験的機能のため、将来のバージョンで動作が変更される可能性あり
- LogicalExpression、BinaryExpression、パイプライン演算子（|>）に適用
- TypeScriptのIntersectionTypeにも適用

---

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

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

### 推奨読解順序

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

オプション定義を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | options.js | `src/language-js/options.js` | experimentalOperatorPositionオプションの定義（40-55行目） |

**読解のコツ**: experimentalOperatorPositionはchoice型で、"start"と"end"の2つの選択肢がある。デフォルトは"end"。

#### Step 2: 二項演算子出力処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | binaryish.js | `src/language-js/print/binaryish.js` | printBinaryishExpressions関数（195-359行目） |

**主要処理フロー**:
1. **298行目**: experimentalOperatorPosition === "start" 判定
2. **299-310行目**: start位置の場合のコメント処理
3. **310行目**: `right = [line, comment, operator, " ", rightContent, rightSuffix]`
4. **311-319行目**: end位置の場合の処理
5. **339-343行目**: 最終的な出力の構築

#### Step 3: 型システムでの使用を確認

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | intersection-type.js | `src/language-js/print/intersection-type.js` | TypeScriptのIntersectionTypeでの適用 |

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

```
format() / formatWithCursor()
    │
    ├─ core.formatWithCursor()
    │      └─ printToDoc()
    │             └─ printer.print()
    │                    │
    │                    └─ printBinaryishExpression() [binaryish.js]
    │                           │
    │                           ├─ options.experimentalOperatorPosition チェック
    │                           │
    │                           ├─ "start" → [line, operator, " ", right]
    │                           │
    │                           └─ "end" → [operator, line, right]
```

### データフロー図

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

options.experimentalOperatorPosition ──▶ printBinaryish() ───▶ formatted binary
                                       │
BinaryExpression / LogicalExpression ──┘
                                       │
                                       ├─ "end" → operator + line + right
                                       │
                                       └─ "start" → line + operator + right
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| options.js | `src/language-js/options.js` | ソース | experimentalOperatorPositionオプション定義 |
| binaryish.js | `src/language-js/print/binaryish.js` | ソース | 二項演算子出力処理 |
| intersection-type.js | `src/language-js/print/intersection-type.js` | ソース | TypeScript IntersectionType出力 |
