# 機能設計書 72-設定管理

## 概要

本ドキュメントは、Lua Language Serverにおける設定管理機能の設計を記述する。この機能は、.luarc.jsonやクライアント設定などの各種設定の読み込み・保存・監視を行い、サーバー全体の動作を制御する中核システムである。

### 本機能の処理概要

**業務上の目的・背景**：Lua Language Serverは多様な設定オプション（ランタイムバージョン、診断ルール、フォーマット設定など）を持ち、プロジェクトやユーザーごとに柔軟にカスタマイズする必要がある。設定管理機能は、これらの設定を一元管理し、変更をリアルタイムに反映することで、開発者の生産性を向上させる。

**機能の利用シーン**：
- サーバー起動時の設定読み込み
- .luarc.json の編集による設定変更
- VSCode設定パネルからの設定変更
- ワークスペースごとの設定適用
- 設定変更に伴う診断・補完機能の動作変更

**主要な処理内容**：
1. 設定テンプレートに基づく型検証とデフォルト値の適用
2. スコープ（グローバル/ワークスペース/フォルダ）別の設定管理
3. 設定変更イベントの発火と購読機能
4. 複数設定ソース（クライアント、ローカルファイル、RCファイル）の統合
5. NULL値の特別処理（設定の明示的な無効化）

**関連システム・外部連携**：
- LSPクライアント（VSCode等）との設定同期
- ワークスペース管理システム（スコープ管理）
- 各機能モジュールへの設定配信

**権限による制御**：特になし。すべてのユーザーが設定を変更可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 31 | 設定変更 | 主画面 | Lua設定を変更するコマンド処理 |
| 32 | 設定取得 | 主画面 | 現在のLua設定を取得するコマンド処理 |
| 45 | APIレポート | 参照画面 | 設定情報の取得 |

## 機能種別

設定管理 / データ変換処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| uri | uri | No | 設定を適用するスコープのURI | 有効なファイルURI |
| key | string | Yes | 設定キー（例: Lua.runtime.version） | テンプレートに存在するキー |
| value | any | Yes | 設定値 | テンプレートの型チェッカーで検証 |

### 入力データソース

- LSPクライアントからのworkspace/didChangeConfiguration通知
- .luarc.json ファイル
- config.lua ファイル（レガシー）
- VSCode設定（settings.json）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| value | any | 設定値（ローダーで変換済み） |
| rawValue | any | 生の設定値（変換前） |
| changed | boolean | 設定変更の有無 |

### 出力先

- 内部設定テーブル（config.now, config.raw）
- 設定変更イベントの購読者

## 処理フロー

### 処理シーケンス

```
1. 設定リクエストの受信
   └─ キーとスコープの特定
2. テンプレートから設定定義を取得
   └─ 型チェッカー、ローダー、デフォルト値
3. 値の検証
   └─ checkerで型・enum検証
4. 値の変換
   └─ loaderで内部形式に変換
5. スコープ別テーブルに保存
   └─ now（変換後）とraw（変換前）
6. 変更イベントの発火
   └─ 購読者への通知
```

### フローチャート

```mermaid
flowchart TD
    A[設定リクエスト受信] --> B[スコープ特定]
    B --> C{テンプレート存在?}
    C -->|No| D[エラー: 未知のキー]
    C -->|Yes| E[型チェック実行]
    E --> F{検証成功?}
    F -->|No| G[デフォルト値を適用]
    F -->|Yes| H[ローダーで変換]
    G --> I[テーブルに保存]
    H --> I
    I --> J{値が変化?}
    J -->|No| K[終了]
    J -->|Yes| L[イベント発火]
    L --> M[購読者に通知]
    M --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-72-01 | スコープ優先順位 | override > folder > linked > fallback の順で設定を検索 | 常時 |
| BR-72-02 | NULL値処理 | m.NULL値は明示的なnil設定として扱う | 常時 |
| BR-72-03 | デフォルト適用 | 検証失敗時はテンプレートのデフォルト値を適用 | 検証失敗時 |
| BR-72-04 | 遅延イベント | 設定変更イベントはタイマーで遅延して一括通知 | 常時 |

### 計算ロジック

**スコープ解決ロジック**:
```lua
local function getScope(uri, key)
    -- overrideスコープを最優先
    if scope.override then return scope.override end
    -- URIからフォルダ/リンクスコープを取得
    if uri then
        local scp = scope.getFolder(uri) or scope.getLinkedScope(uri)
        if scp and scp:get('config.raw')[key] ~= nil then
            return scp
        end
    end
    -- fallbackスコープ
    return scope.fallback
