# 画面設計書 41-AST可視化

## 概要

本ドキュメントは、Lua Language ServerのCLIコマンド「AST可視化」の画面設計書です。Luaソースコードの抽象構文木（AST: Abstract Syntax Tree）をGraphviz DOT形式で出力し、コード構造を視覚的に把握できるようにする機能を提供します。

### 本画面の処理概要

**業務上の目的・背景**：開発者がLuaコードの構文構造を理解するために、ソースコードをパースして得られる抽象構文木を視覚化する必要があります。特にコンパイラや言語処理系の開発者、教育目的でLuaの構文を学習する開発者にとって、ASTを図として閲覧できることは非常に有用です。本機能は、Luaパーサーが生成するASTをGraphviz形式で出力し、GraphvizツールやオンラインDOTビューアを使用して視覚的に確認できるようにします。

**画面へのアクセス方法**：コマンドラインから `lua-language-server --visualize=<ファイルパス>` を実行することでアクセスします。指定されたLuaファイルのASTがGraphviz DOT形式で標準出力に出力されます。

**主要な操作・処理内容**：
1. コマンドライン引数でLuaソースファイルのパスを受け取る
2. 指定されたファイルを読み込み、Luaパーサーでコンパイル（構文解析）する
3. 生成されたAST（抽象構文木）を再帰的に走査する
4. 各ASTノードをGraphviz DOT形式のノードとエッジに変換する
5. ノードには型情報、位置情報、ツールチップ（詳細属性）を含める
6. 完成したDOT形式のテキストを標準出力に出力する

**画面遷移**：CLIコマンドのため、画面遷移はありません。コマンド実行後、結果が標準出力に出力されて終了します。

**権限による表示制御**：ファイルシステムの読み取り権限が必要です。指定ファイルが存在しない場合やアクセス権限がない場合はエラーメッセージが標準エラー出力に出力されます。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 66 | Luaソースコード解析 | 主機能 | Luaコードの構文解析処理 |
| 67 | 構文木(AST)生成 | 主機能 | 抽象構文木をGraphviz形式で可視化するCLI処理 |

## 画面種別

CLIコマンド出力

## URL/ルーティング

コマンドラインオプション: `--visualize=<ファイルパス>`

## 入出力項目

| 項目名 | 入出力 | 型 | 必須 | 説明 |
|--------|--------|-----|------|------|
| ファイルパス | 入力 | 文字列 | Yes | AST可視化対象のLuaソースファイルパス |
| DOT出力 | 出力 | 文字列 | - | Graphviz DOT形式のAST表現 |
| エラーメッセージ | 出力 | 文字列 | - | ファイル読み込みエラー時のメッセージ |

## 表示項目

| 項目名 | 説明 | 形式 |
|--------|------|------|
| ノードID | ASTノードの一意識別子（型:開始位置:終了位置） | `type:start:finish` |
| ノードラベル | ノード型とキー名の表示 | `type\lkeyName\l` |
| ノードツールチップ | ノードの詳細属性（位置情報、プロパティ、子ノード情報） | 複数行テキスト |
| エッジ | 親子関係を示す矢印 | `"親ID" -> "子ID"` |

## イベント仕様

### 1-コマンド実行

コマンドライン引数 `--visualize=<ファイルパス>` を指定して実行すると、以下の処理が行われます：

1. `script/cli/visualize.lua` の `runCLI()` 関数がエントリーポイントとして呼び出される
2. グローバル変数 `VISUALIZE` から対象ファイルパスを取得
3. `io.open()` でファイルを開き、内容を読み込む
4. `visualizeAst()` 関数を呼び出してAST可視化を実行
5. `parser.compile()` でLuaコードをパースしてASTを生成
6. `getVisualizeVisitor()` で再帰的にASTを走査し、DOT形式に変換
7. 結果を `io.stdout` に出力

## データベース更新仕様

本機能はデータベースを使用しません。

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| - | - | - | データベース操作なし |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|---------|
| ERR_FILE_OPEN | エラー | `failed to open {file}: {err}` | 指定ファイルを開けない場合 |

## 例外処理

| 例外条件 | 処理内容 | 出力先 |
|---------|---------|--------|
| ファイルが存在しない | エラーメッセージを出力し、終了コード1を返す | 標準エラー出力 |
| ファイルアクセス権限がない | エラーメッセージを出力し、終了コード1を返す | 標準エラー出力 |
| 構文エラーのあるLuaファイル | パーサーの結果に基づきASTを生成（エラーリカバリ） | 標準出力 |

## 備考

