# 機能設計書 60-定義移動

## 概要

本ドキュメントは、Visual Studio統合における「定義へ移動」（Go to Definition）機能について記述する。

### 本機能の処理概要

エディタ上のシンボル（識別子）から、その定義位置へナビゲーションする機能を提供する。ソリューション内のシンボル、外部アセンブリのシンボル、シグネチャファイルと実装ファイル間の移動をサポートする。

**業務上の目的・背景**：コードの理解と探索において、シンボルの定義位置への移動は最も頻繁に使用される機能の一つである。F#特有のシグネチャファイル（.fsi）と実装ファイル（.fs）の関係も考慮したナビゲーションが必要。

**機能の利用シーン**：
- F12キー（定義へ移動）
- Ctrl+クリック
- コンテキストメニューからの定義移動
- クイック情報からのリンクナビゲーション

**主要な処理内容**：
1. カーソル位置のシンボル識別
2. シンボルの定義位置解決
3. 外部アセンブリのメタデータソース表示
4. シグネチャ/実装間のナビゲーション
5. クロス言語ナビゲーション（C#からF#等）

**関連システム・外部連携**：
- Microsoft.CodeAnalysis.Navigation（Roslyn）
- FSharp.Compiler.Service（FCS）
- Visual Studioエディタサービス
- Metadata As Source（MAS）

**権限による制御**：なし

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | コードエディタ | 入力画面 | F12/Ctrl+クリック |
| - | Metadata As Source | 表示画面 | 外部シンボルの表示 |

## 機能種別

UI操作 / ナビゲーション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| document | Document | Yes | 対象ドキュメント | - |
| position | int | Yes | カーソル位置 | 0以上 |
| cancellationToken | CancellationToken | Yes | キャンセルトークン | - |

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result | FSharpGoToDefinitionResult | ナビゲーション結果 |
| idRange | range | シンボル識別子の範囲 |

### FSharpGoToDefinitionResult

| バリアント | 説明 |
|-----------|------|
| NavigableItem | ソリューション内のナビゲーション可能項目 |
| ExternalAssembly | 外部アセンブリ（メタデータソース表示） |

## 処理フロー

### 処理シーケンス

```
1. シンボル識別
   └─ TryFindFSharpLexerSymbolAsync
   └─ 識別子のレンジ取得

2. 定義位置解決
   └─ GetDeclarationLocation
   └─ ExternalDecl / DeclFound の判定

3. ナビゲーション種別の判定
   └─ ソリューション内: NavigableItem
   └─ 外部アセンブリ: ExternalAssembly

4. シグネチャ/実装の処理
   └─ シグネチャファイル → 実装ファイルへ
   └─ 実装ファイル → シグネチャファイルへ

5. ナビゲーション実行
   └─ NavigateToItem
   └─ または TryGetExternalDeclarationAsync
```

### フローチャート

