# 機能設計書 78-サーバー起動

## 概要

本ドキュメントは、clojure-lsp の CLI コマンドとして提供される `listen` コマンドの機能設計を記述する。このコマンドは LSP (Language Server Protocol) サーバーを起動し、標準入出力を介してエディタと通信する機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：VS Code、Emacs、Vim などのエディタから Clojure のコード補完、定義ジャンプ、リファクタリングなどの機能を利用するには、LSP サーバーが必要である。この機能は clojure-lsp を LSP サーバーとして起動し、LSP プロトコルに従ってエディタと通信を行う。

**機能の利用シーン**：エディタの LSP クライアントから起動され、開発セッション中は常駐してリクエストを処理する。

**主要な処理内容**：
1. LSP サーバーの初期化
2. 標準入出力による JSON-RPC 通信の開始
3. LSP プロトコルメッセージの処理（initialize、textDocument/\*、workspace/\* 等）
4. プロジェクトの解析と状態管理
5. エディタへの診断情報やその他の通知の送信

**関連システム・外部連携**：LSP クライアント（VS Code、Emacs、Vim 等）、JSON-RPC プロトコル。

**権限による制御**：呼び出し元プロセスのファイルシステム権限に依存。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 該当なし | 該当なし | 該当なし | 本プロジェクトは LSP サーバー実装であり UI 画面は存在しない |

## 機能種別

サーバー起動 / プロトコル処理

## 入力仕様

### 入力パラメータ（CLI オプション）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| --trace-level | String | No | トレースレベル（off/messages/verbose） | "off", "messages", "verbose" のいずれか |
| --log-path | String | No | ログファイルのパス | 有効なファイルパス |
| --settings | EDN | No | 設定を EDN 形式で指定 | 有効な EDN マップ |
| --project-root | File | No | プロジェクトルートのパス | 存在するディレクトリ |

### 入力データソース

- 標準入力（LSP クライアントからの JSON-RPC メッセージ）
- プロジェクトファイルシステム
- 設定ファイル（.lsp/config.edn 等）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| JSON-RPC レスポンス | JSON | LSP リクエストへの応答 |
| JSON-RPC 通知 | JSON | 診断情報、進捗状況等の通知 |

### 出力先

- 標準出力（LSP クライアントへの JSON-RPC メッセージ）
- ログファイル（--log-path で指定、または一時ファイル）

## 処理フロー

### 処理シーケンス

```
1. CLI オプション解析
   └─ trace-level、log-path、settings 等を解析
2. サーバー初期化
   └─ TimbreLogger、db*、producer 等のコンポーネント初期化
3. JSON-RPC サーバー起動
   └─ stdio-server で標準入出力による通信開始
4. initialize リクエスト処理
   └─ クライアント capabilities 取得、プロジェクト初期化
5. メッセージループ
   └─ リクエスト/通知の受信と処理
6. shutdown/exit 処理
   └─ リソース解放とプロセス終了
```

### フローチャート

