# 機能設計書 22-プライバシー切り替え

## 概要

本ドキュメントは、clojure-lspの「プライバシー切り替え」機能（cycle-privacyコマンド）の設計仕様を定義する。この機能は、Clojureの関数定義（defn）と非公開関数定義（defn-）を相互に切り替えるリファクタリング機能を提供する。

### 本機能の処理概要

プライバシー切り替え機能は、カーソル位置にある関数定義のプライバシー（公開/非公開）を切り替える。defnをdefn-に、またはdefn-をdefnに変換する。メタデータによるプライバシー指定（^:private）にも対応している。

**業務上の目的・背景**：Clojure開発において、関数のスコープ管理は重要である。開発初期は公開関数として実装し、後で内部実装として非公開にしたい場合や、逆に非公開関数をAPI公開したい場合がある。この機能により、関数のプライバシー設定を素早く切り替えることができ、APIの設計変更を効率的に行える。

**機能の利用シーン**：
- 公開関数を内部実装として非公開にしたい場合
- 非公開関数をAPIとして公開したい場合
- リファクタリング時にAPIの境界を調整したい場合
- テストのために一時的に関数を公開/非公開にしたい場合

**主要な処理内容**：
1. カーソル位置から関数定義フォーム（defn, defn-, def, defmacroなど）を特定
2. 現在のプライバシー状態を判定（defn-かdefnか、^:privateメタデータの有無）
3. 設定に基づき、defn/defn-の切り替えまたはメタデータの追加/削除を実行
4. 変更結果を返却

**関連システム・外部連携**：LSPプロトコルを通じてエディタと連携し、コードアクションまたはコマンドとして実行される。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 該当なし | - | 本プロジェクトはLSPサーバーであり、UI画面は存在しない。エディタのコードアクションメニューから呼び出される。 |

## 機能種別

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

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| zloc | zipper location | Yes | カーソル位置のzipperロケーション | 関数定義フォーム内にあること |
| db | database | Yes | LSPデータベース（設定情報を含む） | - |

### 入力データソース

- エディタから送信されるLSPリクエスト
- ドキュメントのパース結果（rewrite-clj zipper）
- LSP設定（:use-metadata-for-privacy?）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| range | map | 変更対象範囲（:row, :col, :end-row, :end-col） |
| loc | zipper location | 変更後のノード |

### 出力先

LSPプロトコルを通じてエディタに返却され、テキスト編集として適用される。

## 処理フロー

### 処理シーケンス

