# 機能設計書 35-get-in変換

## 概要

本ドキュメントは、Clojure LSPの「get-in変換」機能の設計仕様を記載する。この機能は、ネストされたマップアクセス（例：`(:a (:b m))`）を`get`または`get-in`形式（例：`(get-in m [:b :a])`）に変換するリファクタリング操作を提供する。

### 本機能の処理概要

**業務上の目的・背景**：Clojureでは、ネストされたマップへのアクセスを複数の方法で記述できる。キーワード関数形式（`:key map`）とget/get-in形式にはそれぞれ利点がある。本機能は、キーワード関数形式のネストアクセスをget-in形式に統一することで、コードの可読性向上やデフォルト値の追加を容易にする。

**機能の利用シーン**：この機能は以下の場面で利用される：
- ネストされたマップアクセスの可読性向上
- get-inのデフォルト値引数を活用したい場合
- コードスタイルの統一

**主要な処理内容**：
1. カーソル位置の式がネストされたマップアクセスか判定
2. `get-in-more`: 1段階追加でget/get-inに変換
3. `get-in-all`: 可能な限りすべてのネストをget-inに変換

**関連システム・外部連携**：LSPプロトコルを通じてエディタと連携。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | エディタ画面 | 主画面 | コードアクションメニューから変換操作を選択 |

## 機能種別

リファクタリング（コード変換処理）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| uri | string | Yes | 対象ファイルのURI | 有効なファイルURIであること |
| line | number | Yes | カーソル行（0-indexed） | 0以上の整数 |
| character | number | Yes | カーソル列（0-indexed） | 0以上の整数 |

### 入力データソース

- エディタからのLSP `workspace/executeCommand` リクエスト
- コマンド名: `get-in-more` または `get-in-all`

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| edits | vector | テキスト編集のリスト（:range と :loc を含む） |

### 出力先

- LSPレスポンスとしてエディタに返却

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ コマンドと引数を取得

2. 変換可否判定
   └─ get-in-more-data で変換可能か判定
   └─ 不可の場合はnil

3. get-in-more の場合
   └─ 1段階の変換を実行
   └─ (:key map) → (get map :key)
   └─ (get (:key map) :k2) → (get-in map [:key :k2])

4. get-in-all の場合
   └─ 再帰的にget-in-moreを適用
   └─ 変換不可になるまで繰り返し

5. 結果の返却
   └─ 編集操作を返却
```

### フローチャート

```mermaid
flowchart TD
    A[コマンド受信] --> B{リスト式?}
    B -->|No| C[nil返却]
    B -->|Yes| D{変換パターンに該当?}
    D -->|No| C
    D -->|Yes| E{get-in-more?}
    E -->|Yes| F[1段階変換]
    E -->|No| G[get-in-all]
    G --> H{まだ変換可能?}
    H -->|Yes| F
    F --> H
    H -->|No| I[編集返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-35-01 | キーワード関数変換 | `(:key map)` → `(get map :key)` | キーワードがオペレータ位置の場合 |
| BR-35-02 | get変換 | `(get (:key map) :k2)` → `(get-in map [:key :k2])` | getの引数がネスト可能な場合 |
| BR-35-03 | get-in拡張 | `(get-in (:key map) [:k2])` → `(get-in map [:key :k2])` | get-inの引数がネスト可能な場合 |
| BR-35-04 | デフォルト値保持 | 変換時にデフォルト値引数を保持 | デフォルト値がある場合 |

### 計算ロジック

**変換パターン**：

1. キーワード関数呼び出し：`(:key map)` → `(get map :key)`
2. get + ネスト：`(get (:key map) :k2)` → `(get-in map [:key :k2])`
3. get-in + ネスト：`(get-in (:key map) [:k2])` → `(get-in map [:key :k2])`

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 操作不可 | 変換対象でない式 | nil返却 |

### リトライ仕様

リトライは行わない。

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

トランザクション管理は不要。

## パフォーマンス要件

- 応答時間: 50ms以内

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

- ファイルシステムへの書き込みは行わない

## 備考

- get-in-lessおよびget-in-none機能と対をなす

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | thread_get.clj | `lib/src/clojure_lsp/feature/thread_get.clj` | get-in-more-dataの戻り値構造 |

**読解のコツ**: `get-in-more-data`は以下のマップを返す：
- `:replace-with` - 置換後のオペレータ（`get`または`get-in`）
- `:map-loc` - マップ引数のzloc
- `:key-or-path-loc` - キーまたはパスのzloc
- `:default-loc` - デフォルト値のzloc（オプション）

**主要処理フロー**:
- **21-46行目**: `get-in-more-data` - 変換データの抽出

#### Step 2: コア機能を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | thread_get.clj | `lib/src/clojure_lsp/feature/thread_get.clj` | get-in-more*とget-in-all* |

**主要処理フロー**:
- **48-51行目**: `get-in-more*` - 1段階の変換を実行
- **53-56行目**: `get-in-all*` - 再帰的に全変換を実行
- **105行目**: `can-get-in-more?` - 変換可否判定
- **106行目**: `get-in-more` - 公開API（1段階変換）
- **107行目**: `get-in-all` - 公開API（全変換）

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | command.clj | `lib/src/clojure_lsp/feature/command.clj` | get-in-moreコマンド |

**主要処理フロー**:
- **86-89行目**: `:get-in-more`と`:get-in-all`コマンドハンドラ

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

```
workspace/executeCommand (LSP)
    │
    └─ command/call-command
           │
           ├─ run-command :get-in-more
           │     └─ f.thread-get/get-in-more
           │           ├─ get-in-more-data
           │           ├─ get-in-more*
           │           └─ edits
           │
           └─ run-command :get-in-all
                 └─ f.thread-get/get-in-all
                       ├─ get-in-all* (再帰)
                       │     ├─ get-in-more-data
                       │     └─ get-in-more*
                       └─ edits
```

### データフロー図

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

zloc               ──▶  get-in-more-data           ──▶  {:replace-with, :map-loc, :key-or-path-loc}
                         (変換データ抽出)

変換データ          ──▶  get-in-more*               ──▶  新しいzloc
                         (1段階変換)

新zloc             ──▶  get-in-all* (再帰)          ──▶  最終zloc
                         (全変換)

最終zloc           ──▶  edits                      ──▶  [{:range, :loc}]
                         (編集生成)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| thread_get.clj | `lib/src/clojure_lsp/feature/thread_get.clj` | ソース | get-in変換のコアロジック |
| command.clj | `lib/src/clojure_lsp/feature/command.clj` | ソース | コマンドディスパッチ |
| code_actions.clj | `lib/src/clojure_lsp/feature/code_actions.clj` | ソース | コードアクション生成 |
| thread_get_test.clj | `lib/test/clojure_lsp/feature/thread_get_test.clj` | テスト | get-in変換のテスト |
