# 通知設計書 13-resolverExtensionNotFound

## 概要

本ドキュメントは、リモート接続に必要なリゾルバー拡張機能がマーケットプレイスで見つからない場合に表示される `resolverExtensionNotFound` 通知の設計仕様を記述する。

### 本通知の処理概要

この通知は、リモートウィンドウを開く際に必要なリゾルバー拡張機能をマーケットプレイスからインストールしようとしたが、該当する拡張機能が見つからなかった場合にエラーとして表示される。

**業務上の目的・背景**：VS Code は SSH、WSL、コンテナなどのリモート環境に接続するために専用のリゾルバー拡張機能を必要とする。ユーザーがリモート接続を試みた際に、対応する拡張機能がローカルにインストールされておらず、かつマーケットプレイスでも見つからない場合、ユーザーに問題を通知する必要がある。これはネットワーク環境の問題、拡張機能の廃止、または拡張機能IDの変更などが原因である可能性がある。

**通知の送信タイミング**：リモートウィンドウを開こうとした際に、リゾルバー拡張機能のインストールを試みた結果、マーケットプレイスで拡張機能が見つからなかった時点で通知が表示される。

**通知の受信者**：リモート接続を試みた VS Code ユーザー本人。

**通知内容の概要**：「`{拡張機能ID}` not found on marketplace」というエラーメッセージが表示される。

**期待されるアクション**：ユーザーは以下のいずれかの対処を行う。(1) ネットワーク接続を確認する、(2) マーケットプレイスで手動で拡張機能を検索する、(3) 拡張機能が廃止されていないか確認する、(4) 代替の拡張機能を使用する。

## 通知種別

アプリ内通知（Error レベル）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 中 |
| リトライ | 無し |

### 送信先決定ロジック

リモート接続を試みたユーザーに対してのみ通知が表示される。

## 通知テンプレート

### アプリ内通知

| 項目 | 内容 |
|-----|------|
| 深刻度 | Error |
| スティッキー | デフォルト（明示的な設定なし） |

### 本文テンプレート

```
`{0}` not found on marketplace
```

注意：ソースコードでは `{0}` が実際に使用されていないように見えるが、localize の呼び出しでは通常変数が使用される。

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| {0} | 拡張機能ID | resolverExtensionId | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ユーザー操作 | リモートウィンドウを開く | マーケットプレイスで拡張機能が見つからない | ギャラリー検索結果が空の場合 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 拡張機能がマーケットプレイスで見つかった | 正常にインストールが開始される |
| 拡張機能が既にインストール済み | インストール処理自体が発生しない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[リモートウィンドウを開く] --> B{リゾルバー拡張機能あり?}
    B -->|Yes| C[リモート接続処理]
    B -->|No| D{製品推奨あり?}
    D -->|No| E[処理終了]
    D -->|Yes| F{拡張機能インストール済?}
    F -->|Yes, 無効| G[有効化確認通知]
    F -->|No| H[インストール確認通知]
    H --> I{ユーザーがインストール選択}
    I --> J[マーケットプレイス検索]
    J --> K{拡張機能発見?}
    K -->|Yes| L[インストール実行]
    K -->|No| M[resolverExtensionNotFound エラー]
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| なし | 本通知ではデータベースは使用しない | - |

### 外部サービス参照

| サービス | 用途 | 備考 |
|---------|------|------|
| Extension Gallery Service | マーケットプレイスでの拡張機能検索 | `_extensionGalleryService.getExtensions()` |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 拡張機能未発見 | マーケットプレイス検索結果が空 | エラー通知を表示 |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 制限なし | ユーザー操作に応じて表示 |

### 配信時間帯

制限なし

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

- 拡張機能IDのみが通知に含まれ、個人情報は含まれない

## 備考

- この通知は、拡張機能のインストールを試みた後に発生するため、先行して「Extension '{0}' is required to open the remote window. Do you want to install the extension?」という確認通知が表示される
- `productService.remoteExtensionTips` に推奨拡張機能の情報が定義されている

---

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

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

### 推奨読解順序

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

リモート拡張機能の推奨設定を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | product.ts | `src/vs/platform/product/common/product.ts` | `remoteExtensionTips` プロパティの構造 |
| 1-2 | extensionGalleryService.ts | `src/vs/platform/extensionManagement/common/extensionGalleryService.ts` | `IExtensionGalleryService.getExtensions()` メソッド |

**読解のコツ**: `remoteExtensionTips` はリモート名をキーとして、推奨拡張機能の情報（extensionId, friendlyName）を保持する。

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

通知が発行される処理フローを特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | nativeExtensionService.ts | `src/vs/workbench/services/extensions/electron-browser/nativeExtensionService.ts` | `_handleNoResolverFound` メソッド |

**主要処理フロー**:
1. **行464-469**: リモート名から推奨拡張機能を取得
2. **行471-473**: 拡張機能IDで既存拡張機能を検索
3. **行491-513**: 拡張機能が未インストールの場合の処理
4. **行498**: マーケットプレイスで拡張機能を検索
5. **行502-504**: 見つからない場合にエラー通知を発行

#### Step 3: ギャラリーサービスを理解する

マーケットプレイス検索の仕組みを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | extensionGalleryService.ts | `src/vs/platform/extensionManagement/common/extensionGalleryService.ts` | `getExtensions` メソッドの実装 |

**主要処理フロー**:
- 拡張機能IDを条件にマーケットプレイスAPIを呼び出し
- 結果が空の配列の場合、拡張機能は見つからなかったと判断

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

```
リモートウィンドウを開く
    │
    ├─ NativeExtensionService._handleNoResolverFound()
    │      │
    │      ├─ productService.remoteExtensionTips 参照
    │      │
    │      ├─ _scanAllLocalExtensions() で既存確認
    │      │
    │      └─ 拡張機能未インストールの場合
    │             │
    │             ├─ notificationService.prompt() - インストール確認
    │             │
    │             └─ ユーザーが「Install and Reload」選択
    │                    │
    │                    ├─ extensionGalleryService.getExtensions()
    │                    │
    │                    └─ 拡張機能未発見の場合
    │                           │
    │                           └─ notificationService.error()
    │                                  │
    │                                  └─ "resolverExtensionNotFound"
```

### データフロー図

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

remoteAuthority      ───▶ getRemoteName()           ───▶ remoteName
      │
      ↓
productService       ───▶ remoteExtensionTips[      ───▶ recommendation
.remoteExtensionTips       remoteName]                    (extensionId,
                                                           friendlyName)
      │
      ↓
extensionGallery     ───▶ getExtensions([{id}])     ───▶ galleryExtension[]
Service                                                   (空の場合エラー)
      │
      ↓
[エラー時]

notificationService  ───▶ error()                   ───▶ Notification
                           localize(                      (Error レベル)
                           'resolverExtensionNotFound')
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| nativeExtensionService.ts | `src/vs/workbench/services/extensions/electron-browser/nativeExtensionService.ts` | ソース | 通知発行元 |
| extensionGalleryService.ts | `src/vs/platform/extensionManagement/common/extensionGalleryService.ts` | ソース | マーケットプレイス検索 |
| product.ts | `src/vs/platform/product/common/product.ts` | ソース | 製品設定（推奨拡張機能） |
| notification.ts | `src/vs/platform/notification/common/notification.ts` | ソース | 通知サービスインターフェース |