end
```

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

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

本機能はメモリ上のテーブル操作のみで、データベース操作は行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 未知のキー | テンプレートに存在しないキー | assertでエラー |
| - | 型不一致 | checkerで検証失敗 | デフォルト値を適用 |
| - | 設定ファイル読込失敗 | ファイルアクセスエラー | エラーログ出力、前回値を維持 |

### リトライ仕様

リトライは行わない。エラー時はデフォルト値または前回値を使用。

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

トランザクション管理は不要。各設定操作は独立して実行される。

## パフォーマンス要件

- 設定変更イベントはタイマーで遅延し、連続変更を一括処理
- スコープごとにキャッシュされた設定テーブルを使用

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

- ローカル設定ファイル（config.lua）はLuaコードとして実行されるため、信頼できるソースのみ使用
- クライアントからの設定は型検証を経由して適用

## 備考

- config.luaはレガシーフォーマットであり、config.json（.luarc.json）への移行が推奨される
- テンプレートでの型定義はLuaのメタテーブル演算子オーバーロードを活用

---

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

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

### 推奨読解順序

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

まず、設定テンプレートの構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | template.lua | `script/config/template.lua` | 6-47行目: config.unitクラスの定義、checker/loader/caller |
| 1-2 | template.lua | `script/config/template.lua` | 186-438行目: 全設定項目のテンプレート定義 |

**読解のコツ**: `>>` 演算子はデフォルト値設定、`<<` 演算子はenum定義。Type.Boolean, Type.String等は型チェッカー。

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

設定の取得・設定の公開APIを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | config.lua | `script/config/config.lua` | 157-170行目: m.get - 設定値取得 |
| 2-2 | config.lua | `script/config/config.lua` | 73-88行目: m.set - 設定値設定 |

**主要処理フロー**:
1. **157-170行目**: get - スコープを解決し、nowテーブルから値を取得
2. **73-88行目**: set - 検証・変換後にテーブルに保存、イベント発火

#### Step 3: スコープ管理を理解する

設定のスコープ解決ロジック。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | config.lua | `script/config/config.lua` | 31-51行目: getScope関数 - スコープ優先順位 |
| 3-2 | config.lua | `script/config/config.lua` | 188-197行目: getNowTable, getRawTable |

#### Step 4: 設定更新と通知を理解する

設定変更時の処理フロー。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | config.lua | `script/config/config.lua` | 199-245行目: m.update - 設定一括更新 |
| 4-2 | config.lua | `script/config/config.lua` | 247-271行目: m.watch, m.event - イベント管理 |

**主要処理フロー**:
- **252-263行目**: イベントはタイマーで遅延して一括通知

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

```
m.get / m.set (公開API)
    │
    ├─ getScope(uri, key)
    │      ├─ scope.override チェック
    │      ├─ scope.getFolder(uri)
    │      ├─ scope.getLinkedScope(uri)
    │      └─ scope.fallback
    │
    ├─ template[key]
    │      ├─ checker(value) - 型検証
    │      └─ loader(value) - 値変換
    │
    └─ update(scp, key, nowValue, rawValue)
           │
           └─ m.event(uri, key, value, oldValue)
                  └─ timer.wait → callback呼び出し
```

### データフロー図

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

クライアント設定 ──────▶ ┌─────────────┐
                        │             │
.luarc.json ──────────▶ │ m.update()  │ ──────▶ config.now
                        │             │         (変換後テーブル)
config.lua ───────────▶ │  expand()   │
                        │             │ ──────▶ config.raw
                        │  checker()  │         (生テーブル)
                        │             │
                        │  loader()   │ ──────▶ イベント通知
                        └─────────────┘         (購読者へ)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| config.lua | `script/config/config.lua` | ソース | 設定管理のメインモジュール |
| template.lua | `script/config/template.lua` | ソース | 設定項目のテンプレート定義 |
| loader.lua | `script/config/loader.lua` | ソース | 設定ファイルの読み込み処理 |
| init.lua | `script/config/init.lua` | ソース | モジュールエクスポート |
| env.lua | `script/config/env.lua` | ソース | 環境変数設定 |
| scope.lua | `script/workspace/scope.lua` | ソース | スコープ管理 |
