# 機能設計書 57-DUBフォーマット変換

## 概要

本ドキュメントは、serve-dのLSPカスタム通知 `served/convertDubFormat` の機能設計を記述する。dub.json/dub.sdlファイルを別フォーマットに変換する機能である。

### 本機能の処理概要

**業務上の目的・背景**：DUBパッケージマネージャはJSON形式（dub.json）とSDL形式（dub.sdl）の2種類のレシピファイル形式をサポートしている。プロジェクトの方針変更やチーム間の標準化のために、レシピファイルのフォーマットを変換する必要がある場合がある。本機能は、エディタ上からフォーマット変換をワンクリックで実行できるようにする。

**機能の利用シーン**：開発者がdub.jsonからdub.sdlへ（またはその逆に）レシピファイルの形式を変換する際に、エディタのコマンドパレットから実行する。

**主要な処理内容**：
1. クライアントから `served/convertDubFormat` 通知を受信する
2. 対象ファイルの存在確認とDUBレシピファイルかの検証を行う
3. DUBの `convert` サブコマンドを外部プロセスとして実行する
4. 変換結果をWorkspaceEditとして構築し、ファイルリネームとコンテンツ置換をクライアントに適用要求する

**関連システム・外部連携**：DUBコマンドラインツール（`dub convert`）を外部プロセスとして実行する。クライアントのworkspace/applyEdit機能を使用してファイル操作を反映する。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 57 | DUBフォーマット変換（served/convertDubFormat） | 主画面 | dub.json/dub.sdlファイルを別フォーマットに変換する |

## 機能種別

ファイル変換処理（DUBレシピファイルのフォーマット変換）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| textDocument | TextDocumentIdentifier | Yes | 変換対象のテキストドキュメント識別子（URI） | ファイルが存在し、dub.json/dub.sdl/package.jsonであること |
| newFormat | string | Yes | 変換先フォーマット（"json" または "sdl"） | なし（DUBコマンドで検証） |

### 入力データソース

LSPクライアントからのJSON-RPC通知（DubConvertRequest構造体）

## 出力仕様

### 出力データ

本機能は通知（Notification）であるため、直接の戻り値はない。以下の副作用を生じる。

| 項目名 | 型 | 説明 |
|--------|-----|------|
| workspace/applyEdit | WorkspaceEdit | ファイルリネーム（resourceOperations対応時）とコンテンツ置換を含むWorkspaceEdit |

### 出力先

- `workspace/applyEdit` リクエストによりクライアントにWorkspaceEditを適用要求する
- エラー時は `window/showMessage` でユーザーにエラーを通知する

## 処理フロー

### 処理シーケンス

```
1. 通知受信
   └─ DubConvertRequestとしてデシリアライズ
2. ファイル存在確認
   └─ ファイルが存在しない場合はエラーログ出力して終了
3. レシピファイル検証
   └─ dub.json, dub.sdl, package.json のいずれでもない場合はエラーメッセージ表示して終了
4. DUB convert コマンド実行
   └─ execute([dubPath, "convert", "-f", newFormat, "-s"]) を実行
   └─ 失敗時はエラーメッセージ表示して終了
5. 新URI生成
   └─ 元URIの拡張子をnewFormatに変更
6. WorkspaceEdit構築
   ├─ [resourceOperations対応時]
   │   └─ RenameFile + TextDocumentEdit を documentChanges に設定
   └─ [resourceOperations非対応時]
       └─ 元URIに対するTextEdit を changes に設定
7. workspace/applyEdit 送信
   └─ クライアントにWorkspaceEditの適用を要求
```

### フローチャート

