# 機能設計書: 検索

## 1. 機能概要

### 1.1 機能名
検索（Search）

### 1.2 機能ID
No.22

### 1.3 概要説明
検索機能は、VSCodeのサイドバーに表示されるワークスペース全体を対象としたテキスト検索機能である。正規表現検索、大文字小文字の区別、単語単位検索などの高度な検索オプションを提供し、検索結果の一括置換機能も備える。また、ファイルパターンによるフィルタリングや、開いているエディタのみを対象とした検索も可能である。

### 1.4 関連画面
- 検索ビュー（サイドバー）
- 検索ウィジェット
- 検索結果ツリー

## 2. 機能要件

### 2.1 ビジネス要件
- ワークスペース内のすべてのファイルからテキスト検索ができること
- 検索結果の一覧表示と該当箇所へのジャンプが可能であること
- 検索と置換を効率的に行えること
- 検索履歴の保存と再利用が可能であること

### 2.2 機能要件詳細

| 要件ID | 要件名 | 説明 |
|--------|--------|------|
| SEARCH-001 | テキスト検索 | ワークスペース全体のテキスト検索 |
| SEARCH-002 | 正規表現検索 | 正規表現パターンによる検索 |
| SEARCH-003 | 大文字小文字区別 | 大文字小文字を区別した検索 |
| SEARCH-004 | 単語単位検索 | 単語境界での検索 |
| SEARCH-005 | 置換機能 | 単一/一括置換機能 |
| SEARCH-006 | ファイルフィルタ | 対象ファイルの絞り込み |
| SEARCH-007 | 除外パターン | 特定ファイル/フォルダの除外 |
| SEARCH-008 | 検索履歴 | 検索・置換履歴の保存 |
| SEARCH-009 | AI検索 | AI支援による検索結果表示 |

## 3. アーキテクチャ設計

### 3.1 コンポーネント構成

```
┌─────────────────────────────────────────────────────────┐
│                    Search View                          │
│  ┌──────────────────────────────────────────────────┐  │
│  │              SearchWidget                         │  │
│  │  ┌────────────────┐  ┌─────────────────────────┐ │  │
│  │  │ Search Input   │  │  Replace Input          │ │  │
│  │  └────────────────┘  └─────────────────────────┘ │  │
│  │  ┌────────────────────────────────────────────┐  │  │
│  │  │ Include/Exclude Pattern Inputs             │  │  │
│  │  └────────────────────────────────────────────┘  │  │
│  └──────────────────────────────────────────────────┘  │
│  ┌──────────────────────────────────────────────────┐  │
│  │              Results Tree                         │  │
│  │  (WorkbenchCompressibleAsyncDataTree)            │  │
│  └──────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────┐
│                  SearchModel                            │
│  ┌────────────────────────────────────────────────────┐│
│  │  SearchResult                                      ││
│  │  - folderMatches: Map<URI, FolderMatch>           ││
│  │  - aiTextSearchResult: AITextSearchResult         ││
│  │  - query: ISearchQuery                            ││
│  └────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────┐
│               SearchService (ISearchService)            │
│  ┌────────────────────────────────────────────────────┐│
│  │  - textSearch(): Promise<ISearchComplete>         ││
│  │  - fileSearch(): Promise<ISearchComplete>         ││
│  │  - clearCache(): void                             ││
│  └────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────┘
```

### 3.2 クラス図

