# 機能設計書 21-ナビゲーション機能

## 概要

本ドキュメントは、F#コンパイラサービスが提供するナビゲーション機能の設計を記述する。この機能は、IDE（統合開発環境）においてコード内のシンボル間を移動するためのナビゲーション情報を提供する。

### 本機能の処理概要

この機能は、F#ソースコードの構文解析結果から、IDE向けのナビゲーション情報を抽出・生成する。ナビゲーションバーに表示する型やメンバーの一覧、「移動」機能で使用可能なシンボル一覧など、コードナビゲーションに必要な情報を提供する。

**業務上の目的・背景**：IDE上でのコード理解とナビゲーションを支援する機能として、開発者が大規模なコードベースでも効率的にコードを読み解き、目的の定義や宣言に素早くアクセスできるようにする。Visual StudioやVS Codeなどのエディタで、ナビゲーションバー（ドロップダウン）やGo to Symbol機能を実現するために必要な基盤機能である。

**機能の利用シーン**：エディタのナビゲーションバーでモジュール・型・メンバーを選択して移動する場面、Ctrl+Gなどのキーボードショートカットでシンボルに移動する場面、ドキュメントアウトラインやブレッドクラムでコード構造を把握する場面で利用される。

**主要な処理内容**：
1. 構文木（ParsedInput）からモジュール・名前空間・型定義を解析し、NavigationItemとして抽出
2. 各型定義内のメンバー（メソッド、プロパティ、フィールド等）を解析し、ネストされた項目として整理
3. 実装ファイル（.fs）とシグネチャファイル（.fsi）の両方に対応したナビゲーション情報を生成
4. 名前の一意性を確保するため、同名項目にインデックスを付与
5. NavigateTo機能用に、フラットなNavigableItem配列を生成

**関連システム・外部連携**：FSharpCheckerを通じてVisual Studio、VS Code、その他のLSP対応エディタから呼び出される。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | Visual Studio ナビゲーションバー | 主画面 | 型ドロップダウンとメンバードロップダウンの項目生成 |
| - | VS Code ブレッドクラム | 主画面 | コード階層の表示 |
| - | Go to Symbol ダイアログ | 結果表示画面 | 移動可能なシンボルの一覧表示 |

## 機能種別

データ抽出 / 構造解析

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| parsedInput | ParsedInput | Yes | パース済みのF#ソースコード（実装またはシグネチャファイル） | null不可 |

### 入力データソース

FSharpCheckerによる構文解析結果（ParsedInput）。ParsedInputはSigFile（シグネチャファイル）またはImplFile（実装ファイル）の判別共用体。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| NavigationItems | NavigationItems | トップレベル宣言とネストされた宣言の配列 |
| NavigableItem[] | NavigableItem[] | NavigateTo用のフラットなシンボル一覧 |

### 出力先

呼び出し元のIDEサービスに返却。Visual Studio EditorやLSPサーバーを経由してクライアントに提供される。

## 処理フロー

### 処理シーケンス