```mermaid
flowchart TD
    A[served/convertDubFormat 通知受信] --> B{ファイルが存在?}
    B -->|No| C[エラーログ出力して終了]
    B -->|Yes| D{DUBレシピファイル?}
    D -->|No| E[エラーメッセージ表示して終了]
    D -->|Yes| F[dub convert コマンド実行]
    F --> G{コマンド成功?}
    G -->|No| H[エラーメッセージ表示して終了]
    G -->|Yes| I{rename resourceOp 対応?}
    I -->|Yes| J[RenameFile + TextDocumentEdit を構築]
    I -->|No| K[元URIへの TextEdit を構築]
    J --> L[workspace/applyEdit を送信]
    K --> L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-57-01 | レシピファイル検証 | dub.json, dub.sdl, package.json のいずれかのみ対象とする | 常時 |
| BR-57-02 | resourceOperations分岐 | クライアントがrename resourceOperationに対応する場合はRenameFile+TextDocumentEditを使い、非対応の場合は元URIへのTextEditを使用する | 常時 |
| BR-57-03 | DUBコマンド呼出 | `dub convert -f {format} -s` をファイルのディレクトリで実行する。`-s` はstdout出力指定 | 常時 |
| BR-57-04 | 全文置換 | ドキュメント全体を変換結果で置換する（Position(0,0)からドキュメント末尾まで） | 常時 |

### 計算ロジック

特になし。DUBコマンドの出力をそのままWorkspaceEditのテキストとして使用する。

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

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

本機能はデータベースを使用しない。ファイルシステム上のDUBレシピファイルを変換する。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | エラーログ | 指定ファイルが存在しない場合 | error()でログ出力して処理終了 |
| d.dub.notRecipeFile | エラーメッセージ | DUBレシピファイルでない場合 | showErrorMessageでユーザーに通知して処理終了 |
| d.dub.convertFailed | エラーメッセージ | dub convertコマンドが失敗した場合 | showErrorMessageでユーザーに通知して処理終了 |

### リトライ仕様

リトライは不要。

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

トランザクション管理は不要。WorkspaceEditの適用はクライアント側の責任。

## パフォーマンス要件

DUB convertコマンドの実行にはプロセス生成が伴うため、数百ミリ秒の遅延が発生する可能性がある。stderrPassThroughとバッファサイズ4MBが設定されている。

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

外部プロセス（DUBコマンド）を実行するため、dubPathが信頼できるパスであることが前提となる。

## 備考

- 本機能は `@protocolNotification` として登録されており、戻り値を返さない通知型の処理である
- `dub convert -f {format} -s` の `-s` フラグにより変換結果が標準出力に出力され、ファイルを直接変更しない
- WorkspaceEditのdocumentChanges vs changesの使い分けは、クライアントのcapabilitiesに依存する
- 翻訳機能（translate!）を使用してエラーメッセージを多言語対応している

---

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

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

### 推奨読解順序

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

DubConvertRequest構造体とWorkspaceEditの型定義を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | protoext.d | `source/served/lsp/protoext.d` | DubConvertRequest構造体（83-89行目）のtextDocumentとnewFormatフィールドを確認 |

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

convertDubFormat関数の全体処理を把握する。

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

**主要処理フロー**:
1. **513行目**: `@protocolNotification("served/convertDubFormat")` - LSP通知として登録（戻り値なし）
2. **518行目**: `req.textDocument.uri.uriToFile` - URIからファイルパスに変換
3. **519-523行目**: ファイル存在チェック
4. **525-529行目**: DUBレシピファイル検証（dub.json, dub.sdl, package.json）
5. **533-536行目**: `execute([..., "convert", "-f", req.newFormat, "-s"])` - DUBコマンド実行
6. **538-542行目**: コマンド結果チェック
7. **544行目**: `req.textDocument.uri.setExtension("." ~ req.newFormat)` - 新URI生成
8. **551-566行目**: クライアントのresourceOperations対応有無で分岐
9. **571行目**: `rpc.sendMethod("workspace/applyEdit", params)` - 編集適用要求送信

**読解のコツ**: `@protocolNotification` と `@protocolMethod` の違いに注意。Notificationは戻り値を返さず、void関数として実装される。

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

```
convertDubFormat(DubConvertRequest) [source/served/commands/dub.d:514]
    |
    +-- uriToFile [URI変換]
    +-- fs.exists [ファイル存在確認]
    +-- baseName.among! [レシピファイル判定]
    |
    +-- documents[uri] [テキストドキュメント取得]
    |
    +-- execute([dubPath, "convert", ...]) [DUBプロセス実行]
    |
    +-- setExtension [新URI生成]
    |
    +-- capabilities.workspace.workspaceEdit.resourceOperations [クライアント能力確認]
    |
    +-- rpc.sendMethod("workspace/applyEdit", ...) [編集適用要求]
```

### データフロー図

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

DubConvertRequest          -->  convertDubFormat()                 -->  workspace/applyEdit
  textDocument.uri               |                                       (WorkspaceEdit)
  newFormat ("json"/"sdl")       +-- ファイル検証
                                 +-- dub convert -f {format} -s
                                 +-- WorkspaceEdit構築
                                 +-- workspace/applyEdit送信
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| dub.d | `source/served/commands/dub.d` | ソース | convertDubFormat関数の実装（513-572行目） |
| protoext.d | `source/served/lsp/protoext.d` | ソース | DubConvertRequest構造体定義（83-89行目） |
| types.d | `source/served/types.d` | ソース | documents別名、capabilities、workspace関数 |
| translate.d | `source/served/utils/translate.d` | ソース | エラーメッセージの翻訳機能 |
| extension.d | `source/served/extension.d` | ソース | LSPプロトコルメソッドのルーティング基盤 |