```
┌─────────────────────────┐
│      ISearchService     │
│      <<interface>>      │
├─────────────────────────┤
│ + textSearch()          │
│ + fileSearch()          │
│ + clearCache()          │
│ + schemeHasProvider()   │
└───────────┬─────────────┘
            │
            ▼
┌─────────────────────────┐
│      SearchService      │
├─────────────────────────┤
│ - diskSearch            │
│ - extensionService      │
├─────────────────────────┤
│ + constructor()         │
│ + textSearch()          │
│ + fileSearch()          │
└─────────────────────────┘

┌─────────────────────────┐
│      SearchModel        │
├─────────────────────────┤
│ - _searchResult         │
│ - _replaceActive        │
│ - _replaceString        │
├─────────────────────────┤
│ + get searchResult()    │
│ + search()              │
│ + cancelSearch()        │
│ + replaceAll()          │
└─────────────────────────┘

┌─────────────────────────┐
│      SearchResult       │
├─────────────────────────┤
│ - _folderMatches: Map   │
│ - _query: ISearchQuery  │
│ - _isDirty: boolean     │
├─────────────────────────┤
│ + add()                 │
│ + remove()              │
│ + clear()               │
│ + folderMatches()       │
└─────────────────────────┘
```

## 4. 詳細設計

### 4.1 データ構造

#### ISearchQuery
```typescript
interface ISearchQuery {
    type: QueryType;                    // File | Text
    contentPattern?: IPatternInfo;      // 検索パターン
    folderQueries: IFolderQuery[];      // フォルダクエリ
    extraFileResources?: URI[];         // 追加ファイル
    usingSearchPaths?: boolean;         // 検索パス使用
    filePattern?: string;               // ファイルパターン
    excludePattern?: IExpression;       // 除外パターン
    includePattern?: IExpression;       // 含めるパターン
    maxResults?: number;                // 最大結果数
    onlyOpenEditors?: boolean;          // 開いているエディタのみ
    userDisabledExcludesAndIgnoreFiles?: boolean;
}
```

#### IPatternInfo
```typescript
interface IPatternInfo {
    pattern: string;                    // 検索パターン
    isRegExp?: boolean;                 // 正規表現フラグ
    isWordMatch?: boolean;              // 単語一致フラグ
    isCaseSensitive?: boolean;          // 大文字小文字区別
    isMultiline?: boolean;              // 複数行フラグ
    isUnicode?: boolean;                // Unicode対応
    notebookInfo?: NotebookPriorityInfo; // ノートブック情報
}
```

#### SearchResult
```typescript
interface ISearchResult {
    readonly query: ISearchQuery;
    readonly searchModel: ISearchModel;

    // フォルダマッチ管理
    folderMatches(): FolderMatch[];
    matches(): FileMatch[];

    // 状態管理
    isDirty(): boolean;
    clear(): void;

    // AI検索結果
    readonly aiTextSearchResult: AITextSearchResult;
}
```

### 4.2 処理フロー

#### 検索実行フロー
```
1. ユーザー入力（SearchWidget）
   │
   ├─2. SearchView.triggerQueryChange()
   │    │
   │    └─ デバウンス処理（searchOnTypeDebouncePeriod）
   │
   ├─3. SearchModel.search()
   │    │
   │    ├─ ISearchQuery構築
   │    │
   │    └─ SearchService.textSearch()
   │
   └─4. SearchResult更新
        │
        ├─ FolderMatch追加
        │
        ├─ FileMatch追加
        │
        └─ SearchView.refreshTree()
```

#### 置換実行フロー
```
1. ユーザー置換要求
   │
   ├─2. SearchModel.replaceAll() / replaceMatches()
   │    │
   │    ├─ 対象ファイルのグループ化
   │    │
   │    └─ BulkEditService経由で一括編集
   │
   └─3. SearchResult.clear()
        │
        └─ 検索結果の再取得（必要に応じて）
```

### 4.3 主要メソッド

#### SearchView.triggerQueryChange()
```typescript
private triggerQueryChange(options?: {
    triggeredOnType?: boolean;
    delay?: number
}): void {
    const delay = options?.delay ?? 0;

    if (!this.pauseSearching) {
        this.triggerQueryDelayer.trigger(() => {
            this._onQueryChanged(options?.triggeredOnType);
        }, delay);
    }
}
```