```mermaid
flowchart TD
    A[開始: F12押下] --> B[カーソル位置のシンボル識別]
    B --> C{シンボル存在?}
    C -->|No| D[終了: ナビゲーションなし]
    C -->|Yes| E[GetDeclarationLocation]
    E --> F{結果種別}
    F -->|ExternalDecl| G[外部プロジェクト検索]
    F -->|DeclFound| H{ソリューション内?}
    G --> I{プロジェクト発見?}
    I -->|Yes| J[ソース位置へ移動]
    I -->|No| K[Metadata As Source表示]
    H -->|Yes| L{シグネチャ/実装判定}
    H -->|No| K
    L -->|同位置| M[シグネチャ⇔実装切替]
    L -->|異位置| N[定義位置へ移動]
    J --> O[終了]
    K --> O
    M --> O
    N --> O
    D --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-60-01 | シグネチャ優先 | シグネチャファイルから呼び出し時はシグネチャを探索 | .fsiファイル |
| BR-60-02 | 実装優先 | 実装ファイルから呼び出し時は実装を探索 | .fsファイル |
| BR-60-03 | 同位置切替 | 定義位置が現在位置と同じ場合はシグネチャ/実装を切替 | カーソル位置 == 定義位置 |
| BR-60-04 | MAS表示 | 外部アセンブリはMetadata As Sourceで表示 | 外部参照時 |

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

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | キャンセル | CancellationToken発火 | 終了 |
| - | ナビゲーション不可 | シンボルが見つからない | 何もしない |

## パフォーマンス要件

- テレメトリによるパフォーマンス計測
- JoinableTaskFactoryによる待機UIダイアログ（1秒後に表示）

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

なし

## 備考

- IFSharpCrossLanguageSymbolNavigationServiceでC#からのナビゲーションもサポート
- DocCommentIdを使用したクロス言語シンボル解決

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | GoToDefinition.fs | `vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs` | FSharpGoToDefinitionResult型（117-119行目） |
| 1-2 | GoToDefinition.fs | `vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs` | FSharpGoToDefinitionNavigableItem型（113-114行目） |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | GoToDefinition.fs | `vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs` | GoToDefinitionクラス（121行目） |
| 2-2 | GoToDefinition.fs | `vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs` | FindDefinitionAtPositionメソッド（375-575行目）が中核処理 |

#### Step 3: シンボル解決を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | GoToDefinition.fs | `vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs` | TryFindFSharpLexerSymbolAsync（390行目） |
| 3-2 | GoToDefinition.fs | `vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs` | GetDeclarationLocation（400-407行目） |
| 3-3 | GoToDefinition.fs | `vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs` | GetSymbolUseAtLocation（409-410行目） |

#### Step 4: ナビゲーション種別処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | GoToDefinition.fs | `vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs` | ExternalDecl分岐（417-455行目） |
| 4-2 | GoToDefinition.fs | `vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs` | DeclFound分岐（457-573行目） |
| 4-3 | GoToDefinition.fs | `vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs` | TryGetExternalDeclarationAsync（202-271行目） |

#### Step 5: クロス言語ナビゲーションを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | GoToDefinition.fs | `vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs` | FSharpCrossLanguageSymbolNavigationService（886行目） |
| 5-2 | GoToDefinition.fs | `vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs` | DocCommentIdToPath（963-1055行目） |
| 5-3 | GoToDefinition.fs | `vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs` | TryGetNavigableLocationAsync（1057-1120行目） |

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

```
GoToDefinition
    │
    ├─ FindDefinitionAtPosition
    │      ├─ TryFindFSharpLexerSymbolAsync
    │      ├─ GetDeclarationLocation
    │      ├─ GetSymbolUseAtLocation
    │      └─ 分岐処理
    │             ├─ ExternalDecl → 外部プロジェクト/MAS
    │             └─ DeclFound → ソリューション内
    │
    ├─ TryGetExternalDeclarationAsync
    │      ├─ TryGetMetadataText
    │      ├─ MetadataAsSource.generateTemporaryDocument
    │      └─ tryFindExternalSymbolUse
    │
    ├─ NavigateToItem
    │      └─ IFSharpDocumentNavigationService.TryNavigateToSpan
    │
    └─ FSharpCrossLanguageSymbolNavigationService
           ├─ DocCommentIdToPath
           └─ TryGetNavigableLocationAsync
                  └─ ParseAndCheckProject
```

### データフロー図

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

カーソル位置          ──▶  TryFindFSharpLexerSymbol  ──▶  LexerSymbol
       │
       ▼
LexerSymbol           ──▶  GetDeclarationLocation    ──▶  FindDeclResult
       │
       ▼
FindDeclResult        ──▶  結果種別判定              ──▶  分岐処理
       │
       ├──▶  ExternalDecl ──▶ SymbolFinder          ──▶  ソース位置
       │                      または
       │                      TryGetExternalDecl    ──▶  MASドキュメント
       │
       └──▶  DeclFound   ──▶ シグネチャ/実装判定    ──▶  NavigableItem
       │
       ▼
NavigableItem         ──▶  NavigateToItem           ──▶  ナビゲーション実行
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| GoToDefinition.fs | `vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs` | ソース | 定義移動の中核実装 |
| MetadataAsSource.fs | `vsintegration/src/FSharp.Editor/MetadataAsSource.fs` | ソース | MASドキュメント生成 |
| FindUsages.fs | `vsintegration/src/FSharp.Editor/Navigation/FindUsages.fs` | ソース | 使用箇所検索（関連機能） |
