# 機能設計書 129-Docsシステム

## 概要

本ドキュメントは、JuliaのDocsシステムに関する機能設計書である。Docsシステムは `@doc` マクロによる docstring 定義とヘルプシステムを提供し、`base/docs/Docs.jl` を中核として実装されている。

### 本機能の処理概要

Docsシステムは、Julia のオブジェクト（関数、型、マクロ、モジュール等）にドキュメント文字列（docstring）を関連付け、検索・表示するための仕組みである。`@doc` マクロによるdocstringの定義と取得、ヘルプモード（`?`キー）からのドキュメント検索、`apropos` による全文検索を提供する。

**業務上の目的・背景**：プログラミング言語のドキュメンテーション機能は開発生産性に直結する。Julia のDocsシステムは、ソースコードとドキュメントを同一の場所で管理できるようにし、対話的なヘルプシステムと統合している。これにより開発者はREPLから即座にAPIドキュメントを参照でき、学習コストの低減と開発効率の向上を実現する。

**機能の利用シーン**：関数・型・マクロへのdocstringの付与、REPLヘルプモード（`?`キー）からのドキュメント検索、`@doc` マクロによるプログラムからのドキュメント取得、`apropos` による全文検索、Documenter.jl によるHTMLドキュメント生成のソースデータ提供。

**主要な処理内容**：
1. `@doc` マクロによるdocstringの定義（オブジェクトへの関連付け）
2. `@doc` マクロによるdocstringの取得
3. DocStr 型によるdocstring データの遅延パース管理
4. MultiDoc 型による関数のメソッドごとのdocstring管理
5. Binding 型によるオブジェクトの名前解決
6. キーワードのdocstring管理（keywords辞書）
7. `@__doc__` マクロによるマクロ展開時のdocstring挿入ポイント
8. モジュール単位のメタデータストレージ（META辞書）
9. hasdoc / undocumented_names によるドキュメント網羅性チェック
10. CoreDocs による起動時docstring保存（遅延読み込み対応）

**関連システム・外部連携**：REPL（ヘルプモード・docview.jl）、Markdown（docstringのパース・レンダリング）、Documenter.jl（HTMLドキュメント生成）。

**権限による制御**：特になし。すべてのユーザーが利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | Juliaプロンプト（julia>） | 遷移先機能 | 「?」キー押下によるヘルプモードへの遷移。helpmode()を介してdocstring検索・表示を起動 |
| 3 | ヘルプモード（help?>） | 主機能 | @docマクロで定義されたdocstringの検索・取得。helpmode()がDocs.doc/Docs.resolve等を呼び出す |

## 機能種別

ユーティリティ（ドキュメンテーション基盤）

## 入力仕様

### 入力パラメータ

#### @doc マクロ（docstring定義）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| str | String/Expr | Yes | docstring のテキスト（Markdown形式） | 文字列またはstring式 |
| expr | Expr | Yes | ドキュメント対象の定義式 | 関数/型/マクロ/モジュール等の定義 |

#### @doc マクロ（docstring取得）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| ex | Any | Yes | ドキュメントを取得する対象 | 名前解決可能なシンボル/式 |

### 入力データソース

Julia ソースコード内の `@doc` マクロ呼び出し、およびREPLヘルプモードからの入力。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| DocStr | Docs.DocStr | 生のテキストとメタデータを保持するdocstringオブジェクト |
| Markdown.MD | Markdown.MD | パース済みのMarkdownドキュメント |
| Binding | Docs.Binding | オブジェクトの名前バインディング |

### 出力先

REPLへのドキュメント表示、またはプログラムからのAPI呼び出しへの戻り値。

## 処理フロー

### 処理シーケンス

#### docstring定義フロー
```
1. @doc マクロの呼び出し（ソースコード中に記述）
   └─ docm(source, mod, meta, ex, define) の呼び出し
2. 式の解析とパターンマッチ
   └─ 関数定義/型定義/モジュール/キーワード等の判定（_docm関数）
3. Binding オブジェクトの構築
   └─ bindingexpr(namify(expr)) でモジュール・シンボルの解決
4. DocStr オブジェクトの構築
   └─ テキスト・メタデータ（パス、行番号、モジュール等）の格納
5. モジュールのMETA辞書への登録
   └─ doc!(__module__, binding, docstr, sig) の呼び出し
6. MultiDoc エントリの作成/更新
   └─ 型シグネチャ付きのdocstring登録
```

#### docstring取得フロー
```
1. @doc マクロまたはヘルプモードからの呼び出し
   └─ docm(source, mod, ex) の呼び出し（取得モード）
2. REPL.lookup_doc への委譲（REPL読み込み済みの場合）
   └─ REPL_MODULE_REF によるREPLモジュール参照
3. Binding の解決
   └─ _doc(binding, sig) による検索
4. 全モジュールのMETA辞書を走査
   └─ modules配列の順序で検索
5. DocStr の返却
   └─ パース済みMarkdownまたは生テキスト
```

### フローチャート

