# 通知設計書 5-errCannotOpenFile

## 概要

本ドキュメントは、Nimコンパイラにおけるエラー通知「errCannotOpenFile」の設計仕様を定義する。

### 本通知の処理概要

errCannotOpenFileは、コンパイラが必要なファイルを開けない場合に出力されるエラー通知である。ソースファイル、設定ファイル、出力ファイルなど、コンパイル処理に必要なファイルへのアクセスが失敗した際に発行される。

**業務上の目的・背景**：コンパイラはソースファイルの読み込み、生成コードの書き込み、設定ファイルの参照など、多くのファイル操作を行う。ファイルが存在しない、アクセス権限がない、ファイルがロックされているなどの理由でファイルを開けない場合、明確なエラーメッセージで開発者に問題を通知する必要がある。

**通知の送信タイミング**：ファイルオープン操作（読み込みまたは書き込み）が失敗した時点で発行される。複数のモジュール（passes.nim, pipelines.nim, cgen.nim, jsgen.nim, docgen.nim, tccgen.nimなど）から呼び出される。

**通知の受信者**：Nimソースコードをコンパイルしている開発者。ファイルパスの誤り、アクセス権限の問題、または存在しないファイルへの参照を修正する必要がある。

**通知内容の概要**：「cannot open '{ファイル名}'」という形式で出力される。$1プレースホルダーに問題のファイルパスが挿入される。

**期待されるアクション**：開発者は、指定されたファイルパスを確認し、ファイルが存在すること、アクセス権限があること、パスが正しいことを確認することが期待される。

## 通知種別

コンパイラ標準出力/標準エラー出力（コンソール通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 高（Error） |
| リトライ | なし |

### 送信先決定ロジック

コンパイラオプション`--stdout`が指定されている場合はstdoutに、それ以外はstderrに出力される。

## 通知テンプレート

### コンソール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元 | Nimコンパイラ |
| メッセージ種別 | Error |
| 形式 | テキスト |

### 本文テンプレート

```
{ファイル名}({行},{列}) Error: cannot open '{対象ファイルパス}'
```

