# 機能設計書 47-ドキュメントカラー (textDocument/documentColor)

## 概要

本ドキュメントは、Lua Language Serverにおけるドキュメントカラー機能（textDocument/documentColor）の設計仕様を記述する。この機能は、ソースコード内の色定義を検出し、エディタのカラーピッカー表示に必要な情報を提供する。

### 本機能の処理概要

ドキュメントカラー機能は、Luaソースコード内の文字列リテラルから色コード（8桁ARGB形式または7桁#RGB形式）を検出し、その位置と色情報をエディタに提供する。エディタはこの情報を使用して、コード中に色のプレビューを表示したり、カラーピッカーを起動したりできる。

**業務上の目的・背景**：ゲーム開発やUI開発では、色の値をLuaコードで直接指定することが多い。色コードを手動で解読するのは困難であり、視覚的なプレビューがあると開発効率が向上する。この機能により、色コードの隣にカラースウォッチを表示し、クリックでカラーピッカーを開くことができる。

**機能の利用シーン**：
- 8桁の16進数文字列（ARGB形式）を色として表示したい場合
- #で始まる6桁の16進数文字列（#RRGGBB形式）を色として表示したい場合
- コード内の色定義を視覚的に確認したい場合
- カラーピッカーで色を変更したい場合

**主要な処理内容**：
1. クライアントからdocumentColorリクエストを受信
2. ドキュメントのASTを走査
3. 文字列リテラルを検出し、色パターンにマッチするか確認
4. マッチした場合、色値をRGBA形式に変換
5. 色情報と位置をクライアントに返却

**関連システム・外部連携**：
- パーサー（script/parser）からのAST情報
- LSPクライアントとのJSON-RPC通信

**権限による制御**：特に権限による制御は行われない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 20 | カラー表示 | 主機能 | ファイル内の色定義を検出・表示する主処理 |

## 機能種別

エディタ補助機能 / カラー表示

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| textDocument.uri | string | Yes | 対象ドキュメントのURI | 有効なファイルURIであること |

### 入力データソース

- LSPクライアントからのJSON-RPCリクエスト
- ファイルシステム上のLuaソースコード（AST経由）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ColorInformation[] | array | 色情報の配列 |
| ColorInformation.range | Range | 色コードの位置 |
| ColorInformation.color | Color | RGBA色値（各成分0.0〜1.0） |

Color構造体:
| 項目名 | 型 | 説明 |
|--------|-----|------|
| red | number | 赤成分（0.0〜1.0） |
| green | number | 緑成分（0.0〜1.0） |
| blue | number | 青成分（0.0〜1.0） |
| alpha | number | アルファ成分（0.0〜1.0） |

### 出力先

- LSPクライアントへのJSON-RPCレスポンス

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ textDocument/documentColorメッセージを受信

2. ワークスペース準備確認
   └─ workspace.awaitReady(uri)

3. ドキュメント状態取得
   └─ files.getState(uri)

4. 色検出
   └─ core/color.lua colors()呼び出し
      └─ guide.eachSource()でAST走査
         └─ 各文字列リテラルをisColor()で判定

5. 位置変換
   └─ converter.packRange()

