# 画面設計書 10-LSP言語サーバ

## 概要

本ドキュメントは、Nushellにおける LSP言語サーバ画面の設計仕様を定義する。LSP言語サーバは、IDE/エディタとの連携機能を提供するLanguage Server Protocol実装である。

### 本画面の処理概要

LSP言語サーバは、`nu --lsp`コマンドで起動されるLanguage Server Protocol準拠のサーバーである。VSCode、Neovim、Emacsなどのエディタとstdio通信し、コード補完、定義ジャンプ、ホバー表示、診断、シンボル検索などのIDE機能を提供する。

**業務上の目的・背景**：
Nushellスクリプトの開発効率を向上させるため、モダンなIDE機能が求められる。LSP言語サーバは、エディタに依存しない標準プロトコルでIDE機能を提供し、開発者がコマンドの使い方を調べたり、変数の定義元にジャンプしたり、構文エラーを即座に確認できるようサポートする。

**画面へのアクセス方法**：
- コマンドラインで `nu --lsp` を実行
- エディタの拡張機能から自動起動

**主要な操作・処理内容**：
1. LSPリクエストの受信と応答
2. コード補完の提供
3. 定義ジャンプの処理
4. ホバー情報の表示
5. 診断（エラー・警告）の発行
6. シンボル検索
7. リネーム処理

**画面遷移**：
- エディタ → LSP起動 → 各種LSPリクエスト処理
- LSP言語サーバはバックグラウンドプロセスとして動作

**権限による表示制御**：
- 特になし。ファイルシステムのアクセス権限に依存

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | パーサー | 主機能 | コード解析・構文エラー検出 |
| 3 | 補完 | 主機能 | コード補完候補の生成 |
| 1 | シェル実行環境 | API連携 | EngineStateの管理 |

## 画面種別

LSP（Language Server Protocol）サーバー

## URL/ルーティング

N/A（stdio通信によるLSPプロトコル）

## 入出力項目

| 項目名 | 型 | 入力/出力 | 説明 |
|--------|-----|----------|------|
| LSPリクエスト | Message | 入力 | Request/Notification/Response |
| LSPレスポンス | Response | 出力 | リクエストに対する応答 |
| 診断情報 | PublishDiagnosticsParams | 出力 | エラー・警告の通知 |
| 進捗情報 | ProgressParams | 出力 | 処理進捗の通知 |

## 表示項目

| 項目名 | 説明 | 表示形式 |
|--------|------|----------|
| 補完候補 | コマンド・変数・ファイル等の補完 | CompletionResponse |
| ホバー情報 | コマンド説明・型情報 | Hover (Markdown) |
| 定義位置 | 変数・コマンドの定義場所 | Location |
| シンボル一覧 | ドキュメント/ワークスペースのシンボル | SymbolInformation |
| 診断メッセージ | 構文エラー・警告 | Diagnostic |
| InlayHints | インライン型ヒント | InlayHint |
| SemanticTokens | 構文ハイライト情報 | SemanticToken |

## イベント仕様

### 1-initialize（初期化）

1. Connection::stdioで接続を確立
2. ServerCapabilitiesを定義
3. クライアントパラメータを受信
4. ワークスペースフォルダを初期化

### 2-textDocument/completion（補完）

1. カーソル位置を取得
2. NuCompleterで補完候補を生成
3. CompletionItemに変換して返却
4. スニペット形式でコマンド引数を展開

### 3-textDocument/hover（ホバー）

1. カーソル位置のIDを特定
2. Id種別に応じて情報を取得:
   - Variable: 型と値
   - Declaration: コマンド説明・使い方・例
   - Module: モジュールコメント
   - External: manページ
3. Markdown形式で返却

### 4-textDocument/definition（定義ジャンプ）

1. カーソル位置のIDを特定
2. 定義Spanを取得
3. Location（URI + Range）を返却

### 5-textDocument/publishDiagnostics（診断）

