# 帳票設計書 6-ドキュメントシンボル一覧

## 概要

本ドキュメントは、serve-dのドキュメントシンボル一覧機能の設計を記述する。指定ドキュメント内のシンボル（クラス、関数、変数等）の一覧を階層構造または平坦なリストとして出力する帳票である。

### 本帳票の処理概要

ドキュメントシンボル一覧は、D言語ソースファイル内に定義されたシンボル（クラス、関数、変数、構造体、列挙等）を解析し、その一覧をLSPクライアントに返す帳票である。階層構造対応・非対応の2つの出力形式をサポートする。

**業務上の目的・背景**：開発者がソースファイル内の構造を把握し、目的のシンボルに素早くナビゲートできるようにする。エディタのアウトラインビューやブレッドクラム機能に必要なデータを提供し、大規模ファイルにおけるコードナビゲーション効率を大幅に向上させる。

**帳票の利用シーン**：エディタでD言語ファイルを表示した際にアウトラインビューにシンボル一覧が表示される。開発者はアウトラインからシンボルをクリックして該当箇所にジャンプしたり、ブレッドクラムで現在位置の階層構造を確認できる。

**主要な出力内容**：
1. シンボル名（name）
2. シンボル種別（kind: クラス、関数、変数等）
3. 位置範囲（range / selectionRange）
4. コンテナ名（親シンボル名）
5. 非推奨タグ（deprecated属性付きシンボル）
6. 詳細情報（シグネチャ等）

**帳票の出力タイミング**：エディタからtextDocument/documentSymbolリクエストを受信した際にレスポンスとして返却される。

**帳票の利用者**：D言語開発者（エディタのアウトラインビュー/ブレッドクラムを使用する開発者）

## 帳票種別

シンボルレポート（LSPレスポンス）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | アウトラインビュー | LSP `textDocument/documentSymbol` | ファイル表示時に自動リクエスト |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | JSON-RPC（LSPプロトコル） |
| 用紙サイズ | N/A（デジタル出力） |
| 向き | N/A |
| ファイル名 | N/A（ストリーム出力） |
| 出力方法 | textDocument/documentSymbolレスポンス |
| 文字コード | UTF-8 |

### PDF固有設定

N/A

### Excel固有設定

N/A

## 帳票レイアウト

### レイアウト概要

クライアントのhierarchicalDocumentSymbolSupport設定に応じて2つの形式で出力する。

