# 機能設計書 83-clang-query

## 概要

本ドキュメントは、clang-queryツールの機能設計について記述する。clang-queryは、AST（抽象構文木）に対してインタラクティブにクエリを実行し、マッチャー式を使用してコードパターンを検索・探索するツールである。

### 本機能の処理概要

clang-queryは、Clang ASTマッチャーをインタラクティブに試すためのツールである。ソースコードを解析してASTを構築し、ユーザーが入力したマッチャー式でASTノードを検索して結果を表示する。

**業務上の目的・背景**：ASTマッチャーを使用したリファクタリングツールやスタティック解析ツールを開発する際、マッチャー式のテストと調整が必要になる。clang-queryは、コンパイル・実行サイクルなしにマッチャー式を対話的に試すことができ、開発効率を大幅に向上させる。

**機能の利用シーン**：
- ASTマッチャー式の開発とデバッグ
- ソースコード内の特定パターンの検索
- コードベースの構造理解
- リファクタリングツール開発の事前調査

**主要な処理内容**：
1. ソースファイルのAST構築
2. クエリのパース（match, let, set等）
3. ASTマッチャーの実行
4. バインドされたノードの表示（診断/プリント/詳細AST）
5. 名前付きマッチャーの管理

**関連システム・外部連携**：Clang LibTooling APIとAST Matchers Dynamic APIを使用。LineEditorによるコマンドライン補完をサポート。

**権限による制御**：特になし。読み取り対象ファイルへのアクセス権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | CLIツール | 主画面 | インタラクティブプロンプトまたはコマンドライン経由での実行 |

## 機能種別

コード探索 / 開発支援

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -c | string list | No | 実行するコマンド | 有効なクエリ構文 |
| -f | string list | No | コマンドを読み込むファイル | ファイルが存在すること |
| --preload | string | No | プリロード後インタラクティブモード | ファイルが存在すること |
| --use-color | bool | No | カラー出力を使用 | - |
| source files | string list | Yes | 対象ソースファイル | ファイルが存在すること |

### 入力データソース

- ソースファイル（.h, .c, .cpp等）
- compilation database（compile_commands.json）
- コマンドファイル（-f指定時）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| マッチ結果 | stdout | バインドされたノードの情報 |
| 診断出力 | stdout | ソース位置情報付きのマッチ表示 |
| 詳細AST | stdout | ASTダンプ形式での出力 |

### 出力先

- 標準出力

## 処理フロー

### 処理シーケンス