```
1. Navigation.getNavigation呼び出し
   └─ ParsedInputの種類を判別（SigFile/ImplFile）
2. getNavigationFromImplFile または getNavigationFromSigFile を呼び出し
   └─ モジュール・名前空間のリストを取得
3. 各モジュール・名前空間を走査
   └─ processNavigationTopLevelDeclarations で型・ネストモジュールを抽出
4. 型定義を処理（processTycon）
   └─ クラス、レコード、判別共用体、列挙型等の種類を判別
5. メンバーを処理（processMembers）
   └─ メソッド、プロパティ、フィールド等を抽出
6. 名前の一意性を確保
   └─ 同名項目にインデックスを付与（uniqueName関数）
7. NavigationItems/NavigableItem[]を生成して返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始: getNavigation] --> B{ParsedInput種別?}
    B -->|SigFile| C[getNavigationFromSigFile]
    B -->|ImplFile| D[getNavigationFromImplFile]
    C --> E[モジュール・名前空間を走査]
    D --> E
    E --> F[processNavigationTopLevelDeclarations]
    F --> G[processTycon: 型定義を処理]
    G --> H[processMembers: メンバーを処理]
    H --> I[名前の一意性確保]
    I --> J[NavigationItems生成]
    J --> K[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 名前の一意性 | 同名の宣言には "name_1_of_N" 形式でインデックスを付与 | 同一スコープに同名項目が存在する場合 |
| BR-02 | グリフ決定 | 宣言の種類に応じてFSharpGlyphを設定（Class, Module, Method等） | 常時 |
| BR-03 | アクセス修飾子反映 | private/internalなどのアクセス修飾子情報を保持 | アクセス修飾子が指定されている場合 |
| BR-04 | 範囲情報 | 各項目の宣言範囲と本体範囲を記録 | 常時 |

### 計算ロジック

名前の一意化: `sprintf "%s_%d_of_%d" name idx total`
- nameは元の名前
- idxは1から始まるインデックス
- totalは同名項目の総数

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

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

該当なし。本機能はインメモリでの構文木解析のみを行い、データベース操作は発生しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ArgumentNullException | parsedInputがnullの場合 | 呼び出し元で適切なparsedInputを提供 |
| - | MatchFailureException | 未対応の構文要素が存在する場合 | 空リストを返して継続 |

### リトライ仕様

リトライは不要。同期処理で即座に結果を返す。

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

該当なし。読み取り専用の解析処理。

## パフォーマンス要件

- 解析処理は構文木のサイズに比例（O(n)）
- 大規模ファイル（数千行）でも数十ミリ秒以内で完了すること
- メモリ使用量は構文木サイズに比例

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

- 信頼されていないコードの構文解析は可能だが、実行は行わない
- ファイルシステムへのアクセスは発生しない
- ネットワーク通信は発生しない

## 備考

- NavigationItemKindには Module, Type, Method, Property, Field, Exception, Namespace, ModuleFile, Other がある
- NavigationEntityKindには Namespace, Module, Class, Exception, Interface, Record, Enum, Union がある
- シグネチャファイル処理時は、重複メンバーを除外するためdistinctBy処理が追加される

---

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

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

### 推奨読解順序

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

まず、ナビゲーション機能で使用される主要なデータ型を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ServiceNavigation.fs | `src/Compiler/Service/ServiceNavigation.fs` | NavigationItemKind（17-28行目）、NavigationEntityKind（30-40行目）、NavigationItem（42-83行目）の定義を確認 |
| 1-2 | ServiceNavigation.fs | `src/Compiler/Service/ServiceNavigation.fs` | NavigationTopLevelDeclaration（85-92行目）、NavigationItems（94-99行目）の構造を確認 |

**読解のコツ**: F#の判別共用体（Discriminated Union）とレコード型を理解していると、データ構造の把握が容易。`[<RequireQualifiedAccess>]`属性は完全修飾名での参照を強制する。

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

処理の起点となる関数を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ServiceNavigation.fs | `src/Compiler/Service/ServiceNavigation.fs` | Navigation.getNavigation関数（691-698行目）がエントリーポイント |

**主要処理フロー**:
1. **693-696行目**: ParsedInputの種類を判別し、SigFileならgetNavigationFromSigFile、ImplFileならgetNavigationFromImplFileを呼び出す

#### Step 3: 実装ファイル解析を理解する

実装ファイル（.fs）の解析処理を追跡する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ServiceNavigation.fs | `src/Compiler/Service/ServiceNavigation.fs` | getNavigationFromImplFile関数（128-463行目）の全体構造を把握 |
| 3-2 | ServiceNavigation.fs | `src/Compiler/Service/ServiceNavigation.fs` | createDeclLid/createDecl（146-154行目）で宣言の作成方法を確認 |
| 3-3 | ServiceNavigation.fs | `src/Compiler/Service/ServiceNavigation.fs` | processTycon（241-318行目）で型定義の処理を確認 |
| 3-4 | ServiceNavigation.fs | `src/Compiler/Service/ServiceNavigation.fs` | processMembers（321-362行目）でメンバー処理を確認 |

**主要処理フロー**:
- **130-143行目**: 名前の一意性管理のためのDictionaryとヘルパー関数
- **411-442行目**: モジュール・名前空間の走査とトップレベル宣言の収集
- **444-463行目**: 最終的なNavigationItems配列の構築とソート

#### Step 4: NavigateTo機能を理解する

Go to Symbol機能で使用されるNavigateTo.GetNavigableItemsを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ServiceNavigation.fs | `src/Compiler/Service/ServiceNavigation.fs` | NavigableItem型（747-755行目）の定義 |
| 4-2 | ServiceNavigation.fs | `src/Compiler/Service/ServiceNavigation.fs` | NavigateTo.GetNavigableItems（759-1038行目）の処理フロー |

**主要処理フロー**:
- **767行目**: 結果を格納するResizeArrayの初期化
- **931-933行目**: 実装ファイルの走査開始
- **1034-1037行目**: 結果の返却

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

```
Navigation.getNavigation (ParsedInput)
    │
    ├─ getNavigationFromImplFile (実装ファイル用)
    │      ├─ processNavigationTopLevelDeclarations
    │      │      ├─ processTycon (型定義処理)
    │      │      │      └─ processMembers (メンバー処理)
    │      │      │              └─ processBinding (バインディング処理)
    │      │      └─ processExnDefn (例外定義処理)
    │      └─ processNestedDeclarations (let束縛処理)
    │
    └─ getNavigationFromSigFile (シグネチャファイル用)
           ├─ processNavigationTopLevelSigDeclarations
           │      ├─ processTycon (型定義処理)
           │      └─ processExnSig (例外定義処理)
           └─ processNestedSigDeclarations (val宣言処理)