```mermaid
flowchart TD
    A["@doc ""str"" expr"] --> B[docm 呼び出し]
    B --> C{定義 or 取得?}
    C -->|定義| D[式パターンマッチ _docm]
    D --> E[Binding構築]
    E --> F[DocStr構築]
    F --> G["doc!() でMETAに登録"]
    C -->|取得| H{REPL読込済?}
    H -->|Yes| I[REPL.lookup_doc]
    H -->|No| J[simple_lookup_doc]
    I --> K[_doc でMETA検索]
    J --> K
    K --> L[DocStr返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-129-01 | 遅延パース | docstringのMarkdownパースは初回参照時まで遅延 | DocStr.objectがnothingの場合 |
| BR-129-02 | 上書き警告 | 既存docstringの上書き時に警告を出力（Main以外） | 同一binding・sigのdocstrが既存 |
| BR-129-03 | 定義順序保持 | メソッドのdocstringは定義順序で連結表示 | MultiDoc.orderで管理 |
| BR-129-04 | 型シグネチャマッチ | docstring取得時に型シグネチャで最適なdocを選択 | sig <: msig で判定 |
| BR-129-05 | エイリアス解決 | DataType/Functionのエイリアスを解決して検索 | aliasof関数で解決 |
| BR-129-06 | CoreDocs遅延読み込み | 起動時のdocstringはDocLinkedListに保存し後で読み込み | loaddocs関数で処理 |

### 計算ロジック

docstringの型シグネチャマッチは部分型判定（`sig <: msig`）で行われる。最初にマッチしたdocstringが返される（定義順序）。

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

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

データベースは使用しない。モジュール単位のIdDict（META辞書）でインメモリ管理。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ErrorException | ドキュメント不可能な式に@docを適用 | docerror関数が呼ばれる。@__doc__の使用を検討 |
| - | ErrorException | binding :: typesig のdocstrが見つからない | docstr関数でエラー。binding/sigの正確性を確認 |

### リトライ仕様

リトライは不要。

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

トランザクションは使用しない。META辞書への登録はモジュール評価の一部として実行。

## パフォーマンス要件

docstringの遅延パースにより、プリコンパイルイメージのサイズを削減する。多数のモジュールのMETA辞書を線形走査するため、大量のモジュールがロードされた環境ではdocstring検索に時間がかかる可能性がある。

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

特筆すべきセキュリティ要件はない。docstringの評価はソースコードの一部として安全に処理される。

## 備考

- Docsシステムは `base/docs/` ディレクトリに定義されている
- Julia 1.11以降、docstringの取得にはREPL stdlibのロードが必要
- `Core.@doc` はCoreモジュールで定義されるブートストラップマクロであり、`Docs.docm` に差し替えられる（802行目 `Core.atdoc!(docm)`）
- basedocs.jl にBaseの組み込みオブジェクトのdocstringが定義されている（101,921バイト）
- intrinsicsdocs.jl にCore.Intrinsicsのdocstringが定義されている

---

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

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

### 推奨読解順序

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

Docsシステムの中核データ構造を理解することが最初のステップ。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Docs.jl | `base/docs/Docs.jl` | **165-169行目**: DocStr構造体 - text(SimpleVector), object(Any), data(Dict)の3フィールド |
| 1-2 | Docs.jl | `base/docs/Docs.jl` | **220-227行目**: MultiDoc構造体 - order(Vector{Type})で定義順序、docs(IdDict)で型シグネチャ付きdocstring |
| 1-3 | bindings.jl | `base/docs/bindings.jl` | **1-13行目**: Binding構造体 - mod(Module)とvar(Symbol)でオブジェクトを識別 |

**読解のコツ**: DocStr の `text` フィールドは Core.SimpleVector であり、遅延パース用の生テキストを保持する。`object` は初回パース後にMarkdownオブジェクトが格納される。

#### Step 2: ブートストラップ機構を理解する

Julia起動時のdocstring登録は特殊なリンクリスト経由で行われる。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | core.jl | `base/docs/core.jl` | **7-12行目**: DocLinkedList構造体。起動初期のdocstringを連結リストで保存 |
| 2-2 | core.jl | `base/docs/core.jl` | **15-18行目**: CoreDocs.doc!関数。DOCS グローバル変数にdocstringを蓄積 |
| 2-3 | core.jl | `base/docs/core.jl` | **26-37行目**: CoreDocs.docm関数。ブートストラップ用の簡易@doc実装 |

**主要処理フロー**:
- **14行目**: `global DOCS = DocLinkedList()` 空のリストで初期化
- **16行目**: 新しいdocstringをリストの先頭に追加
- **27行目**: 定義式をQuoteNodeで保存し、後でDocs.loaddocsで処理

#### Step 3: メインDocsモジュールを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Docs.jl | `base/docs/Docs.jl` | **77-78行目**: modules配列とMETA(gensym(:meta))のグローバルストレージ |
| 3-2 | Docs.jl | `base/docs/Docs.jl` | **81-99行目**: meta/initmeta関数。モジュールごとのIdDictの初期化と取得 |
| 3-3 | Docs.jl | `base/docs/Docs.jl` | **237-263行目**: doc!関数。docstringのMETA辞書への登録処理 |
| 3-4 | Docs.jl | `base/docs/Docs.jl` | **685-691行目**: docm関数（定義モード）。macroexpandを行いパターンマッチに委譲 |
| 3-5 | Docs.jl | `base/docs/Docs.jl` | **693-786行目**: _docm関数。式のパターンマッチ（関数/型/モジュール/キーワード等）とdocstring処理の分岐 |
| 3-6 | Docs.jl | `base/docs/Docs.jl` | **611-632行目**: _doc関数。docstringの検索・取得ロジック |
| 3-7 | Docs.jl | `base/docs/Docs.jl` | **802行目**: `Core.atdoc!(docm)` でCoreのブートストラップマクロをDocsの本実装に差し替え |
| 3-8 | Docs.jl | `base/docs/Docs.jl` | **804-815行目**: loaddocs関数。CoreDocs.DocLinkedListに蓄積されたdocstringを本システムに取り込む |

**主要処理フロー**:
- **247-248行目**: 既存docstring上書き時の警告。active_module（Main）以外で上書きすると@warn
- **257-258行目**: MultiDoc.orderへの追加（初回のみ）
- **622-623行目**: `sig <: msig` による型シグネチャマッチ
- **664-675行目**: docm（取得モード）。REPL_MODULE_REFを確認し、REPL.lookup_docに委譲

#### Step 4: ユーティリティ関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | utils.jl | `base/docs/utils.jl` | HTML/Text型、@html_str/@text_strマクロの定義 |
| 4-2 | bindings.jl | `base/docs/bindings.jl` | **15-18行目**: defined/resolve関数。Bindingの値解決 |
| 4-3 | bindings.jl | `base/docs/bindings.jl` | **35-39行目**: aliasof関数。DataType/Function/Moduleのエイリアス解決 |

#### Step 5: hasdoc/undocumented_namesを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | Docs.jl | `base/docs/Docs.jl` | **860-871行目**: hasdoc関数。getdoc→modules走査→alias検索の3段階 |
| 5-2 | Docs.jl | `base/docs/Docs.jl` | **884-889行目**: undocumented_names関数。names(mod; all=true)からhasdoc=falseを抽出 |

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

```
Core.@doc（ブートストラップ）
    |
    +-- CoreDocs.docm(source, mod, str, x)
    |       +-- CoreDocs.doc!(source, mod, str, x)
    |       +-- DOCS = DocLinkedList(..., DOCS)
    |
    +-- [Baseロード後] Core.atdoc!(Docs.docm)  [802行目]
    |
    +-- Docs.loaddocs(CoreDocs.DOCS)  [804行目]
            +-- CoreDocs.DocLinkedListを走査
            +-- Docs.docm(lno, mod, doc, ex, false) で登録

