# 機能設計書 36-バリアントリスト取得（getVariants）

## 概要

本ドキュメントは、Tailwind CSSにおける利用可能な全バリアントリストの生成機能（getVariants）の機能設計を記述する。

### 本機能の処理概要

DesignSystemに登録されたすべてのバリアント（hover、focus、responsive等の修飾子）の一覧を生成する機能である。各バリアントの名前、種別、利用可能な値、セレクタ生成関数を含むVariantEntryのリストを返す。

**業務上の目的・背景**：Tailwind CSSのIDE統合（IntelliSense）において、開発者がバリアントプレフィックス（hover:、md:、dark:等）を入力する際のオートコンプリートを実現するために、利用可能なすべてのバリアントの一覧が必要である。本機能は、各バリアントの名前だけでなく、そのバリアントが生成するCSSセレクタ文字列も提供することで、プレビュー表示やドキュメント生成にも活用できる。

**機能の利用シーン**：
- VS Code拡張機能でのバリアントプレフィックスのオートコンプリート
- バリアントが生成するセレクタのプレビュー表示
- DesignSystem.getVariants()メソッドの呼び出し時

**主要な処理内容**：
1. DesignSystemのvariantsからエントリを列挙する
2. arbitrary種別のバリアントを除外する
3. 各バリアントの種別（static/functional/compound）に応じてVariantEntryを構築する
4. セレクタ生成関数を構築し、バリアント適用後のCSSセレクタ文字列を返せるようにする

**関連システム・外部連携**：DesignSystem APIの一部として公開される。IDE拡張機能（Tailwind CSS IntelliSense）から利用される。

**権限による制御**：権限による制御はない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面に直接関連しないAPI機能。IDEの補完UIに間接的に関連 |

## 機能種別

データ取得処理（バリアントリストの生成）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| design | DesignSystem | Yes | デザインシステムオブジェクト | 有効なDesignSystemインスタンスであること |

### 入力データソース

DesignSystemオブジェクトの`variants`プロパティから登録済みバリアントを取得する。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result | VariantEntry[] | バリアント情報のリスト |

VariantEntry構造:

| フィールド | 型 | 説明 |
|-----------|-----|------|
| name | string | バリアントのルート名（例: hover, md, dark） |
| isArbitrary | boolean | 任意値をサポートするか |
| values | string[] | 利用可能な値のリスト |
| hasDash | boolean | 値の前にダッシュ（-）が必要か（@バリアント以外はtrue） |
| selectors | (options?) => string[] | バリアント適用後のセレクタ文字列を返す関数 |

### 出力先

呼び出し元への戻り値として返される。

## 処理フロー

### 処理シーケンス