#### SearchModel.search()
```typescript
async search(query: ITextQuery): Promise<ISearchComplete> {
    // 既存検索のキャンセル
    this.cancelSearch();

    // 状態の更新
    this._searchResult.clear();
    this._searchResult.query = query;

    // 検索実行
    const result = await this.searchService.textSearch(
        query,
        this._currentCancellationTokenSource.token,
        (matches) => this._searchResult.add(matches)
    );

    return result;
}
```

## 5. インターフェース設計

### 5.1 サービスインターフェース

```typescript
interface ISearchService {
    readonly _serviceBrand: undefined;

    // テキスト検索
    textSearch(
        query: ITextQuery,
        token?: CancellationToken,
        onProgress?: (result: ISearchProgressItem) => void
    ): Promise<ISearchComplete>;

    // ファイル検索
    fileSearch(
        query: IFileQuery,
        token?: CancellationToken
    ): Promise<ISearchComplete>;

    // キャッシュクリア
    clearCache(cacheKey: string): Promise<void>;

    // スキーマサポート確認
    schemeHasProvider(scheme: string): boolean;
}
```

### 5.2 検索ウィジェットインターフェース

```typescript
interface ISearchWidget {
    // 入力値
    getValue(): string;
    setValue(value: string): void;
    getReplaceValue(): string;

    // 検索オプション
    getOptions(): ISearchWidgetOptions;
    setRegex(value: boolean): void;
    setCaseSensitive(value: boolean): void;
    setWholeWords(value: boolean): void;

    // 置換モード
    isReplaceShown(): boolean;
    toggleReplace(show: boolean): void;

    // 履歴
    prependSearchHistory(history: string[]): void;
    prependReplaceHistory(history: string[]): void;
}
```

## 6. 検索状態管理

### 6.1 検索状態（SearchUIState）

```typescript
enum SearchUIState {
    Idle,       // 待機中
    Searching,  // 検索中
    SlowSearch  // 遅延検索（2秒以上）
}
```

### 6.2 状態遷移

```
                 ┌─────────────┐
    検索開始     │             │
  ──────────────▶│  Searching  │
                 │             │
                 └──────┬──────┘
                        │
         ┌──────────────┼──────────────┐
         │              │              │
         ▼              ▼              ▼
   ┌─────────┐    ┌──────────┐   ┌─────────┐
   │  Idle   │    │SlowSearch│   │  Error  │
   │(完了)   │    │(2秒経過) │   │(エラー) │
   └─────────┘    └──────────┘   └─────────┘
```

## 7. エラーハンドリング

### 7.1 エラー種別

| エラーコード | エラー名 | 説明 | 対処方法 |
|-------------|---------|------|---------|
| SEARCH-E001 | InvalidRegex | 正規表現構文エラー | エラーメッセージを表示 |
| SEARCH-E002 | SearchCancelled | 検索キャンセル | 状態をIdleに戻す |
| SEARCH-E003 | NoWorkspace | ワークスペースなし | 警告メッセージを表示 |
| SEARCH-E004 | TooManyResults | 結果数超過 | 部分結果を表示 |
| SEARCH-E005 | SearchTimeout | 検索タイムアウト | タイムアウト通知を表示 |

### 7.2 エラーハンドリングフロー

```
1. 検索実行
   │
   ├─ 成功 → 結果表示
   │
   └─ 失敗
        │
        ├─ InvalidRegex → 入力欄にエラー表示
        │
        ├─ SearchCancelled → 静かに状態リセット
        │
        ├─ TooManyResults → 部分結果 + 警告表示
        │
        └─ その他 → エラーダイアログ表示
```

## 8. パフォーマンス考慮事項

### 8.1 最適化戦略

- **インクリメンタル検索**: 入力変更のデバウンス処理（250ms）
- **部分結果表示**: ストリーミングで結果を逐次表示
- **キャンセル機構**: CancellationTokenによる中断可能な検索
- **キャッシュ**: 検索結果のキャッシュと再利用
- **遅延レンダリング**: 結果ツリーの仮想スクロール

