# 機能設計書 20-ドキュメントシンボル (textDocument/documentSymbol)

## 概要

本ドキュメントは、Lua Language Serverにおける「ドキュメントシンボル」機能の設計を記述する。この機能は、LSPの`textDocument/documentSymbol`リクエストに対応し、ファイル内のシンボル一覧を階層的に表示する機能を提供する。

### 本機能の処理概要

ドキュメントシンボル機能は、ファイル内で定義されている全てのシンボル（変数、関数、クラス、テーブル等）を階層構造で返す機能である。エディタのアウトラインビューやブレッドクラムで使用され、コード構造の把握に役立つ。

**業務上の目的・背景**：大きなLuaファイルでは、どのような関数やテーブルが定義されているかを把握するのが困難になる。この機能により、ファイル全体のシンボル構造をツリー形式で確認でき、目的のシンボルへの素早いナビゲーションが可能になる。

**機能の利用シーン**：
- ファイル内の関数一覧を確認したい場合
- テーブルの構造を階層的に確認したい場合
- アウトラインビューでシンボルをナビゲートしたい場合
- ブレッドクラムで現在位置を確認したい場合

**主要な処理内容**：
1. ファイル内の全ソースノードを走査
2. シンボルとして表示すべきノードを特定（local, setfield, function等）
3. 各シンボルの名前、種別、範囲を構築
4. テーブルや関数内のネストしたシンボルを子として関連付け
5. 階層構造を構築して返す

**関連システム・外部連携**：
- LSPプロトコルの`textDocument/documentSymbol`リクエストハンドラ
- エディタのアウトラインビュー/ブレッドクラム機能

**権限による制御**：特になし

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 12 | ドキュメントシンボル | 主機能 | ファイル内のシンボル一覧を階層的に表示する主処理 |

## 機能種別

情報表示 / ナビゲーション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| uri | uri | Yes | 対象ファイルのURI | 有効なファイルURI |

### 入力データソース

- 対象ファイルのAST状態（files.getState）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| name | string | シンボル名 |
| detail | string | 詳細情報（型、値など） |
| kind | SymbolKind | シンボルの種別 |
| range | Range | シンボルの全体範囲 |
| selectionRange | Range | シンボル名の範囲（選択範囲） |
| children | DocumentSymbol[] | 子シンボルの配列 |

### SymbolKind

| 種別 | 説明 | 対象ノード |
|------|------|-----------|
| Function | 関数 | setmethod, setfield（function値） |
| Method | メソッド | setmethod |
| Variable | 変数 | local, setlocal, setglobal, setfield |
| Constant | 定数 | funcargs内のlocal |
| Boolean | 真偽値 | boolean値を持つシンボル |
| String | 文字列 | string値を持つシンボル |
| Number | 数値 | number/integer値を持つシンボル |
| Array | 配列 | 配列形式のテーブル |
| Object | オブジェクト | オブジェクト形式のテーブル |
| Package | パッケージ | if/while/for/repeat等のブロック |

### 出力先

LSPレスポンスとしてクライアントに返される

## 処理フロー

### 処理シーケンス