または（位置情報なしの場合）：
```
Error: cannot open '{対象ファイルパス}'
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| $1 | 開けなかったファイルパス | 呼び出し元から渡されるファイルパス | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ソースファイル読み込み | llStreamOpen失敗 | s == nil | passes.nim, pipelines.nim |
| C/C++コード出力 | writeRope失敗 | 書き込み失敗 | cgen.nim |
| JavaScriptコード出力 | writeRope失敗 | 書き込み失敗 | jsgen.nim |
| ドキュメント出力 | writeFile失敗 | IOError例外 | docgen.nim |
| TinyC処理 | addFile失敗 | 非ゼロ戻り値 | tccgen.nim |
| 出力ディレクトリ | isAbsolute失敗 | パスが相対 | main.nim |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| なし | エラーのため常に出力される |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ファイル操作要求] --> B{ファイルオープン}
    B -->|成功| C[処理継続]
    B -->|失敗| D[rawMessage呼び出し]
    D --> E[liMessage処理]
    E --> F[メッセージ出力]
    F --> G[処理中断/継続]
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし（ファイルベースの処理）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| ファイル不存在 | 指定されたパスにファイルがない | パスを確認、ファイルを作成 |
| アクセス権限不足 | 読み取り/書き込み権限がない | ファイル権限を変更 |
| パス形式エラー | 無効なパス文字が含まれる | パスを修正 |
| ディスク容量不足 | 書き込み時にディスクが満杯 | ディスク容量を確保 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし |
| 1日あたり上限 | なし |

### 配信時間帯

制限なし

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

- エラーメッセージにはファイルパスが含まれる
- ローカル開発環境での使用を想定
- ファイルパスにより機密情報が漏洩しないよう注意

## 備考

- errCannotOpenFileはエラー（Error）カテゴリに属する
- 対応する警告版としてwarnCannotOpenFileが存在する
- docgen.nimではuseWarningフラグにより警告またはエラーを選択可能
- 位置情報なしの場合（unknownLineInfo）はrawMessageで呼び出される

---

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

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

### 推奨読解順序

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

errCannotOpenFile通知の基盤となるデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | lineinfos.nim | `compiler/lineinfos.nim` | TMsgKind列挙型でerrCannotOpenFileの定義を確認（34行目） |
| 1-2 | lineinfos.nim | `compiler/lineinfos.nim` | MsgKindToStr配列でメッセージ文字列を確認（125行目） |

**読解のコツ**: errCannotOpenFileは非致命的エラー（non-fatal errors）セクションに定義されている。$1プレースホルダーにファイルパスが挿入される。

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

通知発行の起点となるファイル・関数を特定。複数のモジュールから呼び出される。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | passes.nim | `compiler/passes.nim` | ソースファイル読み込み失敗（109-110行目） |
| 2-2 | pipelines.nim | `compiler/pipelines.nim` | ソースファイル読み込み失敗（162-163行目） |
| 2-3 | cgen.nim | `compiler/cgen.nim` | C/C++コード書き込み失敗（2399-2400行目, 2484-2485行目, 2492-2493行目） |
| 2-4 | jsgen.nim | `compiler/jsgen.nim` | JavaScriptコード書き込み失敗（3227-3228行目） |
| 2-5 | tccgen.nim | `compiler/tccgen.nim` | TinyCファイル追加失敗（35-36行目） |

**主要処理フロー**:
1. **passes.nim 109-110行目**: `s == nil`の場合、rawMessage呼び出し
2. **cgen.nim 2399-2400行目**: `not writeRope`の場合、rawMessage呼び出し

#### Step 3: docgen.nimでの特別処理を理解する

ドキュメント生成時の警告/エラー選択処理を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | docgen.nim | `compiler/docgen.nim` | useWarningフラグによる警告/エラー選択（1801-1803行目） |
| 3-2 | docgen.nim | `compiler/docgen.nim` | RSTメッセージの変換処理（247行目） |

**主要処理フロー**:
- **1801-1803行目**: `useWarning`フラグにより、warnCannotOpenFileまたはerrCannotOpenFileを選択

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

```
コンパイラモジュール
    │
    ├─ passes.nim::processModule
    │      │
    │      └─ llStreamOpen() → nil
    │             │
    │             └─ rawMessage(conf, errCannotOpenFile, filename)
    │
    ├─ cgen.nim::writeModule
    │      │
    │      └─ writeRope() → false
    │             │
    │             └─ rawMessage(conf, errCannotOpenFile, filename)
    │
    └─ docgen.nim::writeOutput
           │
           └─ writeFile() → IOError
                  │
                  └─ rawMessage(conf, errCannotOpenFile, outfile)
```

### データフロー図

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

ファイルパス ────▶ ファイルオープン試行 ───▶ 標準エラー出力
(filename)          │                         "cannot open '{filename}'"
                    ▼
               失敗検出
                    │
                    ▼
              rawMessage
                    │
                    ▼
              liMessage
                    │
                    ▼
              handleError
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| lineinfos.nim | `compiler/lineinfos.nim` | ソース | TMsgKind定義、メッセージ文字列定義 |
| msgs.nim | `compiler/msgs.nim` | ソース | rawMessageテンプレート |
| passes.nim | `compiler/passes.nim` | ソース | ソースファイル読み込み処理 |
| pipelines.nim | `compiler/pipelines.nim` | ソース | パイプライン処理 |
| cgen.nim | `compiler/cgen.nim` | ソース | Cコード生成・出力 |
| jsgen.nim | `compiler/jsgen.nim` | ソース | JavaScriptコード生成・出力 |
| docgen.nim | `compiler/docgen.nim` | ソース | ドキュメント生成・出力 |
| tccgen.nim | `compiler/tccgen.nim` | ソース | TinyC処理 |
| main.nim | `compiler/main.nim` | ソース | メインエントリーポイント |