### 8.2 パフォーマンス目標

| 指標 | 目標値 |
|------|--------|
| 入力レスポンス | < 100ms |
| 初期結果表示 | < 500ms |
| 全結果表示（1万件） | < 3s |
| メモリ使用量（10万件） | < 200MB |

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

### 9.1 推奨読解順序

1. **共通定義**: `src/vs/workbench/contrib/search/common/search.ts`
   - **1-30行目**: IWorkspaceSymbolインターフェース
   - **31-70行目**: WorkspaceSymbolProviderRegistry
   - **150-230行目**: SearchUIState、extractRangeFromFilter

2. **ビュー層**: `src/vs/workbench/contrib/search/browser/searchView.ts`
   - **1-100行目**: インポートとコンテキストキー定義
   - **200-350行目**: コンストラクタとイベントリスナー設定
   - **456-600行目**: renderBody()でのUI構築
   - **300-340行目**: 検索履歴の読み込みとデバウンス設定

3. **検索モデル**: `src/vs/workbench/contrib/search/common/searchModel.ts`
   - SearchModel、SearchResult、FolderMatch、FileMatchクラス

4. **検索サービス**: `src/vs/workbench/services/search/common/searchService.ts`
   - textSearch()、fileSearch()の実装

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

```
SearchViewlet
└── SearchView
    ├── SearchWidget
    │   ├── SearchInput (HistoryInputBox)
    │   ├── ReplaceInput (HistoryInputBox)
    │   └── SearchOptions (Toggle buttons)
    ├── IncludePatternInputWidget
    ├── ExcludePatternInputWidget
    ├── SearchTree (WorkbenchCompressibleAsyncDataTree)
    │   ├── SearchTreeDelegate
    │   ├── SearchRenderer
    │   └── SearchAccessibilityProvider
    └── SearchModel
        ├── SearchResult
        │   ├── FolderMatch[]
        │   │   └── FileMatch[]
        │   │       └── Match[]
        │   └── AITextSearchResult
        └── SearchService (ISearchService)
            ├── DiskSearch
            └── SearchProvider extensions
```

### 9.3 データフロー図

```
┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   User Input    │────▶│  SearchWidget   │────▶│   SearchView    │
│  (Query/Options)│     │                 │     │                 │
└─────────────────┘     └─────────────────┘     └────────┬────────┘
                                                         │
                                                         ▼
┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   SearchTree    │◀────│  SearchResult   │◀────│  SearchModel    │
│   (Display)     │     │  (FolderMatch)  │     │                 │
└─────────────────┘     └─────────────────┘     └────────┬────────┘
                                                         │
                                                         ▼
                        ┌─────────────────┐     ┌─────────────────┐
                        │  SearchService  │◀────│   ITextQuery    │
                        │                 │     │                 │
                        └─────────────────┘     └─────────────────┘
```

### 9.4 関連ファイル一覧

| パス | 種別 | 役割 |
|------|------|------|
| `src/vs/workbench/contrib/search/browser/searchView.ts` | ビュー | 検索ビュー実装 |
| `src/vs/workbench/contrib/search/browser/searchWidget.ts` | ウィジェット | 検索入力ウィジェット |
| `src/vs/workbench/contrib/search/common/searchModel.ts` | モデル | 検索モデル |
| `src/vs/workbench/contrib/search/common/search.ts` | 共通 | インターフェース定義 |
| `src/vs/workbench/services/search/common/searchService.ts` | サービス | 検索サービス実装 |
| `src/vs/workbench/contrib/search/browser/searchActions.ts` | アクション | 検索関連アクション |
| `src/vs/workbench/contrib/search/browser/searchResultsView.ts` | ビュー | 検索結果表示 |

## 10. 変更履歴

| 日付 | バージョン | 変更内容 | 作成者 |
|------|-----------|---------|--------|
| 2026-01-27 | 1.0 | 初版作成 | Claude |