```
1. ASTを取得
   └─ files.getState(uri)でファイル状態を取得
2. 全ソースノードを走査
   └─ guide.eachSourceで全ノードを処理
3. 各ソースに対してシンボルを構築
   └─ buildSource()でシンボルを生成
   └─ buildValue(): 値を持つシンボル
   └─ buildAnonymous(): 匿名関数/テーブル
   └─ buildBlock(): 制御構造ブロック
4. シンボルリストをソート
   └─ valueRangeまたはselectionRangeでソート
5. 階層構造を構築
   └─ packChild()で子シンボルを関連付け
6. 結果を変換
   └─ 範囲をLSP形式に変換
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B[AST取得]
    B --> C{AST存在?}
    C -->|No| D[nil を返す]
    C -->|Yes| E[全ソースを走査]
    E --> F[各ソースをループ]
    F --> G{シンボル対象?}
    G -->|No| F
    G -->|Yes| H[シンボル構築]
    H --> I{構築成功?}
    I -->|No| F
    I -->|Yes| J[symbolsに追加]
    J --> K{全ソース処理完了?}
    K -->|No| F
    K -->|Yes| L[シンボルをソート]
    L --> M[階層構造を構築]
    M --> N[範囲を変換]
    N --> O[結果を返す]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 対象ノード型 | local, setlocal, setglobal, setfield, setmethod, tablefield, tableindex, tableexp, function, table, if, while, for, repeat | シンボル構築時 |
| BR-02 | 名前クリッピング | 複数行にまたがる名前は最後の行を「...」付きで表示 | 名前構築時 |
| BR-03 | テーブルフィールド表示 | テーブルの先頭5フィールドまでを表示、それ以上は「...(+N)」 | テーブル詳細構築時 |
| BR-04 | 配列判定 | 最後のフィールドがtableexpかつtindexが要素数と一致する場合は配列 | シンボル種別判定時 |
| BR-05 | 匿名関数表示 | return文やcallargs内の無名関数は「return」「呼び出し先名」として表示 | 匿名シンボル構築時 |
| BR-06 | ブロック表示 | if/while/for/repeat等の制御構造もシンボルとして表示 | ブロック構築時 |

### シンボル種別判定ルール

| 条件 | 種別 |
|------|------|
| funcargs内のlocal | Constant |
| setmethod（function値） | Method |
| その他のfunction値 | Function |
| boolean値 | Boolean |
| string値 | String |
| number/integer値 | Number |
| 配列形式のテーブル | Array |
| オブジェクト形式のテーブル | Object |
| その他 | Variable |
| if/while/for/repeat | Package |

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

この機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 無視 | ASTが取得できない | nilを返す |
| - | 無視 | シンボルが構築できない | そのノードをスキップ |

### リトライ仕様

リトライは行わない。

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

該当なし

## パフォーマンス要件

- 全ソースを走査するため、大きなファイルでは時間がかかる可能性がある
- 1000ノードごとにawait.delay()を実行して応答性を確保
- LSPの応答性を維持するためprogress表示（0.5秒以上の処理時）

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

特になし

## 備考

- エディタのアウトラインビューでツリー形式で表示される
- ブレッドクラム機能で現在のシンボル階層が表示される
- 空の名前は1文字のスペースに置換される（LSP仕様）

---

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

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

### 推奨読解順序

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

シンボル情報の構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | document-symbol.lua | `script/core/document-symbol.lua` | シンボル構造（202-209行目） |

**読解のコツ**: `valueRange`は子シンボルの範囲計算に使用される内部プロパティで、LSP出力時には削除される。

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

メイン関数の構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | document-symbol.lua | `script/core/document-symbol.lua` | makeSymbol関数（337-357行目） |
| 2-2 | document-symbol.lua | `script/core/document-symbol.lua` | メイン関数（402-411行目） |
| 2-3 | provider.lua | `script/provider/provider.lua` | textDocument/documentSymbol ハンドラ（825-875行目） |

**主要処理フロー**:
1. **338-340行目**: AST取得
2. **348-354行目**: 全ソースを走査してシンボル構築
3. **389-398行目**: packSymbolsでソートと階層構築
4. **403-410行目**: 結果を返す

#### Step 3: シンボル構築を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | document-symbol.lua | `script/core/document-symbol.lua` | buildName関数（18-41行目） - 名前生成 |
| 3-2 | document-symbol.lua | `script/core/document-symbol.lua` | buildValue関数（100-210行目） - 値シンボル構築 |
| 3-3 | document-symbol.lua | `script/core/document-symbol.lua` | buildAnonymous関数（212-265行目） - 匿名シンボル構築 |
| 3-4 | document-symbol.lua | `script/core/document-symbol.lua` | buildBlock関数（267-312行目） - ブロック構築 |
| 3-5 | document-symbol.lua | `script/core/document-symbol.lua` | buildSource関数（314-334行目） - 型別分岐 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | document-symbol.lua | `script/core/document-symbol.lua` | packChild関数（359-386行目） |
| 4-2 | document-symbol.lua | `script/core/document-symbol.lua` | packSymbols関数（389-399行目） |

**主要処理フロー**:
- **packSymbols**: シンボルをvalueRange/selectionRangeでソート
- **packChild**: 再帰的に子シンボルを構築

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

```
provider.lua ('textDocument/documentSymbol' ハンドラ)
    │
    └─ document-symbol.lua (メイン関数)
           │
           ├─ files.getState() [AST取得]
           │
           └─ makeSymbol()
                  │
                  ├─ guide.eachSource() [全ソース走査]
                  │
                  └─ buildSource()
                         ├─ buildValue()
                         │      ├─ buildName() [名前生成]
                         │      ├─ buildFunctionParams() [関数引数]
                         │      ├─ buildTable() [テーブル詳細]
                         │      └─ buildArray() [配列詳細]
                         │
                         ├─ buildAnonymous()
                         │      └─ buildFunctionParams()
                         │
                         └─ buildBlock()
                                └─ if/while/for/repeat処理
```

### データフロー図

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

URI ──────────────────────┐
                          │
                          ▼
                   ┌────────────────┐
                   │   AST取得      │
                   └────────────────┘
                          │
                          ▼
                   ┌────────────────┐
                   │ 全ソース走査   │
                   │ (eachSource)  │
                   └────────────────┘
                          │
                          ▼
                   ┌────────────────┐
                   │ シンボル構築   │
                   │ (buildSource) │
                   └────────────────┘
                          │
                          ▼
                   ┌────────────────┐
                   │    ソート      │
                   └────────────────┘
                          │
                          ▼
                   ┌────────────────┐
                   │ 階層構造構築   │
                   │ (packChild)   │
                   └────────────────┘
                          │
                          ▼
                   [DocumentSymbol[]]
                      - name
                      - detail
                      - kind
                      - range
                      - selectionRange
                      - children
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| document-symbol.lua | `script/core/document-symbol.lua` | ソース | ドキュメントシンボルのメイン実装 |
| provider.lua | `script/provider/provider.lua` | ソース | LSPハンドラ、シンボルリクエストを処理 |
| substring.lua | `script/core/substring.lua` | ソース | 部分文字列取得ユーティリティ |
| define.lua | `script/proto/define.lua` | ソース | SymbolKind定義 |
| guide.lua | `script/parser/guide.lua` | ソース | AST操作ユーティリティ（eachSource） |
| await.lua | `script/await.lua` | ソース | 非同期処理（delay） |
| converter.lua | `script/proto/converter.lua` | ソース | LSP位置変換 |
