# 画面設計書 59-依存関係更新（served/updateDependency）

## 概要

本ドキュメントは、serve-d LSPサーバーが提供するカスタム通知 `served/updateDependency` の設計を記述する。この通知は、DUBレシピファイル内の既存の依存関係バージョンを更新し、dub upgradeとインポートパス更新を実行する。

### 本画面の処理概要

このカスタム通知は、エディタ（LSPクライアント）からの要求に応じて、DUBレシピファイル（dub.sdl/dub.json）内の指定された依存関係のバージョン文字列を書き換え、パッケージの再ダウンロードとインポートパスの更新を行う処理である。

**業務上の目的・背景**：D言語の開発において、依存パッケージの新しいバージョンが公開された場合、レシピファイルのバージョン指定を更新する必要がある。手動でのファイル編集は、特にSDL形式の構文に不慣れな場合にエラーが発生しやすい。この通知により、エディタのDUBツリービューから直接バージョン更新を実行でき、バージョン文字列の正確な置換とパッケージの再ダウンロードを自動化する。

**画面へのアクセス方法**：LSPクライアントが `served/updateDependency` 通知をJSON-RPCで送信する。通常はエディタのDUBツリービューの「バージョン更新」操作やコマンドパレットから実行される。

**主要な操作・処理内容**：
1. クライアントからJSON-RPC通知 `served/updateDependency` を受信する
2. `changeDependency` 関数でレシピファイル内のバージョン文字列を置換する
3. 置換成功時に不足パッケージの自動ダウンロードを実行する
4. インポートパスを更新する（served/updateImports を内部呼び出し）

**画面遷移**：DUB依存関係管理フローの一部として動作する。依存関係ツリー表示（No.55）で対象パッケージを選択し、更新後はインポートパス更新（No.54）が実行され、DUBツリー更新通知が発生する。

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

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 59 | 依存関係更新 (served/updateDependency) | 主機能 | DUBレシピファイル内の依存関係バージョンを更新しdub upgradeとインポート更新を実行する |
| 54 | インポート更新 (served/updateImports) | 遷移先機能 | 依存関係更新後にインポートパスの更新処理を呼び出す |

## 画面種別

カスタムLSP通知（ファイル更新処理）

## URL/ルーティング

LSPカスタム通知: `served/updateDependency`

## 入出力項目

### 入力（通知パラメータ）

| 項目名 | 型 | 必須 | 説明 |
|--------|-----|------|------|
| name | string | はい | 更新する依存パッケージの名前（例: "vibe-d"） |
| version | string | はい | 新しいバージョン文字列（例: "~>0.9.6"） |

### 出力

通知のため直接的な戻り値はなし。処理結果はDUBレシピファイルの更新として反映される。

## 表示項目

進捗通知としてクライアントに送信される情報：

| 項目 | 表示形式 | 説明 |
|------|----------|------|
| importUpgrades進捗 | 数値（0/10） | 処理開始 |
| dubReload進捗 | 数値（7/10） | DUB依存関係リロード完了 |
| dubReload進捗 | 数値（10/10） | 全処理完了 |

## イベント仕様

### 1-通知受信

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

1. `UpdateRequest` からパラメータをデシリアライズする
2. `activeInstance` を取得する
3. `importUpgrades` 進捗（0/10）を通知する
4. `changeDependency(instance, req)` 関数を呼び出してバージョンを置換する
5. 置換成功時（trueが返却された場合）：
   - DubComponentが存在する場合、`selectAndDownloadMissing()` で不足パッケージをダウンロードする
   - `dubReload` 進捗（7/10）を通知する
   - `updateImports(UpdateImportsParams(false))` でインポートパスを更新する（進捗通知なし）
6. `dubReload` 進捗（10/10）を通知する

### 2-changeDependency（dub.sdl の場合）

1. `dub.sdl` ファイルの存在を確認する
2. ファイル内容を行単位で読み込む
3. トップレベル（depth=0）で `dependency "{name}"` で始まる行を検索する
4. 対象行内の `version` キーワードの後のダブルクォート内の文字列を新しいバージョンに置換する
5. 対象行が見つからない場合はfalseを返す
6. ファイルに書き戻す

### 3-changeDependency（dub.json / package.json の場合）

1. `dub.json` またはフォールバックとして `package.json` の存在を確認する
2. ファイル内容全体を読み込む
3. 正規表現 `("{name}"\s*:\s*)"[^"]*"` でバージョン文字列を検索・置換する
4. 置換が発生しなかった場合はfalseを返す
5. ファイルに書き戻す

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| バージョン置換 | ファイルシステム（dub.sdl/dub.json） | UPDATE | レシピファイル内のバージョン文字列を置換 |
| パッケージダウンロード | ファイルシステム（~/.dub/packages） | INSERT/UPDATE | 新バージョンのパッケージをダウンロード |
| インポートパス更新 | インメモリ（DCDキャッシュ） | UPDATE | DCDのインポートパスを再構築 |

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

#### DUBレシピファイル（dub.sdl）