1. ファイルをパース
2. parse_errorsからエラーを収集
3. parse_warningsから警告を収集
4. Diagnosticとして通知

### 6-workspace/symbol（ワークスペースシンボル）

1. SymbolCacheを更新
2. クエリでファジーマッチング
3. SymbolInformation一覧を返却

### 7-textDocument/rename（リネーム）

1. prepare_renameで準備
2. ワークスペース全体の参照を検索
3. WorkspaceEditを返却

## データベース更新仕様

N/A（データベース操作なし）

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 発生条件 |
|-------------|------|---------------|----------|
| LOG | 情報 | 各種ログメッセージ | デバッグ情報 |
| PROGRESS | 情報 | 処理進捗 | ワークスペース検索時 |
| DIAGNOSTIC_ERROR | エラー | Variable not found等 | 構文エラー |
| DIAGNOSTIC_WARNING | 警告 | 非推奨警告等 | 構文警告 |

## 例外処理

| 例外状態 | 対応処理 |
|---------|---------|
| パースエラー | Diagnosticとして通知 |
| ファイル未発見 | null応答 |
| タイムアウト | バックグラウンドスレッドをキャンセル |
| チャネル切断 | サーバー終了 |

## 備考

- stdio通信でLSPプロトコルを実装
- lsp-server/lsp-typesクレートを使用
- TextDocumentsでドキュメント状態を管理
- SymbolCacheでシンボル情報をキャッシュ
- StateDeltaキャッシュで再パースを最小化
- crossbeam-channelでバックグラウンドスレッドと通信

---

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

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

### 推奨読解順序

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

LSP言語サーバで扱う主要なデータ構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | lib.rs | `crates/nu-lsp/src/lib.rs` | LanguageServer構造体（51-70行） |
| 1-2 | lib.rs | `crates/nu-lsp/src/lib.rs` | Id列挙型（41-49行） |
| 1-3 | symbols.rs | `crates/nu-lsp/src/symbols.rs` | SymbolCache構造体（71-78行） |

**読解のコツ**: LanguageServerはconnection、docs、engine_state、symbol_cacheを中心に構成

#### Step 2: 初期化とメインループを理解する

サーバー起動から終了までの流れを追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | lib.rs | `crates/nu-lsp/src/lib.rs` | initialize_stdio_connection関数（95-98行） |
| 2-2 | lib.rs | `crates/nu-lsp/src/lib.rs` | serve_requests関数（121-288行） |

**主要処理フロー**:
1. **95-98行**: stdio接続の確立
2. **125-163行**: ServerCapabilitiesの定義
3. **173-281行**: メインループ - リクエスト/通知の処理

#### Step 3: 補完機能を理解する

コード補完の処理を追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | completion.rs | `crates/nu-lsp/src/completion.rs` | complete関数（16-63行） |
| 3-2 | completion.rs | `crates/nu-lsp/src/completion.rs` | completion_item_from_suggestion関数（65-172行） |

**主要処理フロー**:
- **16-46行**: NuCompleterで補完候補を取得
- **65-172行**: CompletionItemへの変換、スニペット生成

#### Step 4: ホバー機能を理解する

ホバー情報表示の処理を追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | hover.rs | `crates/nu-lsp/src/hover.rs` | hover関数（119-217行） |
| 4-2 | hover.rs | `crates/nu-lsp/src/hover.rs` | get_decl_description関数（11-117行） |

**主要処理フロー**:
- **119-128行**: parse_and_findでIDを特定
- **141-216行**: Id種別に応じた情報取得

#### Step 5: 定義ジャンプを理解する

定義位置への移動処理を追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | goto.rs | `crates/nu-lsp/src/goto.rs` | goto_definition関数（87-105行） |
| 5-2 | goto.rs | `crates/nu-lsp/src/goto.rs` | find_definition_span_by_id関数（56-85行） |

#### Step 6: 診断機能を理解する