```
┌────────────────────────────────────────┐
│  階層構造形式 (DocumentSymbol[])        │
├────────────────────────────────────────┤
│  DocumentSymbol                         │
│    ├─ name: string                      │
│    ├─ kind: SymbolKind                  │
│    ├─ range: TextRange                  │
│    ├─ selectionRange: TextRange         │
│    └─ children: DocumentSymbol[]        │
│                                         │
│  平坦リスト形式 (SymbolInformation[])   │
├────────────────────────────────────────┤
│  SymbolInformation                      │
│    ├─ name: string                      │
│    ├─ kind: SymbolKind                  │
│    ├─ location: Location                │
│    └─ containerName: string             │
└────────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | textDocument.uri | 対象ドキュメントのURI | DocumentSymbolParamsのリクエストパラメータ | URI文字列 |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | name | シンボル名 | DefinitionElement.name | 文字列 | - |
| 2 | kind | シンボル種別 | convertFromDscannerType(def.type, def.name) | SymbolKind列挙値 | - |
| 3 | location.range | シンボルの位置範囲 | def.range[0]/range[1] -> movePositionBytes() | TextRange | - |
| 4 | containerName | 親シンボル名 | def.attributes["struct"/"class"/"enum"/"union"] | 文字列 | - |
| 5 | tags | シンボルタグ | "deprecation"属性がある場合deprecated_ | SymbolTag配列 | - |
| 6 | detail | 詳細情報（シグネチャ） | def.attributes["signature"/"detail"] | 文字列 | - |

### フッター部

N/A

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| 言語ID | document.getLanguageId == "d" であること | Yes |
| DscannerComponent有効 | hasBest!DscannerComponentがtrueであること | Yes |
| 非verboseフィルタ | 階層/平坦リストの非verboseモードではisVerboseType以外のみ出力 | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | DscannerComponent.listDefinitionsの出力順（ソースコード出現順） | 昇順 |

### 改ページ条件

N/A

## データベース参照仕様

### 参照テーブル一覧

本帳票はデータベースを使用しない。

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| N/A | - | - |

### テーブル別参照項目詳細

N/A

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| kind | convertFromDscannerType(def.type, def.name) | - | DScanner定義タイプからLSP SymbolKindへ変換 |
| extendedType | convertExtendedFromDscannerType(def.type) | - | SymbolKindEx（test等の拡張種別） |
| range | movePositionBytes(def.range[0]) 〜 movePositionBytes(def.range[1]) | - | バイトオフセットからPosition変換 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[documentSymbolリクエスト受信] --> B{hierarchicalSupport?}
    B -->|Yes| C[provideDocumentSymbolsHierarchical]
    B -->|No| D[provideDocumentSymbolsOld]
    C --> E[provideDocumentSymbolsOldを内部呼び出し]
    E --> F[シンボルをDocumentSymbol形式に変換]
    F --> G[親子関係を構築]
    G --> H[トップレベルシンボルのみ返却]
    D --> I[キャッシュ確認]
    I --> J{キャッシュヒット?}
    J -->|Yes| K[キャッシュから返却]
    J -->|No| L[DscannerComponent.listDefinitions呼び出し]
    L --> M[DefinitionElement一覧をループ]
    M --> N[makeSymbolInfoExでSymbolInformationEx生成]
    N --> O[キャッシュに格納]
    O --> P[結果返却]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| コンポーネント未登録 | DscannerComponentが利用できない | なし | null返却 |
| 非D言語ファイル | 言語IDが"d"でない | なし | null返却 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 1ファイルあたり数十〜数百シンボル |
| 目標出力時間 | PerDocumentCacheによりキャッシュヒット時は数ミリ秒以内 |
| 同時出力数上限 | ドキュメント単位でキャッシュ管理 |

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

- ソースファイルの構文解析のみ行い、外部リソースへのアクセスは行わない

## 備考

- PerDocumentCacheにより、同一ドキュメントへの繰り返しリクエストはキャッシュから応答（行69, 75-77）
- verboseモードとnon-verboseモードの2種類のキャッシュを保持（行64-67）
- 階層構造形式は平坦リストから親子関係を構築して生成（行139-178）
- selectionRangeはrange.endをstart.lineに制限（行154-156）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | protoext.d | `source/served/lsp/protoext.d` | SymbolInformationEx構造体（行202-222）: nameからdowncast()まで |
| 1-2 | protoext.d | `source/served/lsp/protoext.d` | SymbolKindEx列挙（行180-199）: test等の拡張シンボル種別 |
| 1-3 | protoext.d | `source/served/lsp/protoext.d` | DocumentSymbolParamsEx構造体（行155-177）: verboseフラグ付きのパラメータ |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | symbol_search.d | `source/served/commands/symbol_search.d` | provideDocumentSymbols関数（行51-61）: 階層/平坦の出力形式分岐 |

**主要処理フロー**:
1. **行54-57**: hierarchicalDocumentSymbolSupportの確認
2. **行58**: 階層対応時 -> provideDocumentSymbolsHierarchical
3. **行60**: 非対応時 -> provideDocumentSymbolsOld + downcast

#### Step 3: 平坦リスト生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | symbol_search.d | `source/served/commands/symbol_search.d` | provideDocumentSymbolsOld関数（行70-106）: DscannerComponent経由のシンボル取得とキャッシュ管理 |
| 3-2 | symbol_search.d | `source/served/commands/symbol_search.d` | makeSymbolInfoEx関数（行108-128）: DefinitionElementからSymbolInformationExへの変換 |

**主要処理フロー**:
- **行75-77**: キャッシュヒット時はキャッシュから返却
- **行82-84**: DscannerComponent.listDefinitionsでシンボル定義一覧取得
- **行91-101**: 各定義をmakeSymbolInfoExで変換（range算出、kind変換、属性抽出）

#### Step 4: 階層構造生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | symbol_search.d | `source/served/commands/symbol_search.d` | provideDocumentSymbolsHierarchical関数（行139-178）: 平坦リストから階層構造への変換 |

**主要処理フロー**:
- **行145**: provideDocumentSymbolsOldで平坦リスト取得
- **行146-158**: SymbolInformationExからDocumentSymbolInfoへ変換
- **行160-173**: containerNameベースの親子関係構築
- **行175**: トップレベル（parent未設定）のシンボルのみフィルタ

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

```
provideDocumentSymbols(params)                    [symbol_search.d:51]
    |
    +-- [hierarchical] provideDocumentSymbolsHierarchical() [symbol_search.d:139]
    |       +-- provideDocumentSymbolsOld()         [symbol_search.d:145]
    |       +-- 親子関係構築ループ                   [symbol_search.d:160-173]
    |
    +-- [flat] provideDocumentSymbolsOld()           [symbol_search.d:70]
            +-- documentSymbolsCacheOld.cached()     [symbol_search.d:75]
            +-- DscannerComponent.listDefinitions()  [symbol_search.d:82-84]
            +-- [foreach def] makeSymbolInfoEx()     [symbol_search.d:98]
            |       +-- convertFromDscannerType()
            |       +-- convertExtendedFromDscannerType()
            |       +-- movePositionBytes()
            +-- documentSymbolsCacheOld.store()      [symbol_search.d:103]
```

### データフロー図

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

documentSymbolリクエスト ──> provideDocumentSymbols()  ──> JsonValue
(textDocument.uri)

D言語ソースコード ──────────> DscannerComponent         ──> DefinitionElement[]
                              .listDefinitions()

DefinitionElement[] ────────> makeSymbolInfoEx()        ──> SymbolInformationEx[]

SymbolInformationEx[] ──────> provideDocumentSymbols    ──> DocumentSymbol[] (階層)
                              Hierarchical()                 or
                              provideDocumentSymbolsOld() ──> SymbolInformation[] (平坦)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| symbol_search.d | `source/served/commands/symbol_search.d` | ソース | ドキュメントシンボル一覧の主処理 |
| protoext.d | `source/served/lsp/protoext.d` | ソース | SymbolInformationEx、DocumentSymbolParamsEx等の型定義 |
| types.d | `source/served/types.d` | ソース | 共通型定義 |
| extension.d | `source/served/extension.d` | ソース | LSPサーバー拡張機能・capabilities |