| 操作 | 項目 | 更新値 | 備考 |
|-----|------|--------|------|
| UPDATE | dependency行のversion属性 | 新バージョン文字列 | ダブルクォート内のテキストのみ置換 |

#### DUBレシピファイル（dub.json）

| 操作 | 項目 | 更新値 | 備考 |
|-----|------|--------|------|
| UPDATE | dependencies内のバージョン値 | 新バージョン文字列 | 正規表現でマッチした部分を置換 |

## メッセージ仕様

| メッセージID | 種別 | 条件 | メッセージ内容 |
|-------------|------|------|---------------|
| (なし) | - | - | 本通知自体ではユーザー向けエラーメッセージは発生しない |

## 例外処理

| 条件 | 動作 | 返却値 |
|------|------|--------|
| dub.sdl も dub.json も package.json も存在しない | changeDependencyがfalseを返し、ダウンロード・更新をスキップ | (通知のため戻り値なし) |
| 指定された依存関係がレシピファイルに見つからない | changeDependencyがfalseを返し、ダウンロード・更新をスキップ | (通知のため戻り値なし) |
| SDL形式でversionキーワードが見つからない | changeDependencyがfalseを返す | (通知のため戻り値なし) |
| DubComponentが存在しない | パッケージダウンロードをスキップ | (通知のため戻り値なし) |

## 備考

- ソースコード内に `// TODO: update in dub.selections.json` コメントがあり、dub.selections.json の更新は未実装
- SDL形式の場合は行内のversionダブルクォート内の文字列を直接置換する
- JSON形式の場合は正規表現による置換を行うため、複雑なJSON構造に対しても比較的安全に動作する
- changeDependencyがfalseを返した場合、以降のダウンロード・インポート更新処理はスキップされるが、進捗の最終通知（10/10）は送信される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | protoext.d | `source/served/lsp/protoext.d` | UpdateRequest構造体（109-116行目）のフィールド定義を確認 |

**読解のコツ**: UpdateRequestはInstallRequestと同じフィールド構成（name, version_）を持つが、意味的に異なる操作（既存バージョンの更新 vs 新規追加）に使用される。

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

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

**主要処理フロー**:
1. **588行目**: `@protocolNotification("served/updateDependency")` UDAで通知ハンドラとして登録
2. **591行目**: TODOコメント - dub.selections.json更新は未実装
3. **595行目**: `reportProgress(ProgressType.importUpgrades, 0, 10, uri)` - 進捗開始
4. **596行目**: `if (changeDependency(instance, req))` - バージョン置換実行と結果チェック
5. **598-599行目**: 置換成功時のパッケージダウンロードとインポート更新
6. **603行目**: `reportProgress(ProgressType.dubReload, 10, 10, uri)` - 完了通知

#### Step 3: changeDependency関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | dub.d | `source/served/commands/dub.d` | changeDependency関数（727-776行目）- SDL/JSONそれぞれのバージョン置換ロジック |

**主要処理フロー**:
- **729-760行目**: dub.sdl形式の処理 - dependency行を検索し、version属性のダブルクォート内を置換
- **761-776行目**: dub.json形式の処理 - 正規表現 `("{name}"\s*:\s*)"[^"]*"` で置換

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

```
LSPクライアント (エディタ DUBツリービュー)
    |
    |  served/updateDependency (JSON-RPC notification)
    v
updateDependency(UpdateRequest) [source/served/commands/dub.d:589]
    |
    +-- reportProgress(importUpgrades, 0/10)
    |
    +-- changeDependency(instance, req) [source/served/commands/dub.d:727]
    |       |
    |       +-- [dub.sdl存在] SDL形式でバージョン文字列を置換
    |       |       +-- dependency行検索 (depth=0)
    |       |       +-- version属性のダブルクォート内置換
    |       |
    |       +-- [dub.json/package.json] JSON形式でバージョン文字列を正規表現置換
    |
    +-- [changeDependency=true の場合]
    |       +-- DubComponent.selectAndDownloadMissing()
    |       +-- reportProgress(dubReload, 7/10)
    |       +-- updateImports(UpdateImportsParams(false))
    |
    +-- reportProgress(dubReload, 10/10)
```

### データフロー図

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

JSON-RPC Notification   --->  updateDependency()            --->  ファイル更新
  name: "vibe-d"                |                                  |
  version: "~>0.9.6"           +-- changeDependency              +-- dub.sdl/dub.json更新
                                |   (バージョン文字列置換)           +-- パッケージダウンロード
                                +-- selectAndDownloadMissing      +-- DCDインポートパス更新
                                +-- updateImports
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| dub.d | `source/served/commands/dub.d` | ソース | updateDependency関数（588-604行目）、changeDependency関数（727-776行目） |
| protoext.d | `source/served/lsp/protoext.d` | ソース | UpdateRequest構造体定義（109-116行目） |
| progress.d | `source/served/utils/progress.d` | ソース | ProgressType定義、reportProgress関数 |
| types.d | `source/served/types.d` | ソース | activeInstance、backend等のグローバル定義 |
| extension.d | `source/served/extension.d` | ソース | LSP通知ディスパッチ基盤 |