```
1. design.variants.entries()でバリアントを列挙
2. arbitrary種別のバリアントを除外
3. 各バリアントに対して:
   a. hasDashの決定（rootが'@'でない場合はtrue）
   b. design.variants.getCompletions()で利用可能な値を取得
   c. selectors関数の構築
      ├─ バリアント名の構築（root + value + modifier）
      ├─ design.parseVariant()でバリアントをパース
      ├─ applyVariant()でプレースホルダルールにバリアントを適用
      ├─ walk()でノードを走査しセレクタを収集
      └─ v3スタイルのネストされたセレクタ文字列を生成
   d. バリアント種別に応じてVariantEntryを構築
      ├─ static: isArbitrary = false
      ├─ functional: isArbitrary = true
      └─ compound: isArbitrary = true
4. VariantEntry[]を返す
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[variants.entries列挙]
    B --> C{arbitrary種別?}
    C -->|Yes| D[スキップ]
    C -->|No| E[hasDash判定]
    E --> F[getCompletionsで値取得]
    F --> G[selectors関数構築]
    G --> H{variant.kind判定}
    H -->|static| I[isArbitrary=false でVariantEntry追加]
    H -->|functional| J[isArbitrary=true でVariantEntry追加]
    H -->|compound| K[isArbitrary=true でVariantEntry追加]
    I --> B
    J --> B
    K --> B
    D --> B
    B --> L[VariantEntry配列を返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-36-01 | arbitrary除外 | arbitrary種別のバリアントはリストに含めない | variant.kind === 'arbitrary' |
| BR-36-02 | hasDash | ルート名が'@'の場合はhasDash=false（ダッシュ不要） | root === '@' |
| BR-36-03 | staticバリアント | isArbitrary=falseとしてリストに追加 | variant.kind === 'static' |
| BR-36-04 | functionalバリアント | isArbitrary=trueとしてリストに追加 | variant.kind === 'functional' |
| BR-36-05 | compoundバリアント | isArbitrary=trueとしてリストに追加 | variant.kind === 'compound' |
| BR-36-06 | セレクタのv3スタイル表示 | ネストされたルールをv3スタイルの`parent { child }`形式で表示する | selectors関数呼び出し時 |
| BR-36-07 | at-ruleの前置 | セレクタ生成時、at-ruleをstyleルールの前にソートする | selectors関数内 |
| BR-36-08 | &セレクタの除外 | セレクタが`&`のみの場合はパスから除外する | selectors関数内 |

### 計算ロジック

selectors関数のセレクタ構築:
1. バリアント名を構築: `root[-value][/modifier]`
2. プレースホルダルール`.__placeholder__`にバリアントを適用
3. 結果のASTをwalk()で走査し、リーフノード（子なしのrule/at-ruleノード）を収集
4. 各リーフのパスからセレクタ文字列を構築
5. at-ruleは`@media (...)` 形式、styleルールはセレクタ文字列
6. ネストされたセレクタを末尾から結合: `parent { child }`

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

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

データベース操作なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | セレクタ生成失敗 | parseVariantがnullを返す場合 | 空配列を返す |
| - | バリアント適用失敗 | applyVariantがnullを返す場合 | 空配列を返す |

### リトライ仕様

リトライは不要。

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

トランザクション管理なし。

## パフォーマンス要件

- selectors関数は遅延評価される（呼び出し時にのみ計算）
- バリアント数は通常数十から数百程度のため、列挙処理のコストは低い

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

特になし。

## 備考

- `@`で始まるバリアント（例: `@md`コンテナクエリ）はhasDash=falseとなり、値の前にダッシュが不要
- selectors関数はv3互換のセレクタ表現を返す。これはIntelliSenseの表示用であり、実際のCSS出力とは異なる場合がある

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | intellisense.ts | `packages/tailwindcss/src/intellisense.ts` | VariantEntry型定義（148-154行目） |
| 1-2 | intellisense.ts | `packages/tailwindcss/src/intellisense.ts` | SelectorOptions型定義（143-146行目） |

**読解のコツ**:
- `VariantEntry`: name, isArbitrary, values, hasDash, selectorsの5フィールド
- `selectors`はSelectorOptionsを受け取りstring[]を返す関数型
- SelectorOptionsにはoptionalなmodifierとvalueフィールドがある

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | intellisense.ts | `packages/tailwindcss/src/intellisense.ts` | `getVariants`関数（156-268行目） |

**主要処理フロー**:
1. **159行目**: `design.variants.entries()`でバリアントを列挙
2. **160行目**: `variant.kind === 'arbitrary'`のスキップ
3. **162行目**: `hasDash = root !== '@'`の判定
4. **163行目**: `design.variants.getCompletions(root)`で値リスト取得
5. **165-231行目**: `selectors`関数の定義
   - **166-168行目**: バリアント名の構築
   - **170行目**: `design.parseVariant(name)`
   - **175行目**: `styleRule('.__placeholder__', [])`でプレースホルダ生成
   - **178行目**: `applyVariant(node, variant, design.variants)`
   - **187-228行目**: walk()でセレクタ収集とv3スタイル結合
6. **233-264行目**: switch文でバリアント種別に応じたVariantEntry構築

#### Step 3: 依存関係を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | compile.ts | `packages/tailwindcss/src/compile.ts` | `applyVariant`関数 - バリアントのASTノードへの適用 |
| 3-2 | variants.ts | `packages/tailwindcss/src/variants.ts` | Variantsクラス - entries(), getCompletions()メソッド |

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

```
DesignSystem.getVariants (design-system.ts:173-175)
    │
    └─ getVariants (intellisense.ts:156)
           │
           ├─ design.variants.entries()
           │      └─ 登録済みバリアントの列挙
           │
           ├─ design.variants.getCompletions(root)
           │      └─ 値リストの取得
           │
           └─ selectors関数（遅延評価）
                  ├─ design.parseVariant(name)
                  ├─ styleRule('.__placeholder__', [])
                  ├─ applyVariant() (compile.ts)
                  └─ walk() (walk.ts)
                         └─ セレクタ文字列の収集・結合
```

### データフロー図

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

DesignSystem          ───▶ variants.entries()列挙         ───▶ VariantEntry[]
  .variants                 │
                            ├─ arbitrary除外
                            │
                            ├─ 各バリアントの処理
                            │   ├─ hasDash判定
                            │   ├─ 値リスト取得
                            │   └─ selectors関数構築
                            │
                            └─ VariantEntry配列構築      ───▶ [{name: "hover",
                                                                isArbitrary: false,
                                                                values: [],
                                                                hasDash: true,
                                                                selectors: fn},
                                                               ...]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| intellisense.ts | `packages/tailwindcss/src/intellisense.ts` | ソース | メイン処理: getVariants関数 |
| design-system.ts | `packages/tailwindcss/src/design-system.ts` | ソース | DesignSystem API: getVariantsメソッド公開 |
| variants.ts | `packages/tailwindcss/src/variants.ts` | ソース | Variantsクラス: entries(), getCompletions() |
| compile.ts | `packages/tailwindcss/src/compile.ts` | ソース | applyVariant関数 |
| ast.ts | `packages/tailwindcss/src/ast.ts` | ソース | styleRule関数（プレースホルダ生成） |
| walk.ts | `packages/tailwindcss/src/walk.ts` | ソース | ASTウォーカー（セレクタ収集） |