- 出力されるDOT形式はGraphviz互換であり、`dot` コマンドや各種オンラインDOTビューアで表示可能
- ノードのツールチップには詳細なAST属性情報が含まれ、デバッグに有用
- 長い文字列は20文字に切り詰められ、改行は `\\n` にエスケープされる
- 子ノードが15個を超える場合は省略表示される
- Luaバージョンは `LUA_VER` グローバル変数で指定可能（デフォルト: Lua 5.4）

---

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

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

### 推奨読解順序

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

まず、パーサーが生成するAST（抽象構文木）のデータ構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | guide.lua | `script/parser/guide.lua` | `parser.object` クラスの定義（1-87行目）でASTノードの構造を理解。`type`, `start`, `finish`, `parent` などの基本プロパティを確認 |
| 1-2 | guide.lua | `script/parser/guide.lua` | `childMap` テーブル（132-196行目）で各ノードタイプの子要素構造を理解 |

**読解のコツ**: `parser.object` は全てのASTノードの基底型であり、`type` フィールドでノードの種類を判別します。`start` と `finish` は文字位置を表します。

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

処理の起点となるファイル・関数を特定します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | visualize.lua | `script/cli/visualize.lua` | CLIエントリーポイント。`runCLI()` 関数（94-104行目）がメイン処理 |

**主要処理フロー**:
1. **94行目**: `runCLI()` 関数の定義開始
2. **95行目**: `lang(LOCALE)` で言語設定を初期化
3. **96行目**: `_G['VISUALIZE']` からファイルパスを取得
4. **97-101行目**: ファイルオープンとエラーハンドリング
5. **102行目**: ファイル内容を全て読み込み
6. **103行目**: `visualizeAst()` を呼び出してAST可視化を実行

#### Step 3: AST可視化処理を理解する

AST可視化の中核処理を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | visualize.lua | `script/cli/visualize.lua` | `visualizeAst()` 関数（86-92行目）でDOT形式出力の全体フローを理解 |
| 3-2 | visualize.lua | `script/cli/visualize.lua` | `getVisualizeVisitor()` 関数（67-81行目）で再帰的AST走査ロジックを理解 |
| 3-3 | visualize.lua | `script/cli/visualize.lua` | `getNodeLabel()` 関数（57-65行目）でノードのDOT形式表現を理解 |
| 3-4 | visualize.lua | `script/cli/visualize.lua` | `getTooltip()` 関数（35-54行目）でツールチップ生成ロジックを理解 |

**主要処理フロー**:
- **86-92行目**: `visualizeAst()` でパーサーを呼び出し、DOT形式のヘッダー・フッターを出力
- **67-81行目**: `getVisualizeVisitor()` でクロージャを返し、再帰的にASTを走査
- **76-78行目**: `guide.eachChild()` で子ノードを列挙し、再帰呼び出し

#### Step 4: パーサー処理を理解する

Luaコードのパース処理を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | init.lua | `script/parser/init.lua` | パーサーモジュールのエクスポート構造を確認 |
| 4-2 | compile.lua | `script/parser/compile.lua` | `parser.compile()` の実装（visualize.luaの87行目で呼び出し） |

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

```
runCLI() [visualize.lua:94]
    │
    ├─ io.open(file) [97行目]
    │      └─ ファイル読み込み
    │
    └─ visualizeAst(code, io.stdout) [103行目]
           │
           ├─ parser.compile(code, 'Lua', 'Lua 5.4') [87行目]
           │      └─ AST生成
           │
           └─ getVisualizeVisitor(writer)(state.ast) [90行目]
                  │
                  ├─ getNodeLabel(node) [70行目]
                  │      │
                  │      ├─ guide.getKeyName(node) [58行目]
                  │      │
                  │      └─ getTooltip(node) [64行目]
                  │             │
                  │             └─ getTooltipLine(k, v) [複数呼び出し]
                  │
                  └─ guide.eachChild(node, callback) [76行目]
                         └─ visitNode(child, node) [再帰呼び出し]
```

### データフロー図

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

ファイルパス ───▶ io.open() ───▶ ファイル内容
                                        │
                                        ▼
                         parser.compile() ───▶ AST (state.ast)
                                                       │
                                                       ▼
                         getVisualizeVisitor() ───▶ DOT形式テキスト
                                                       │
                                                       ▼
                                              io.stdout (標準出力)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| visualize.lua | `script/cli/visualize.lua` | ソース | AST可視化CLIのメイン実装 |
| init.lua | `script/parser/init.lua` | ソース | パーサーモジュールのエントリーポイント |
| compile.lua | `script/parser/compile.lua` | ソース | Luaコードのコンパイル（パース）処理 |
| guide.lua | `script/parser/guide.lua` | ソース | AST操作のユーティリティ（eachChild, getKeyName等） |
| utility.lua | `script/utility.lua` | ソース | 汎用ユーティリティ関数（sortPairs等） |
| language.lua | `script/language.lua` | ソース | 多言語対応処理 |
