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

## 概要

本ドキュメントは、LSPプロトコルの `textDocument/documentColor` リクエストに対応するドキュメントカラー検出機能の設計を記述する。DMLファイル内のHEXカラーコードを検出し、カラー情報を返却する。

### 本機能の処理概要

**業務上の目的・背景**：vibe.d DML（Diet Markup Language）ファイルでは、HEXカラーコード（例: `#ff0000`）が頻繁に使用される。エディタ上でこれらのカラーコードを視覚的なカラースウォッチとして表示することで、開発者が色の確認・選択を直感的に行えるようにする。LSP仕様の `textDocument/documentColor` に準拠する。

**機能の利用シーン**：開発者がDMLファイルをエディタで開いた際に、エディタがバックグラウンドでこのリクエストを送信し、ファイル内の全てのHEXカラーコードの位置とRGB(A)値を取得する。エディタはコード横にカラースウォッチを表示する。

**主要な処理内容**：
1. リクエストパラメータからテキストドキュメントを取得する
2. ドキュメントの言語がDMLであることを確認する
3. 正規表現でHEXカラーコード（#RRGGBB または #AARRGGBB）をマッチする
4. マッチした各カラーコードについて、テキスト範囲とRGBA色値を算出する
5. ColorInformation配列として返却する

**関連システム・外部連携**：外部コンポーネントへの依存はない。正規表現による自己完結的なテキスト解析処理である。

**権限による制御**：特になし。DMLファイルに対してのみ処理が実行される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 21 | カラー表示（textDocument/documentColor） | 主画面 | DMLファイル内のHEXカラーコードを検出しカラー情報を返却する |

## 機能種別

データ取得処理（テキストパターンマッチング・データ変換）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| params.textDocument | TextDocumentIdentifier | Yes | 対象ドキュメントの識別子（URI） | ドキュメントが管理下に存在すること |

### 入力データソース

LSPクライアントからの `textDocument/documentColor` リクエスト。テキストドキュメントの生テキストはDocumentManagerから取得する。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result | ColorInformation[] | カラー情報の配列。DMLファイル以外の場合はnull |
| ColorInformation.range | TextRange | HEXカラーコードのテキスト範囲 |
| ColorInformation.color.red | double | 赤成分（0.0-1.0） |
| ColorInformation.color.green | double | 緑成分（0.0-1.0） |
| ColorInformation.color.blue | double | 青成分（0.0-1.0） |
| ColorInformation.color.alpha | double | アルファ成分（0.0-1.0、デフォルト1.0） |

### 出力先

LSPクライアントへのレスポンスとして返却する。

## 処理フロー

### 処理シーケンス

```
1. ドキュメント取得
   └─ documents[params.textDocument.uri]でドキュメント取得
2. 言語チェック
   └─ getLanguageId != "dml" の場合はnullを返却
3. 正規表現マッチング
   └─ colorRegex (#RRGGBB形式, #AARRGGBB形式, ダブルクォート囲みも対応) で全マッチ取得
4. 各マッチの処理
   └─ ダブルクォート囲みの場合は除去
   └─ movePositionBytesでバイトオフセットをPosition変換（start, end）
   └─ 8文字（AARRGGBB）の場合: 先頭2文字をalpha、残り6文字をRGBに分解
   └─ 6文字（RRGGBB）の場合: 6文字をRGBに分解（alphaはデフォルト1.0）
   └─ 各成分を0-255から0.0-1.0に正規化
5. 結果返却
   └─ ColorInformation配列を返却
```

### フローチャート

```mermaid
flowchart TD
    A[textDocument/documentColor リクエスト受信] --> B[ドキュメント取得]
    B --> C{言語がDML?}
    C -->|No| D[null を返却]
    C -->|Yes| E[正規表現でHEXカラー検索]
    E --> F{マッチあり?}
    F -->|No| G[空配列を返却]
    F -->|Yes| H[各マッチを処理]
    H --> I{8文字?}
    I -->|Yes| J[AARRGGBB解析]
    I -->|No| K[RRGGBB解析]
    J --> L[ColorInformationに追加]
    K --> L
    L --> M[次のマッチへ]
    M --> H
    L --> N[ColorInformation配列を返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-33-01 | DML限定 | DMLファイル以外ではnullを返却する | 常時 |
| BR-33-02 | HEXカラー形式 | `#RRGGBB` または `#AARRGGBB`形式（大文字小文字不問）のみ検出 | 常時 |
| BR-33-03 | クォート対応 | ダブルクォートで囲まれたカラーコード（`"#RRGGBB"`形式）も検出対象 | 常時 |
| BR-33-04 | 色値正規化 | 各成分は0-255の整数値を255.0で除算して0.0-1.0に正規化 | 常時 |