エラー・警告の通知処理を追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | diagnostics.rs | `crates/nu-lsp/src/diagnostics.rs` | publish_diagnostics_for_file関数（9-58行） |

**主要処理フロー**:
- **13-15行**: ファイルをパース
- **30-38行**: parse_errorsからDiagnostic生成
- **41-50行**: parse_warningsからDiagnostic生成

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

```
nu --lsp
    |
    +-- LanguageServer::initialize_stdio_connection()  [lib.rs:95]
            |
            +-- Connection::stdio()
            +-- initialize_connection()  [lib.rs:100]
                    |
                    +-- serve_requests()  [lib.rs:121]
                            |
                            +-- メインループ  [lib.rs:173]
                            |       |
                            |       +-- handle_internal_messages()  [lib.rs:302]
                            |       +-- connection.receiver.recv_timeout()
                            |
                            +-- Request処理
                            |       +-- Completion::METHOD → complete()  [completion.rs:16]
                            |       +-- HoverRequest::METHOD → hover()  [hover.rs:119]
                            |       +-- GotoDefinition::METHOD → goto_definition()  [goto.rs:87]
                            |       +-- DocumentSymbol::METHOD → document_symbol()  [symbols.rs:273]
                            |       +-- References::METHOD → references()
                            |       +-- Rename::METHOD → rename()
                            |
                            +-- Notification処理
                                    +-- handle_lsp_notification()  [notification.rs:15]
                                    +-- publish_diagnostics_for_file()  [diagnostics.rs:9]
```

### データフロー図

```
[エディタ]                    [LSPサーバー]                    [Nushell]

Request
(stdio) ─────────────────────▶ Connection.receiver
                                    │
                                    ▼
                              serve_requests()
                                    │
                    ┌───────────────┼───────────────┐
                    │               │               │
                    ▼               ▼               ▼
              complete()       hover()       goto_definition()
                    │               │               │
                    ▼               ▼               ▼
              NuCompleter    parse_and_find   parse_and_find
                    │               │               │
                    ▼               ▼               ▼
              EngineState ◀─────────┴───────────────┘
                    │
                    ▼
              StateWorkingSet
                    │
                    ▼
              Response ──────────────────────────────▶ エディタ

Notification
(textDocument/didOpen) ──────▶ handle_lsp_notification()
                                    │
                                    ▼
                              publish_diagnostics_for_file()
                                    │
                                    ▼
                              parse_file() → working_set.parse_errors
                                    │
                                    ▼
                              PublishDiagnosticsParams ────▶ エディタ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| lib.rs | `crates/nu-lsp/src/lib.rs` | ソース | LanguageServer構造体とメインループ |
| completion.rs | `crates/nu-lsp/src/completion.rs` | ソース | コード補完機能 |
| hover.rs | `crates/nu-lsp/src/hover.rs` | ソース | ホバー情報表示 |
| goto.rs | `crates/nu-lsp/src/goto.rs` | ソース | 定義ジャンプ機能 |
| diagnostics.rs | `crates/nu-lsp/src/diagnostics.rs` | ソース | 診断（エラー・警告）機能 |
| notification.rs | `crates/nu-lsp/src/notification.rs` | ソース | 通知処理 |
| symbols.rs | `crates/nu-lsp/src/symbols.rs` | ソース | シンボル検索・キャッシュ |
| ast.rs | `crates/nu-lsp/src/ast.rs` | ソース | AST解析ユーティリティ |
| hints.rs | `crates/nu-lsp/src/hints.rs` | ソース | InlayHints抽出 |
| semantic_tokens.rs | `crates/nu-lsp/src/semantic_tokens.rs` | ソース | SemanticTokens抽出 |
| signature.rs | `crates/nu-lsp/src/signature.rs` | ソース | シグネチャヘルプ |
| workspace.rs | `crates/nu-lsp/src/workspace.rs` | ソース | ワークスペース操作 |
| completer.rs | `crates/nu-cli/src/completions/completer.rs` | ソース | NuCompleter実装 |