Docs.docm（本実装）
    |
    +-- 取得モード: docm(source, mod, ex)
    |       +-- REPL.lookup_doc(ex)  [REPL読込済]
    |       +-- simple_lookup_doc(ex)  [REPL未読込]
    |               +-- _doc(binding, sig)
    |                       +-- getdoc(resolve(binding))
    |                       +-- modules走査 → META検索
    |
    +-- 定義モード: docm(source, mod, meta, ex, define)
            +-- macroexpand(mod, ex)
            +-- _docm(source, mod, meta, x, define)
                    +-- keyworddoc()  [キーワード]
                    +-- objectdoc()   [関数/型/変数]
                    +-- calldoc()     [呼び出し構文]
                    +-- moduledoc()   [モジュール]
                    +-- multidoc()    [タプル構文]
                    +-- __doc__!()    [マクロ展開内@__doc__]
                            |
                            +-- doc!(__module__, binding, docstr, sig)
                                    +-- initmeta(__module__)
                                    +-- META[binding] = MultiDoc
                                    +-- MultiDoc.docs[sig] = DocStr
```

### データフロー図

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

ソースコード中の   ──> CoreDocs.doc!              ──> DocLinkedList (起動時)
docstring                   |
                     Core.atdoc!(docm)
                            |
                     Docs.loaddocs              ──> META辞書 (各モジュール)
                            |
@doc "str" expr    ──> Docs.docm (定義)          ──> META[binding].docs[sig]
                            |
@doc expr          ──> Docs.docm (取得)          ──> DocStr / Markdown.MD
                            |
help?> expr        ──> REPL.lookup_doc           ──> ターミナル表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Docs.jl | `base/docs/Docs.jl` | ソース | Docsシステム本体（891行） |
| core.jl | `base/docs/core.jl` | ソース | CoreDocsブートストラップ（39行） |
| bindings.jl | `base/docs/bindings.jl` | ソース | Binding型とエイリアス解決（39行） |
| utils.jl | `base/docs/utils.jl` | ソース | HTML/Text型ユーティリティ（119行） |
| basedocs.jl | `base/docs/basedocs.jl` | ソース | Base組み込みオブジェクトのdocstring |
| intrinsicsdocs.jl | `base/docs/intrinsicsdocs.jl` | ソース | Core.Intrinsicsのdocstring |
