# 機能設計書 48-コンテキストキー

## 概要

本ドキュメントは、VS Codeのコンテキストキー機能に関する機能設計書である。条件付きコマンド実行を制御するためのコンテキスト式評価システムを定義する。

### 本機能の処理概要

コンテキストキー機能は、現在のエディタ状態、アクティブなビュー、選択状態等に基づいて動的にコマンドやメニューの有効/無効を制御する式評価システムである。

**業務上の目的・背景**：UIの状態に応じて適切なコマンドやメニュー項目のみを有効にすることで、ユーザーの混乱を防ぎ、直感的な操作体験を提供する。拡張機能も独自のコンテキストキーを定義可能。

**機能の利用シーン**：
- メニュー項目の条件付き表示（when句）
- キーバインディングの条件付き有効化
- ビューの条件付き表示
- コマンドの条件付き実行

**主要な処理内容**：
1. コンテキストキー式のパース
2. コンテキストキー式の評価
3. コンテキストキーの設定・更新
4. コンテキストキー変更イベントの発火
5. スコープ付きコンテキストキーの管理

**関連システム・外部連携**：
- メニューサービス（when句評価）
- キーバインディングサービス（when句評価）
- コマンドサービス（precondition評価）
- ビューサービス（when句評価）
- 拡張機能（setContext API）

**権限による制御**：コンテキストキーはスコープに応じて階層的に管理される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 全画面共通 | API連携 | when句によるUI状態制御 |

## 機能種別

プラットフォームサービス / 式評価

## 入力仕様

### 入力パラメータ

#### コンテキストキー式の例

| 式 | 意味 |
|-----|------|
| `editorTextFocus` | エディタにテキストフォーカスがある |
| `editorLangId == typescript` | 言語がTypeScript |
| `resourceScheme == file` | ファイルスキームがfile |
| `!editorReadonly` | エディタが読み取り専用でない |
| `a && b` | aかつb |
| `a \|\| b` | aまたはb |
| `a =~ /pattern/` | 正規表現マッチ |
| `a in b` | bにaが含まれる |

### ContextKeyExprType列挙

| 値 | 説明 |
|-----|------|
| False | 常にfalse |
| True | 常にtrue |
| Defined | キーが定義されている |
| Not | 否定 |
| Equals | 等価比較 |
| NotEquals | 不等価比較 |
| And | 論理積 |
| Or | 論理和 |
| Regex | 正規表現マッチ |
| In | 包含チェック |
| Greater | 大なり |
| Smaller | 小なり |

### 定数コンテキストキー

| キー | 値 |
|-----|-----|
| isMac | プラットフォーム判定 |
| isLinux | プラットフォーム判定 |
| isWindows | プラットフォーム判定 |
| isWeb | Web環境判定 |
| isChrome | ブラウザ判定 |
| isFirefox | ブラウザ判定 |
| isSafari | ブラウザ判定 |
| isEdge | ブラウザ判定 |

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ContextKeyExpression | type | パース済み式 |
| boolean | primitive | 評価結果 |

### 出力先

- 呼び出し元（evaluate結果）
- イベントリスナー（onDidChangeContext）

## 処理フロー

### 処理シーケンス

```
1. 式のパース
   └─ Parser.parse() で文字列をASTに変換
   └─ Scanner で字句解析
   └─ 構文解析でContextKeyExpression生成

2. 式の評価
   └─ evaluate(context) でIContext上で評価
   └─ 各ノードタイプに応じた評価ロジック

3. コンテキストキーの設定
   └─ createKey() でキーを作成
   └─ set() で値を設定
   └─ onDidChangeContext イベント発火

4. 変更監視
   └─ contextKeyChanged() でキー変更を監視
   └─ 影響を受ける式を再評価
```

### 構文文法（EBNF）

```ebnf
expression ::= or
or ::= and { '||' and }*
and ::= term { '&&' term }*
term ::= '!' (KEY | true | false | parenthesized) | primary
primary ::= 'true' | 'false' | parenthesized
          | KEY '=~' REGEX
          | KEY [ ('==' | '!=' | '<' | '<=' | '>' | '>=' | 'not' 'in' | 'in') value ]
parenthesized ::= '(' expression ')'
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-48-01 | 定数置換 | プラットフォーム定数は起動時に評価 | substituteConstants時 |
| BR-48-02 | スコープ継承 | 子スコープは親スコープのキーを継承 | キー評価時 |
| BR-48-03 | 短絡評価 | And/OrはtrueまたはfalseでShort-circuit | 式評価時 |
| BR-48-04 | 正規表現回復 | 正規表現パースエラー時に回復可能 | regexParsingWithErrorRecovery設定時 |

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

コンテキストキーはメモリ内で管理され、データベースには保存されない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| EMPTY_STRING | パースエラー | 空の式 | parsingErrorsに追加 |
| UNEXPECTED_TOKEN | パースエラー | 予期しないトークン | parsingErrorsに追加 |
| UNEXPECTED_EOF | パースエラー | 式の途中で終了 | parsingErrorsに追加 |
| LEXING_ERROR | 字句解析エラー | 不正な字句 | lexingErrorsに追加 |

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

トランザクション制御は行わない。コンテキストキーの変更は即座に反映される。

## パフォーマンス要件

- パース済み式のキャッシュ
- 定数式の事前評価
- 変更影響範囲の効率的な検出

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

- コンテキストキー式は信頼されたソースからのみ評価
- 正規表現はサンドボックス化なし（信頼前提）

## 備考

- package.jsonのwhen句で広く使用
- 拡張機能はvscode.commands.executeCommand('setContext', key, value)でキー設定可能

---

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

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

### 推奨読解順序

#### Step 1: 式型を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | contextkey.ts | `src/vs/platform/contextkey/common/contextkey.ts` | ContextKeyExprType（38-55行目）、ContextKeyExpression（83-89行目） |

**主要処理フロー**:
1. **16-27行目**: `CONSTANT_VALUES` で定数マップ
2. **38-55行目**: `ContextKeyExprType` 列挙型
3. **71-81行目**: `IContextKeyExpression` インターフェース
4. **83-89行目**: `ContextKeyExpression` 型定義

#### Step 2: パーサーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | contextkey.ts | `src/vs/platform/contextkey/common/contextkey.ts` | Parser クラス（173行目〜） |

**主要処理フロー**:
- **92-127行目**: EBNF構文定義（コメント）
- **173行目〜**: `Parser` クラス
- **204-232行目**: `parse()` メソッド

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

```
ContextKeyExpr (static methods)
    │
    ├─ deserialize(str) ──▶ Parser.parse() ──▶ ContextKeyExpression
    │
    └─ 各種ファクトリメソッド
           ├─ true() ──▶ ContextKeyTrueExpr
           ├─ false() ──▶ ContextKeyFalseExpr
           ├─ equals(k, v) ──▶ ContextKeyEqualsExpr
           ├─ and(...) ──▶ ContextKeyAndExpr
           └─ or(...) ──▶ ContextKeyOrExpr

IContextKeyService
    │
    ├─ createKey() ──▶ IContextKey<T>
    │      └─ set(value)
    │
    └─ onDidChangeContext ──▶ 変更通知
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| contextkey.ts | `src/vs/platform/contextkey/common/contextkey.ts` | ソース | 式定義・パーサー |
| scanner.ts | `src/vs/platform/contextkey/common/scanner.ts` | ソース | 字句解析 |
| contextKeyService.ts | `src/vs/platform/contextkey/browser/contextKeyService.ts` | ソース | サービス実装 |