```mermaid
flowchart TD
    A[clojure-lsp listen] --> B[CLI オプション解析]
    B --> C[サーバーコンポーネント初期化]
    C --> D[JSON-RPC サーバー起動]
    D --> E[initialize 待機]
    E --> F[プロジェクト初期化]
    F --> G{メッセージ受信}
    G -->|リクエスト| H[リクエスト処理]
    G -->|通知| I[通知処理]
    G -->|shutdown| J[シャットダウン処理]
    H --> K[レスポンス送信]
    I --> G
    K --> G
    J --> L[exit]
    L --> M[プロセス終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-78-1 | LSP 準拠 | LSP 3.17 仕様に準拠したプロトコル処理 | 常時 |
| BR-78-2 | 初期化必須 | initialize 完了前は他のリクエストを処理しない | LSP 仕様 |
| BR-78-3 | トレースレベル | trace-level に応じてログ詳細度を制御 | trace-level 指定時 |
| BR-78-4 | 親プロセス監視 | 親プロセス終了時にサーバーも終了 | liveness-probe 有効時 |

### 計算ロジック

トレースレベル：
- `off`: トレースなし
- `messages`: 基本的なメッセージログ
- `verbose`: 詳細なトレースログ

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 該当なし | 該当なし | 該当なし | RDB は使用しない |

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

atom によるインメモリデータベースで状態管理。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 該当なし | 初期化エラー | プロジェクト解析失敗 | エラーログを確認 |
| 該当なし | プロトコルエラー | 不正な JSON-RPC メッセージ | LSP クライアントのバージョンを確認 |

### リトライ仕様

サーバーレベルのリトライは実装されていない。個別のリクエストは LSP クライアントが再送する。

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

RDB を使用しないため、トランザクション管理は不要。

## パフォーマンス要件

- リクエストへの応答は可能な限り高速に
- 重い処理（プロジェクト解析等）は非同期で実行
- debounce によるリクエスト最適化

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

- ファイルシステムアクセスはプロセス権限に依存
- ネットワークアクセスは行わない（標準入出力のみ）

## 備考

- デフォルトコマンド（引数なしで起動時も listen として動作）
- nREPL サーバーも起動可能（開発モード）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | db.clj | `lib/src/clojure_lsp/db.clj` | サーバー状態の構造 |

**読解のコツ**: initial-db がサーバー起動時の初期状態。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | main.clj | `cli/src/clojure_lsp/main.clj` | CLI エントリーポイント |

**主要処理フロー**:
1. **156-180行目**: parse 関数でコマンド解析
2. **194-198行目**: handle-action! で "listen" アクション処理
3. **196-198行目**: server/run-lsp-io-server! 呼び出し

#### Step 3: サーバー実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | server.clj | `cli/src/clojure_lsp/server.clj` | LSP サーバー実装 |

**主要処理フロー**:
- **647-670行目**: start-server! でコンポーネント初期化
- **672-678行目**: run-lsp-io-server! で標準入出力サーバー起動
- **549-570行目**: "initialize" リクエストハンドラー
- **572-574行目**: "initialized" 通知ハンドラー

#### Step 4: プロジェクト初期化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | startup.clj | `lib/src/clojure_lsp/startup.clj` | プロジェクト初期化 |

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

```
main/-main
    |
    +-- main/run!
            |
            +-- parse (CLI オプション解析)
            |
            +-- handle-action! "listen"
                    |
                    +-- server/run-lsp-io-server!
                            |
                            +-- jsonrpc.io-server/stdio-server
                            |
                            +-- start-server!
                                    |
                                    +-- TimbreLogger 初期化
                                    +-- ClojureLspProducer 初期化
                                    +-- spawn-async-tasks!
                                    +-- jsonrpc.server/start
                                            |
                                            +-- "initialize" -> handler/initialize
                                            +-- "initialized" -> handler/initialized
                                            +-- "textDocument/*" -> 各ハンドラー
                                            +-- "workspace/*" -> 各ハンドラー
```

### データフロー図

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

LSP クライアント          clojure-lsp server                  LSP クライアント
        |                      |                                    |
        | initialize           |                                    |
        +--------------------> | handler/initialize                 |
        |                      | startup/initialize-project         |
        | <--------------------+ capabilities                       |
        |                      |                                    |
        | textDocument/*       |                                    |
        +--------------------> | 各ハンドラー                        |
        | <--------------------+ レスポンス                          |
        |                      |                                    |
        |                      | publish-diagnostic                 |
        | <--------------------+ 診断通知                            |
        |                      |                                    |
        | shutdown             |                                    |
        +--------------------> | handler/shutdown                   |
        |                      |                                    |
        | exit                 |                                    |
        +--------------------> | プロセス終了                        |
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| main.clj | `cli/src/clojure_lsp/main.clj` | ソース | CLI エントリーポイント |
| server.clj | `cli/src/clojure_lsp/server.clj` | ソース | LSP サーバー実装 |
| handlers.clj | `lib/src/clojure_lsp/handlers.clj` | ソース | リクエストハンドラー |
| startup.clj | `lib/src/clojure_lsp/startup.clj` | ソース | プロジェクト初期化 |
| producer.clj | `lib/src/clojure_lsp/producer.clj` | ソース | 通知プロデューサー |
