# 画面設計書 61-ファイル検索（served/searchFile）

## 概要

本ドキュメントは、serve-d LSPサーバーのカスタムリクエスト `served/searchFile` の画面設計書である。クライアントからファイル名クエリを受け取り、プロジェクトおよび依存関係内から一致するファイルパスを検索して返却する。

### 本画面の処理概要

本リクエストは、エディタ（LSPクライアント）からD言語プロジェクト内のファイルをファイル名で横断検索する機能を提供する。

**業務上の目的・背景**：D言語の開発において、プロジェクトが依存する標準ライブラリや外部パッケージを含む広範なファイル群の中から、特定のファイルを迅速に見つける必要がある。本リクエストは、ファイル名の部分一致（末尾一致）によるファイル検索を提供し、エディタの「ファイルを開く」機能やコードナビゲーション機能を支援する。

**画面へのアクセス方法**：LSPクライアントから `served/searchFile` カスタムリクエストを送信することでアクセスする。エディタ拡張（code-d等）のコマンドパレットやファイル検索UIから呼び出される。

**主要な操作・処理内容**：
1. クライアントからファイル名クエリ（文字列）を受信する
2. クエリが空文字列の場合はnullを返却する
3. クエリが絶対パスの場合はファイルの存在確認を行い、存在すればそのパスを返却する
4. 相対パスの場合は、全ワークスペースインスタンスのインポートファイル・インポートパスおよび標準ライブラリパスを横断検索する
5. ファイル名の末尾一致でマッチするファイルパスの一覧を返却する

**画面遷移**：
- 遷移元：エディタのファイル検索UI、コマンドパレット
- 遷移先：検索結果のファイルを開く操作（textDocument/didOpen）

**権限による表示制御**：特になし。全てのクライアントが利用可能。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 64 | ファイル検索 (served/searchFile) | 主機能 | ファイル名でプロジェクトと依存関係（標準ライブラリ含む）を横断検索する |

## 画面種別

カスタムLSPリクエスト（検索結果返却型）

## URL/ルーティング

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

## 入出力項目

### リクエストパラメータ

| 項目名 | 型 | 必須 | 説明 |
|--------|------|------|------|
| query | string | はい | 検索するファイル名クエリ。絶対パスまたは相対パスの末尾部分 |

### レスポンス

| 項目名 | 型 | 説明 |
|--------|------|------|
| (戻り値) | string[] | マッチしたファイルの絶対パスの配列。該当なしの場合はnull |

## 表示項目

本リクエストはデータ返却のみであり、エディタ上の表示はクライアント側の実装に依存する。返却されるファイルパスの一覧がクライアント側のファイル選択UIに表示される。

## イベント仕様

### 1-ファイル検索リクエスト受信

1. クライアントから `served/searchFile` リクエストを受信する
2. クエリが空文字列の場合、即座にnullを返却する
3. クエリが絶対パスの場合：
   - ファイルシステム上にファイルが存在するか確認する
   - 存在すればそのパスを配列に格納して返却する
   - 存在しなければnullを返却する
4. クエリが相対パスの場合：
   - 選択中ワークスペースの標準ライブラリパスを取得する
   - 全バックエンドインスタンスからインポートファイル・インポートパスを収集する
   - インポートファイル一覧に対して末尾一致検索を実行する
   - インポートパス配下のディレクトリを再帰的に走査し、末尾一致検索を実行する
   - マッチしたファイルパスを配列に格納して返却する

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

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

本リクエストはデータベースへの更新を行わない。ファイルシステムの読み取り専用操作のみを実施する。

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| ファイル検索リクエスト | なし | SELECT（読み取り） | ファイルシステムからファイル一覧を検索 |

## メッセージ仕様

| メッセージID | 種別 | 表示条件 | メッセージ内容 |
|-------------|------|---------|--------------|
| なし | - | - | 本リクエストはエラーメッセージを直接クライアントに表示しない |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| クエリが空文字列 | nullを返却する |
| 絶対パスが存在しない | nullを返却する |
| ファイルシステムアクセスエラー | 該当ファイル/ディレクトリをスキップして処理を継続する |

## 備考

- 検索はファイル名の末尾一致（サフィックスマッチ）で行われる。例えば "std/stdio.d" をクエリすると、パスの末尾が "/std/stdio.d" で終わるファイルが全てマッチする
- インポートファイルとインポートパスはソート後にuniqで重複排除してから検索を実施する
- 標準ライブラリパス（phobos, druntime）も検索対象に含まれる

---

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

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

### 推奨読解順序

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

本リクエストは文字列のみを入出力として使用するため、特別なデータ構造は定義されていない。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types.d | `source/served/types.d` | serve-d全体で使用される型定義。DocumentUri等の基本型を理解する |

**読解のコツ**: D言語の `@protocolMethod` UDAがLSPメソッドのルーティングを定義している。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | file_search.d | `source/served/commands/file_search.d` | `searchFile` 関数がエントリーポイント |

**主要処理フロー**:
1. **行18-19**: `@protocolMethod("served/searchFile")` UDAで `served/searchFile` リクエストにバインドされる `searchFile(string query)` 関数
2. **行21-22**: クエリが空の場合はnullを返却
3. **行24-30**: 絶対パスの場合はファイル存在確認を実施
4. **行34**: `selectedWorkspace.stdlibPath()` で標準ライブラリパスを取得
5. **行36-40**: 全バックエンドインスタンスからインポートファイルとインポートパスを収集
6. **行45-54**: インポートファイル一覧に対する末尾一致検索
7. **行55-69**: インポートパス配下のディレクトリ再帰走査による末尾一致検索

#### Step 3: ファイルシステム走査を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | file_search.d | `source/served/commands/file_search.d` | 行55-69のディレクトリ走査ロジック |

**主要処理フロー**:
- **行55-57**: ディレクトリの存在確認
- **行58**: `fs.dirEntries(dir, fs.SpanMode.breadth)` で幅優先でディレクトリ内のファイルを列挙
- **行62-66**: ファイルパスの末尾一致チェック。パス区切り文字（`/` または `\`）の境界も確認

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

```
served/searchFile リクエスト
    |
    +-- searchFile(string query)              [file_search.d:19]
           |
           +-- selectedWorkspace.stdlibPath()  [extension.d 経由]
           |
           +-- backend.instances               [全インスタンスのインポートパス取得]
           |      +-- instance.importFiles
           |      +-- instance.importPaths
           |
           +-- fs.exists() / fs.isFile()       [ファイル存在確認]
           |
           +-- fs.dirEntries()                 [ディレクトリ再帰走査]
```

### データフロー図

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

query(string) ---------> searchFile()                 --> string[] (ファイルパス一覧)
                            |
                            +-- stdlibPath取得
                            +-- importFiles収集
                            +-- importPaths収集
                            +-- 末尾一致フィルタリング
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| file_search.d | `source/served/commands/file_search.d` | ソース | ファイル検索・モジュール検索の実装 |
| extension.d | `source/served/extension.d` | ソース | selectedWorkspaceの定義やbackendインスタンス管理 |
| types.d | `source/served/types.d` | ソース | 共通型定義 |