6. レスポンス返却
   └─ ColorInformation配列を返却
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B[workspace.awaitReady]
    B --> C{ドキュメント状態取得}
    C -->|失敗| D[null返却]
    C -->|成功| E[core/color.lua colors]
    E --> F[guide.eachSource]
    F --> G{文字列リテラル?}
    G -->|No| H{次のソース}
    G -->|Yes| I{isColor判定}
    I -->|No| H
    I -->|Yes| J[textToColor/hexTextToColor]
    J --> K[colorValues配列に追加]
    K --> H
    H -->|あり| G
    H -->|なし| L[converter.packRange]
    L --> M[レスポンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-47-01 | 8桁ARGB形式 | 8桁16進数（AARRGGBB）を色として認識 | 文字列長=8 |
| BR-47-02 | 7桁#RGB形式 | #で始まる6桁16進数（#RRGGBB）を色として認識 | 文字列長=7 |
| BR-47-03 | 範囲調整 | source.start+1〜source.finish-1（引用符除外） | 常時 |

### 計算ロジック

ARGB変換（textToColor）:
```lua
return {
    alpha = tonumber(colorText:sub(1, 2), 16) / 255,
    red   = tonumber(colorText:sub(3, 4), 16) / 255,
    green = tonumber(colorText:sub(5, 6), 16) / 255,
    blue  = tonumber(colorText:sub(7, 8), 16) / 255,
}
```

#RGB変換（hexTextToColor）:
```lua
return {
    alpha = 255,  -- 固定
    red   = tonumber(colorText:sub(2, 3), 16) / 255,
    green = tonumber(colorText:sub(4, 5), 16) / 255,
    blue  = tonumber(colorText:sub(6, 7), 16) / 255,
}
```

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

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

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | null返却 | ドキュメント状態が取得できない | クライアントは色表示を行わない |
| - | null返却 | テキストが取得できない | クライアントは色表示を行わない |

### リトライ仕様

リトライは行わない。

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

該当なし（メモリ内処理のみ）

## パフォーマンス要件

- AST走査で全文字列をチェックするため、大規模ファイルでは処理時間が増加する可能性あり

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

- 特になし

## 備考

- colorProvider: trueでcapability宣言
- 機能No.48のカラープレゼンテーションと連携

---

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

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

### 推奨読解順序

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

Color構造体の定義を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | color.lua | `script/core/color.lua` | Color型定義（56-60行目）とColorValue型定義（62-65行目） |

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

LSPリクエストハンドラを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | provider.lua | `script/provider/provider.lua` | documentColorの登録（1183-1209行目） |

**主要処理フロー**:
1. **1184-1186行目**: capability定義（colorProvider: true）
2. **1190-1191行目**: ワークスペース準備とドキュメント状態取得
3. **1196行目**: core/color.lua colors()呼び出し
4. **1201-1206行目**: 結果のLSP形式変換

#### Step 3: コアロジックを理解する

色検出ロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | color.lua | `script/core/color.lua` | isColor, textToColor, hexTextToColor, colors関数 |

**主要処理フロー**:
- **4-5行目**: 色パターン定義（8桁ARGB, 6桁#RGB）
- **8-20行目**: isColor() - 色パターン判定
- **25-32行目**: textToColor() - ARGB形式の変換
- **36-43行目**: hexTextToColor() - #RGB形式の変換
- **68-92行目**: colors() - AST走査と色検出

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

```
provider.lua (m.register 'textDocument/documentColor')
    │
    ├─ workspace.awaitReady(uri)
    │
    ├─ files.getState(uri)
    │
    └─ core/color.lua colors(uri)
           │
           ├─ files.getState(uri)
           │      └─ AST取得
           │
           ├─ files.getText(uri)
           │      └─ テキスト取得
           │
           └─ guide.eachSource(state.ast, callback)
                  │
                  └─ source.type == 'string'
                         │
                         ├─ isColor(source)
                         │      ├─ colorPattern (8桁)
                         │      └─ hex6Pattern (#6桁)
                         │
                         └─ textToColor / hexTextToColor
                                └─ ColorValue生成
```

### データフロー図

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

LSPリクエスト             provider.lua
  └─ uri          ───▶    ├─ workspace.awaitReady()
                          └─ files.getState()
                                    │
                                    ▼
                          color.lua colors()
                          guide.eachSource()
                                    │
                          ┌─────────┴─────────┐
                          ▼                   ▼
                    'string'型?           その他
                          │                   │
                          ▼                   └─ skip
                    isColor()?
                          │
                    ┌─────┴─────┐
                    ▼           ▼
               8桁ARGB      #6桁RGB
                    │           │
                    ▼           ▼
             textToColor  hexTextToColor
                    │           │
                    └─────┬─────┘
                          ▼
                    ColorValue配列
                          │
                          ▼
                    converter.packRange()
                          │
                          ▼                  ColorInformation[]
                    LSPレスポンス ────────▶  ├─ range
                                              └─ color (r,g,b,a)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| provider.lua | `script/provider/provider.lua` | ソース | LSPリクエストハンドラの登録・実行 |
| color.lua | `script/core/color.lua` | ソース | 色検出・変換のコアロジック |
| converter.lua | `script/proto/converter.lua` | ソース | 位置・範囲変換 |
| files.lua | `script/files.lua` | ソース | ファイル管理・状態取得 |
| guide.lua | `script/parser/guide.lua` | ソース | AST走査ユーティリティ |
