# 機能設計書 146-LSIF出力

## 概要

本ドキュメントでは、RoslynのLSIF出力（Language Server Index Format）機能について設計を記載する。この機能は、コードベースのインデックス情報をLSIF形式で出力し、GitHub Code NavigationなどのリッチなコードナビゲーションUXを実現する。

### 本機能の処理概要

**業務上の目的・背景**：
GitHubなどのコードホスティングサービスでは、ブラウザ上でコードを閲覧する際に「定義へ移動」「参照の検索」などのナビゲーション機能を提供している。これらの機能を実現するには、事前にコードを解析してインデックス情報を生成する必要がある。LSIF（Language Server Index Format）は、この目的のために設計された標準フォーマットであり、本機能はRoslynのセマンティック解析能力を活用してLSIF形式のインデックスを生成する。

**機能の利用シーン**：
- GitHub Code Navigationのためのインデックス生成
- リポジトリ全体の静的解析インデックス作成
- コードナビゲーション情報のキャッシュ生成

**主要な処理内容**：
1. ソリューション/プロジェクトの解析
2. シンボル情報のMoniker（一意識別子）生成
3. 定義・参照関係のグラフ構築
4. LSIF JSON形式での出力

**関連システム・外部連携**：
- GitHub Code Navigation
- Azure DevOps
- Language Server Protocol (LSP) Moniker機能

**権限による制御**：
特定の権限による制御は行わない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | GitHub Code Navigation | 参照画面 | 生成されたインデックスの利用先 |
| - | コマンドライン | 主画面 | LSIF生成ツールの実行 |

## 機能種別

インデックス生成 / データエクスポート / セマンティック解析

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| solution | Solution | Yes | 解析対象ソリューション | null不可 |
| project | Project | No | 解析対象プロジェクト（個別指定時） | - |
| outputPath | string | Yes | LSIF出力パス | 有効なファイルパス |

### 入力データソース

- ソリューション/プロジェクトファイル
- ソースコードドキュメント
- コンパイル情報

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| vertices | LsifVertex[] | LSIFグラフの頂点（ドキュメント、シンボル等） |
| edges | LsifEdge[] | LSIFグラフの辺（contains、item等） |
| monikers | Moniker[] | シンボルの一意識別子 |

### 出力先

- LSIF JSONファイル（Line Mode形式）

## 処理フロー

### 処理シーケンス

```
1. ソリューション解析
   └─ ソリューション構造を解析しプロジェクト一覧を取得
2. ドキュメント処理
   └─ 各ドキュメントに対してシンボル情報を抽出
3. Moniker生成
   └─ シンボルに対して一意識別子を生成
4. グラフ構築
   └─ LSIF頂点と辺を構築
5. JSON出力
   └─ Line Mode形式でJSONを出力
```

### フローチャート

```mermaid
flowchart TD
    A[ソリューション読み込み] --> B[プロジェクト列挙]
    B --> C[ドキュメント列挙]
    C --> D[シンボル解析]
    D --> E{Monikerあり?}
    E -->|Yes| F[Moniker生成]
    E -->|No| G[スキップ]
    F --> H[頂点作成]
    H --> I[辺作成]
    I --> J{次のシンボル?}
    J -->|Yes| D
    J -->|No| K[JSON出力]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-146-01 | Monikerスキーム | dotnet-namespaceまたはdotnet-xml-docを使用 | シンボルMoniker生成時 |
| BR-146-02 | Moniker対象外 | Local、RangeVariable、Label、Alias、BuiltinOperatorはMoniker生成しない | シンボル判定時 |
| BR-146-03 | 型置換なし | OriginalDefinitionと異なるシンボルはMoniker生成しない | ジェネリック型処理時 |
| BR-146-04 | 名前空間Moniker | 名前空間はdotnet-namespaceスキームで表示文字列をIdentifierとする | 名前空間処理時 |

### 計算ロジック

- 通常シンボルのMoniker: `{AssemblyName}#{DocumentationCommentId}`
- パラメータのMoniker: `{AssemblyName}#{ContainingSymbolDocId}#{ParameterName}`

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

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

データベース操作は行わない。

### テーブル別操作詳細

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ERR-146-01 | コンパイルエラー | ソースコードにエラーあり | 警告として続行 |
| ERR-146-02 | DocId取得失敗 | DocumentationCommentIdがnull | 例外スロー |

### リトライ仕様

リトライは行わない。

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

トランザクション管理は不要（読み取り専用処理）。

## パフォーマンス要件

- 大規模ソリューションでも実用的な時間で完了すること
- メモリ使用量を抑制するためストリーミング出力

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

- ソースコード内容は出力しない（ソース生成ドキュメントを除く）
- シンボル情報のみをエクスポート

## 備考

- LSIFはLanguage Server Protocolの拡張として設計された
- 本機能はVB固有のテストコード（GeneratorTest）を含む

---

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

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

### 推奨読解順序

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