NavigateTo.GetNavigableItems (ParsedInput)
    │
    ├─ walkImplFileInput (実装ファイル用)
    │      └─ walkSynModuleOrNamespace
    │             ├─ walkSynModuleDecl
    │             │      ├─ walkSynTypeDefn
    │             │      └─ walkSynMemberDefn
    │             └─ addBinding / addMember
    │
    └─ walkSigFileInput (シグネチャファイル用)
           └─ walkSynModuleOrNamespaceSig
                  └─ walkSynModuleSigDecl
```

### データフロー図

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

ParsedInput ───▶ Navigation.getNavigation ───▶ NavigationItems
(構文木)              │                              │
                      ├─ モジュール/名前空間抽出       ├─ Declaration (トップレベル)
                      ├─ 型定義抽出                    └─ Nested[] (メンバー)
                      ├─ メンバー抽出
                      └─ 名前の一意化

ParsedInput ───▶ NavigateTo.GetNavigableItems ───▶ NavigableItem[]
(構文木)              │                                    │
                      ├─ 再帰的にASTを走査                  ├─ Name
                      └─ 各シンボルをNavigableItemに変換    ├─ Range
                                                            ├─ Kind
                                                            └─ Container
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ServiceNavigation.fs | `src/Compiler/Service/ServiceNavigation.fs` | ソース | ナビゲーション機能のメイン実装 |
| SyntaxTree.fs | `src/Compiler/SyntaxTree/SyntaxTree.fs` | ソース | ParsedInput, SynModuleOrNamespace等の構文木定義 |
| SyntaxTreeOps.fs | `src/Compiler/SyntaxTree/SyntaxTreeOps.fs` | ソース | 構文木操作ユーティリティ（textOfLid等） |
| Symbols.fs | `src/Compiler/Symbols/Symbols.fs` | ソース | FSharpGlyph等のシンボル関連定義 |
| service.fs | `src/Compiler/Service/service.fs` | ソース | FSharpChecker経由でのナビゲーション機能呼び出し |
