# 画面設計書 53-インポート追加（served/addImport）

## 概要

本ドキュメントは、serve-d LSPサーバーが提供するカスタムリクエスト `served/addImport` の設計を記述する。このリクエストは、指定されたインポートをD言語ソースコードに追加するためのテキスト編集情報を返却する。

### 本画面の処理概要

このカスタムリクエストは、エディタ（LSPクライアント）からの要求に応じて、指定されたモジュールのインポート文をソースコードの適切な位置に追加するためのテキスト編集（TextEdit）を生成して返却する処理である。

**業務上の目的・背景**：D言語の開発では、使用するシンボルに応じて適切なimport文をソースファイルに追加する必要がある。手動でのインポート追加はエラーが発生しやすく、特に適切な挿入位置の判定は煩雑である。このリクエストにより、コードアクション（No.19）やコード補完（No.17）と連携して、自動的に正しい位置にインポート文を追加できるようにする。

**画面へのアクセス方法**：LSPクライアントが `served/addImport` メソッドをJSON-RPCリクエストとして送信する。通常はコードアクション経由（未定義識別子に対する「インポートを追加」アクション）やコード補完の自動インポート機能から呼び出される。

**主要な操作・処理内容**：
1. クライアントからJSON-RPCリクエスト `served/addImport` を受信する
2. AddImportParamsからテキストドキュメント、インポート名、カーソル位置、挿入位置設定を取得する
3. ドキュメントマネージャからテキストドキュメントの内容を取得する
4. ImporterComponentのaddメソッドを呼び出し、テキスト編集情報を生成する
5. 生成されたテキスト編集情報を返却する

**画面遷移**：コードアクション・リファクタリングフロー内で、`textDocument/codeAction` から選択された「インポート追加」アクションの実行先として呼び出される。

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

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 53 | インポート追加 (served/addImport) | 主機能 | ソースコードにインポート文を追加するためのテキスト編集を生成する |

## 画面種別

カスタムLSPリクエスト（テキスト編集生成）

## URL/ルーティング

LSPカスタムメソッド: `served/addImport`

## 入出力項目

### 入力（リクエスト）

| 項目名 | 型 | 必須 | 説明 |
|--------|-----|------|------|
| textDocument | TextDocumentIdentifier | はい | 対象テキストドキュメントの識別子（uri） |
| name | string | はい | 追加するインポートの名前（例: "std.stdio"） |
| location | int | はい | カーソル位置（標準オフセット値） |
| insertOutermost | bool | いいえ | trueの場合は最も外側のブロックにインポートを追加（デフォルト: true） |

### 出力（レスポンス）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result | auto (ImporterComponent.add の戻り値) | インポート追加のためのテキスト編集情報（CodeReplacement配列等） |

## 表示項目

LSPリクエスト応答のため、直接的な画面表示項目はない。エディタ側でテキスト編集が適用される。

## イベント仕様

### 1-リクエスト受信

クライアントから `served/addImport` リクエストを受信すると、以下の処理が実行される：

1. `AddImportParams` からパラメータをデシリアライズする
2. `documents[params.textDocument.uri]` でテキストドキュメントの内容を取得する
3. `backend.get!ImporterComponent` でImporterComponentを取得する
4. `ImporterComponent.add` メソッドを以下の引数で呼び出す：
   - `params.name.idup` - インポート名
   - `document.rawText` - ドキュメントの生テキスト
   - `cast(int) document.offsetToBytes(params.location)` - バイトオフセットに変換したカーソル位置
   - `params.insertOutermost` - 最外部挿入フラグ
5. 結果を返却する

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| インポート追加 | (なし) | - | テキスト編集情報の生成のみ。実際のファイル書き込みはクライアント側で行う |

### テーブル別更新項目詳細

データベース・ファイルへの直接更新は発生しない。返却されたテキスト編集情報をクライアントが適用する。

## メッセージ仕様

| メッセージID | 種別 | 条件 | メッセージ内容 |
|-------------|------|------|---------------|
| (なし) | - | - | 本リクエストではユーザー向けメッセージは発生しない |

## 例外処理

| 条件 | 動作 | 返却値 |
|------|------|--------|
| ドキュメントが見つからない | 例外送出 | LSPエラーレスポンス |
| ImporterComponentが存在しない | 例外送出 | LSPエラーレスポンス |

## 備考

- ImporterComponentはworkspace-d APIの一部で、D言語のインポート解析・編集機能を提供する
- `insertOutermost` がtrueの場合、ネストされたスコープの外側にインポートが追加される
- `offsetToBytes` によりUTF文字のバイトオフセット変換が行われる
- コードアクション（No.19）の「インポート追加」アクションから連携して呼び出される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | protoext.d | `source/served/lsp/protoext.d` | AddImportParams構造体（12-22行目）のフィールド定義を確認 |
| 1-2 | types.d | `source/served/types.d` | documents（ドキュメントマネージャ）、backend（LazyWorkspaceD）の定義を確認 |

**読解のコツ**: `@serdeOptional bool insertOutermost = true` はデフォルトtrueのオプショナルパラメータ。リクエストで省略された場合は最外部挿入がデフォルト動作となる。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | dub.d | `source/served/commands/dub.d` | addImport関数（204-210行目）がエントリーポイント |

**主要処理フロー**:
1. **204行目**: `@protocolMethod("served/addImport")` UDAでLSPメソッドとして登録
2. **205行目**: `auto addImport(AddImportParams params)` - 戻り値はauto推論
3. **207行目**: `auto document = documents[params.textDocument.uri]` - ドキュメント取得
4. **208-209行目**: `backend.get!ImporterComponent.add(...)` - ImporterComponentのaddメソッド呼び出し
5. **209行目**: `cast(int) document.offsetToBytes(params.location)` - 文字オフセットからバイトオフセットへの変換

#### Step 3: ImporterComponent（workspace-d API）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | (workspace-d外部) | - | ImporterComponent.addメソッドはworkspace-d APIとして提供される。インポート文の適切な挿入位置を計算し、テキスト編集情報を返却する |

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

```
LSPクライアント (エディタ)
    |
    |  served/addImport (JSON-RPC request)
    v
addImport(AddImportParams) [source/served/commands/dub.d:205]
    |
    +-- documents[uri] [source/served/types.d:54]
    |       |
    |       +-- document.rawText
    |       +-- document.offsetToBytes(location)
    |
    +-- backend.get!ImporterComponent [source/served/types.d:518]
            |
            +-- ImporterComponent.add(name, rawText, offset, insertOutermost)
                    |
                    +-- (workspace-d API: インポート位置計算・テキスト編集生成)
```

### データフロー図

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

JSON-RPC Request       --->  addImport()                  --->  テキスト編集情報
  textDocument.uri              |                                 (CodeReplacement[])
  name: "std.stdio"             +-- ドキュメント内容取得
  location: 42                  +-- オフセット変換
  insertOutermost: true         +-- ImporterComponent.add
                                    (インポート位置計算)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| dub.d | `source/served/commands/dub.d` | ソース | addImport関数の実装（204-210行目） |
| protoext.d | `source/served/lsp/protoext.d` | ソース | AddImportParams構造体定義（12-22行目） |
| types.d | `source/served/types.d` | ソース | documents、backend等のグローバル定義 |
| extension.d | `source/served/extension.d` | ソース | LSPメソッドディスパッチ基盤 |
| code_actions.d | `source/served/commands/code_actions.d` | ソース | コードアクションからの連携元 |