### 計算ロジック

- `color.red = hex(RR) / 255.0`
- `color.green = hex(GG) / 255.0`
- `color.blue = hex(BB) / 255.0`
- `color.alpha = hex(AA) / 255.0`（8文字形式の場合）

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

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

本機能にデータベース操作は存在しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 非DMLファイル | ドキュメントの言語IDが "dml" でない | nullを返却 |

### リトライ仕様

リトライは行わない。

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

トランザクション管理は不要（読み取り専用処理）。

## パフォーマンス要件

正規表現マッチングのみのため、高速に処理される。大規模DMLファイルでも問題ない性能が期待される。

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

特になし。ローカルファイルの読み取り専用処理のみ。

## 備考

- 正規表現パターン: `#([0-9a-fA-F]{2}){3,4}|"#([0-9a-fA-F]{2}){3,4}"` はコンパイル時正規表現（ctRegex）で定義される。
- サーバー初期化時にcolorProviderがDocumentColorOptions.initとしてサーバーケイパビリティに登録される（extension.d 306行目）。
- 将来的にマルチスレッド化する場合、ドキュメントのロック処理が必要（コード内にコメントあり）。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | protocol.d | `protocol/source/served/lsp/protocol.d` | DocumentColorParams（3546行目）、ColorInformation（3552行目）、Color構造体（3559行目）を確認 |

**読解のコツ**: Color構造体のフィールドはred, green, blue, alphaの4つで、全てdouble型（0.0-1.0）。alphaのデフォルト値は1.0。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | color.d | `source/served/commands/color.d` | `provideDocumentColor` 関数（12-55行目）がLSPリクエストハンドラ |

**主要処理フロー**:
1. **9行目**: `colorRegex` - コンパイル時正規表現の定義
2. **14行目**: `documents[params.textDocument.uri]` でドキュメント取得
3. **15-16行目**: DML言語チェック
4. **28行目**: `matchAll(document.rawText, colorRegex)` で全マッチ取得
5. **31-32行目**: ダブルクォート囲みの除去
6. **37-39行目**: `movePositionBytes` でテキスト範囲を算出
7. **42-49行目**: HEX値からRGBA色値に変換
8. **50行目**: `ColorInformation` を結果配列に追加

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

```
provideDocumentColor (color.d:12)
    |
    +-- documents[uri] (テキストドキュメント取得)
    |
    +-- document.getLanguageId (言語チェック: "dml")
    |
    +-- matchAll(document.rawText, colorRegex)
    |       (正規表現マッチング)
    |
    +-- document.movePositionBytes (バイト→Position変換)
    |
    +-- HEX→RGBA変換 (to!int(16) / 255.0)
```

### データフロー図

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

DocumentColorParams   ──▶  provideDocumentColor          ──▶  ColorInformation[]
  .textDocument.uri         |                                    .range (TextRange)
                            +-- DMLテキスト取得                   .color (Color)
                            +-- 正規表現マッチ
                            |     #RRGGBB / #AARRGGBB
                            +-- HEX→RGBA変換
                            +-- バイト→Position変換
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| color.d | `source/served/commands/color.d` | ソース | LSPリクエストハンドラ（メイン処理） |
| protocol.d | `protocol/source/served/lsp/protocol.d` | ソース | DocumentColorParams/ColorInformation/Color等のLSP型定義 |
| extension.d | `source/served/extension.d` | ソース | サーバーケイパビリティにcolorProviderを登録（306行目） |
| types.d | `source/served/types.d` | ソース | 共通型定義・documentsへのアクセス |