```
1. 関数定義フォームの特定
   └─ find-function-form関数でdefn, defn-, def, defmacroなどを検索
2. 現在のプライバシー状態を判定
   └─ シンボルがdefn-か、名前に^:privateメタデータがあるか確認
3. 設定の確認
   └─ :use-metadata-for-privacy?設定を取得
4. プライバシー切り替え
   └─ defn⇔defn-の切り替え、またはメタデータの追加/削除
5. 結果の返却
   └─ rangeとlocを含むマップのベクターを返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{関数定義フォーム内?}
    B -->|No| C[nil返却]
    B -->|Yes| D[opシンボルを取得]
    D --> E{defn?}
    E -->|Yes| F{use-metadata設定?}
    F -->|No| G[defn-に置換]
    F -->|Yes| H[名前に^:private追加]
    E -->|No| I{defn-?}
    I -->|Yes| J[defnに置換]
    I -->|No| K{名前に^:privateあり?}
    K -->|Yes| L[^:private削除]
    K -->|No| M[名前に^:private追加]
    G --> N[結果返却]
    H --> N
    J --> N
    L --> N
    M --> N
    N --> O[終了]
    C --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | defn切り替え | defnはdefn-に、defn-はdefnに切り替える | use-metadata-for-privacy?がfalseの場合 |
| BR-002 | メタデータ切り替え | defnの名前に^:privateを追加/削除する | use-metadata-for-privacy?がtrueの場合 |
| BR-003 | 対象シンボル制限 | defn, defn-, def, defmacro, defmulti, defmethod, defonce, deftest, deftype, defrecordが対象 | 常時 |

### 計算ロジック

特になし。

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

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

本機能はデータベース操作を行わない。設定の読み取りのみ。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 暗黙的エラー | 関数定義フォーム外でコマンド実行 | nil返却（操作不可として扱われる） |

### リトライ仕様

リトライは不要。

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

該当なし（メモリ上の操作のみ）。

## パフォーマンス要件

即座に完了すること（100ms以内）。

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

特になし。ローカルファイルの操作のみ。

## 備考

- common-var-definition-symbolsで対象シンボルが定義されている
- use-metadata-for-privacy?設定により、defn/defn-方式とメタデータ方式を選択可能

---

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

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

### 推奨読解順序

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

対象となる関数定義シンボルのセットを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | transform.clj | `lib/src/clojure_lsp/refactor/transform.clj` | common-var-definition-symbols（19-29行目）で対象シンボルを確認 |

**読解のコツ**: common-var-definition-symbolsはdefn, defn-, def, defmacroなど、Clojureの変数定義に使用されるシンボルのセット。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | command.clj | `lib/src/clojure_lsp/feature/command.clj` | cycle-privacyコマンドの定義（50-51行目） |
| 2-2 | code_actions.clj | `lib/src/clojure_lsp/feature/code_actions.clj` | cycle-privacy-actionでUIアクション生成（175-180行目） |

**主要処理フロー**:
1. **50-51行目**: run-commandのcycle-privacyメソッドがr.transform/cycle-privacyを呼び出し

#### Step 3: 変換処理の実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | transform.clj | `lib/src/clojure_lsp/refactor/transform.clj` | find-function-form（1006-1007行目）で関数定義を検索 |
| 3-2 | transform.clj | `lib/src/clojure_lsp/refactor/transform.clj` | cycle-privacy（1009-1028行目）で切り替え処理 |

**主要処理フロー**:
- **1006-1007行目**: find-function-form関数でdefnなどの関数定義を検索
- **1011行目**: oplocで操作対象シンボルのロケーション取得
- **1012行目**: z/sexprでシンボル値取得
- **1013-1014行目**: defn && !use-metadata-for-privacy の場合switch-defn-?がtrue
- **1015行目**: defn-の場合switch-defn?がtrue
- **1019-1023行目**: switchの値を決定（defn, defn-, メタデータ操作）
- **1027行目**: z/replaceで置換

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

```
call-command (command.clj)
    │
    └─ run-command :cycle-privacy (command.clj:50-51)
           │
           └─ r.transform/cycle-privacy (transform.clj:1009-1028)
                  │
                  ├─ find-function-form (transform.clj:1006-1007)
                  │      └─ edit/find-ops-up
                  │
                  ├─ settings/get [:use-metadata-for-privacy?]
                  │
                  └─ z/replace
                         └─ 'defn | 'defn- | n/meta-node | vary-meta
```

### データフロー図

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

LSPリクエスト ───▶ zloc取得 ───▶ find-function-form ───▶ プライバシー判定 ───▶ 切り替え ───▶ TextEdit
(uri, pos)                         │                         │
                                   │                         └─ 設定参照
                                   └─ common-var-definition-symbols照合
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| transform.clj | `lib/src/clojure_lsp/refactor/transform.clj` | ソース | 切り替え処理の実装（cycle-privacy, find-function-form） |
| command.clj | `lib/src/clojure_lsp/feature/command.clj` | ソース | コマンドディスパッチ |
| code_actions.clj | `lib/src/clojure_lsp/feature/code_actions.clj` | ソース | コードアクションUI生成 |
| settings.clj | `lib/src/clojure_lsp/settings.clj` | ソース | use-metadata-for-privacy?設定の読み取り |