```
1. コマンドライン引数の解析
   └─ CommonOptionsParserでオプションとソースファイルを取得

2. AST構築
   └─ ClangTool.buildASTsで全ソースファイルを解析

3. QuerySessionの初期化
   └─ 構築されたASTを保持するセッションを作成

4. クエリ実行モードの選択
   ├─ -c指定時：コマンドを順次実行
   ├─ -f指定時：ファイルからコマンドを読み込み実行
   └─ それ以外：インタラクティブモード

5. インタラクティブモードの場合
   └─ LineEditorでプロンプト表示
   └─ 補完機能の設定
   └─ ユーザー入力を受け付けループ

6. クエリのパースと実行
   └─ QueryParser::parseでクエリをパース
   └─ Query::runで実行
   └─ 結果を出力

7. 終了条件の確認
   └─ quitコマンドまたはEOFで終了
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[コマンドライン解析]
    B --> C{-cと-fの同時指定?}
    C -->|Yes| D[エラー: 同時指定不可]
    D --> Z[終了]
    C -->|No| E[ClangTool.buildASTs]
    E --> F{AST構築成功?}
    F -->|失敗| G[エラー終了]
    F -->|成功/部分成功| H[QuerySession初期化]
    H --> I{実行モード?}
    I -->|-c指定| J[コマンド順次実行]
    I -->|-f指定| K[ファイルからコマンド読み込み]
    I -->|なし| L{--preload指定?}
    L -->|Yes| M[プリロード実行]
    M --> N[インタラクティブモード]
    L -->|No| N
    N --> O[LineEditor初期化]
    O --> P[ユーザー入力待ち]
    P --> Q{入力あり?}
    Q -->|No/EOF| Z
    Q -->|Yes| R[QueryParser::parse]
    R --> S[Query::run]
    S --> T{Terminate?}
    T -->|Yes| Z
    T -->|No| P
    J --> Z
    K --> Z
    G --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 排他オプション | -cと-fは同時に指定不可 | 両オプション指定時 |
| BR-02 | preloadとの排他 | -c/-fと--preloadは同時に指定不可 | 複数指定時 |
| BR-03 | bind-root | デフォルトでルートマッチャーを"root"にバインド | 設定変更可能 |
| BR-04 | 出力モード | diag/print/detailed-astの3種類から選択可能 | set outputで変更 |

### 計算ロジック

マッチ結果の表示：
- DiagOutput：ソース位置と"binds here"メッセージを表示
- PrintOutput：バインドされたノードのpretty-print
- DetailedASTOutput：ASTDumperによる詳細ダンプ

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

該当なし（ファイルベースの操作のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | 排他オプション | -cと-f両方指定 | どちらか一方を使用 |
| 1 | AST構築失敗 | ソースファイルのコンパイルエラー | ソースを修正 |
| - | パースエラー | 無効なクエリ構文 | 正しい構文で再入力 |
| - | マッチャーエラー | 無効なマッチャー式 | マッチャー式を修正 |

### リトライ仕様

インタラクティブモードではエラー後も入力を継続可能。コマンドモードではエラー時に即座に終了。

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

該当なし。読み取り専用の操作のみ。

## パフォーマンス要件

特に規定なし。AST構築はソースファイルサイズに依存。

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

- ソースファイルへの読み取りアクセスが必要
- 任意のソースコードを解析可能

## 備考

- 対話モードでは入力補完機能あり（Tab補完）
- let コマンドで名前付きマッチャーを定義可能
- traversal kindでAST走査方法を変更可能（AsIs/IgnoreUnlessSpelledInSource）
- プロファイリング機能（enable-profile）あり

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | QuerySession.h | `clang-tools-extra/clang-query/QuerySession.h` | セッション状態の管理（AST参照、出力設定、名前付き値） |
| 1-2 | Query.h | `clang-tools-extra/clang-query/Query.h` | Queryクラス階層とQueryKind列挙型 |

**読解のコツ**: QuerySessionはASTへの参照と各種出力フラグ（PrintOutput, DiagOutput, DetailedASTOutput）を保持。BindRoot, PrintMatcher, EnableProfile等の設定も管理。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ClangQuery.cpp | `clang-tools-extra/clang-query/tool/ClangQuery.cpp` | main関数とモード選択ロジック |

**主要処理フロー**:
1. **84-91行目**: CommonOptionsParserでコマンドライン解析
2. **93-102行目**: -cと-f、--preloadの排他チェック
3. **104-134行目**: ClangTool初期化とAST構築
4. **136行目**: QuerySession初期化
5. **138-165行目**: 実行モード分岐（-c/-f/インタラクティブ）
6. **154-164行目**: LineEditorによるインタラクティブループ

#### Step 3: クエリパース処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | QueryParser.h | `clang-tools-extra/clang-query/QueryParser.h` | パーサーの公開API |
| 3-2 | QueryParser.cpp | `clang-tools-extra/clang-query/QueryParser.cpp` | クエリパースとコード補完実装 |

**主要処理フロー**:
- **29-47行目**: lexWord - トークン分割
- **51-90行目**: LexOrCompleteWord - 補完対応のトークン処理
- **207-360行目**: doParse - メインパースロジック
- **362-373行目**: parse/complete - 公開API

#### Step 4: クエリ実行処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Query.cpp | `clang-tools-extra/clang-query/Query.cpp` | 各Queryクラスのrun実装 |

**主要処理フロー**:
- **36-76行目**: HelpQuery::run - ヘルプ表示
- **78-81行目**: QuitQuery::run - セッション終了
- **109-203行目**: MatchQuery::run - マッチ実行とバインド表示
- **205-212行目**: LetQuery::run - 名前付き値の登録/削除
- **219-238行目**: FileQuery::run - ファイルからのコマンド読み込み

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

```
main (ClangQuery.cpp)
    │
    ├─ CommonOptionsParser::create
    │
    ├─ ClangTool::buildASTs
    │      └─ ASTUnit生成
    │
    ├─ QuerySession初期化
    │
    └─ 実行モード分岐
           │
           ├─ -c: QueryParser::parse → Query::run
           │
           ├─ -f: FileQuery::run
           │       └─ QueryParser::parse → Query::run (繰り返し)
           │
           └─ インタラクティブ:
                   │
                   ├─ LineEditor::setListCompleter
                   │       └─ QueryParser::complete
                   │
                   └─ LineEditor::readLine
                          └─ QueryParser::parse
                                 └─ Query::run
                                        ├─ MatchQuery::run
                                        │      ├─ MatchFinder::addDynamicMatcher
                                        │      ├─ MatchFinder::matchAST
                                        │      └─ 結果表示 (Diag/Print/DetailedAST)
                                        ├─ LetQuery::run
                                        ├─ SetQuery::run
                                        ├─ HelpQuery::run
                                        └─ QuitQuery::run
```

### データフロー図

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

source files ───┐
                │
compile_commands.json ─┼─▶ ClangTool::buildASTs ─▶ vector<ASTUnit>
                │               │
                │               ▼
                │        QuerySession
                │               │
query command ─────────▶ QueryParser::parse ─▶ QueryRef
                               │
                               ▼
                        Query::run
                               │
                    ┌──────────┼──────────┐
                    ▼          ▼          ▼
              MatchQuery   LetQuery   SetQuery
                    │          │          │
                    ▼          │          │
            MatchFinder        │          │
                    │          │          │
                    ▼          ▼          ▼
              BoundNodes   NamedValues  Session設定
                    │
        ┌───────────┼───────────┐
        ▼           ▼           ▼
    DiagOutput  PrintOutput  DetailedAST
        │           │           │
        └───────────┴───────────┘
                    │
                    ▼
                 stdout
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ClangQuery.cpp | `clang-tools-extra/clang-query/tool/ClangQuery.cpp` | ソース | mainエントリーポイント |
| Query.h | `clang-tools-extra/clang-query/Query.h` | ヘッダ | Queryクラス階層定義 |
| Query.cpp | `clang-tools-extra/clang-query/Query.cpp` | ソース | Queryクラス実装 |
| QueryParser.h | `clang-tools-extra/clang-query/QueryParser.h` | ヘッダ | パーサーAPI |
| QueryParser.cpp | `clang-tools-extra/clang-query/QueryParser.cpp` | ソース | パーサー実装 |
| QuerySession.h | `clang-tools-extra/clang-query/QuerySession.h` | ヘッダ | セッション状態管理 |
| CMakeLists.txt | `clang-tools-extra/clang-query/CMakeLists.txt` | ビルド | ビルド設定 |