Monikerとスキームの定義を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SymbolMoniker.cs | `src/Features/Core/Portable/LanguageServiceIndexFormat/SymbolMoniker.cs` | Moniker生成ロジック（9-84行目） |
| 1-2 | WellKnownSymbolMonikerSchemes.cs | `src/Features/Core/Portable/LanguageServiceIndexFormat/WellKnownSymbolMonikerSchemes.cs` | スキーム定義（7-11行目） |

**読解のコツ**: `SymbolMoniker`クラスは`Scheme`と`Identifier`のペアを保持し、`Create`メソッドでシンボルからMonikerを生成する。`HasMoniker`で対象外シンボルをフィルタリングする。

#### Step 2: Moniker生成ロジックを理解する

シンボルからMonikerへの変換ロジックを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SymbolMoniker.cs | `src/Features/Core/Portable/LanguageServiceIndexFormat/SymbolMoniker.cs` | HasMonikerメソッド（15-42行目） |

**主要処理フロー**:
- **18-19行目**: OriginalDefinitionと異なる場合はMoniker対象外
- **23-29行目**: Local、RangeVariable等のローカルシンボルは対象外
- **33-34行目**: BuiltinOperatorは対象外
- **38-39行目**: ContainingAssemblyがnullのシンボルは対象外

#### Step 3: Moniker生成ロジック（続き）を理解する

実際のMoniker識別子生成を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SymbolMoniker.cs | `src/Features/Core/Portable/LanguageServiceIndexFormat/SymbolMoniker.cs` | Createメソッド（44-84行目） |

**主要処理フロー**:
- **53-56行目**: 名前空間はdotnet-namespaceスキームで表示文字列を使用
- **58-68行目**: 通常シンボルは`{AssemblyName}#{DocId}`形式
- **60-62行目**: パラメータは`{AssemblyName}#{ContainingDocId}#{Name}`形式

#### Step 4: LSP Moniker連携を理解する

LSPとの連携を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Moniker.cs | `src/LanguageServer/Protocol/Protocol/Moniker/Moniker.cs` | LSP Moniker型定義（16-46行目） |

**主要処理フロー**:
- **23行目**: `Scheme`プロパティ（tscや.Net等）
- **31行目**: `Identifier`プロパティ（不透明な識別子）
- **38行目**: `Unique`プロパティ（一意性レベル）
- **45行目**: `Kind`プロパティ（オプション）

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

```
[LSIF Generator Tool]
    │
    ▼
ソリューション解析
    │
    ├─ Project
    │      └─ Document
    │             └─ シンボル
    │
    ▼
SymbolMoniker
    │
    ├─ HasMoniker(symbol)
    │      │
    │      ├─ OriginalDefinitionチェック
    │      ├─ SymbolKindチェック
    │      ├─ BuiltinOperatorチェック
    │      └─ ContainingAssemblyチェック
    │
    └─ Create(symbol)
           │
           ├─ Namespace → dotnet-namespace:ToDisplayString()
           │
           └─ Other → dotnet-xml-doc:{AssemblyName}#{DocId}
                  │
                  └─ Parameter → {AssemblyName}#{ContainingDocId}#{Name}

LSP Moniker (Protocol)
    │
    ├─ Scheme (string)
    ├─ Identifier (string)
    ├─ Unique (UniquenessLevel)
    └─ Kind (MonikerKind?)
```

### データフロー図

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

ソリューション ───────▶ LSIF Generator ───────▶ LsifProject頂点
    │                        │
    ▼                        ▼
プロジェクト ───────▶ Document解析 ───────▶ LsifDocument頂点
    │                        │
    ▼                        ▼
シンボル ───────▶ HasMoniker() ───────▶ フィルタリング
    │                        │
    ▼                        ▼
対象シンボル ───────▶ SymbolMoniker.Create() ───────▶ Moniker
    │                        │
    ▼                        ▼
定義・参照情報 ───────▶ 頂点・辺構築 ───────▶ LSIFグラフ
                             │
                             ▼
                    LineModeLsifJsonWriter
                             │
                             ▼
                      LSIF JSONファイル
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SymbolMoniker.cs | `src/Features/Core/Portable/LanguageServiceIndexFormat/` | ソース | Moniker生成ロジック |
| WellKnownSymbolMonikerSchemes.cs | `src/Features/Core/Portable/LanguageServiceIndexFormat/` | ソース | スキーム定数定義 |
| Moniker.cs | `src/LanguageServer/Protocol/Protocol/Moniker/` | ソース | LSP Moniker型 |
| MonikerKind.cs | `src/LanguageServer/Protocol/Protocol/Moniker/` | ソース | Monikerの種類列挙 |
| UniquenessLevel.cs | `src/LanguageServer/Protocol/Protocol/Moniker/` | ソース | 一意性レベル列挙 |
| MonikerParams.cs | `src/LanguageServer/Protocol/Protocol/Moniker/` | ソース | LSPリクエストパラメータ |
| ProjectStructureTests.vb | `src/Features/Lsif/GeneratorTest/` | テスト | プロジェクト構造テスト |
| CompilerInvocationTests.vb | `src/Features/Lsif/GeneratorTest/` | テスト | コンパイラ呼び出しテスト |
