# 機能設計書 58-分類サービス

## 概要

本ドキュメントは、Visual Studio統合におけるF#コードのシンタックスハイライト・セマンティックハイライト機能について記述する。

### 本機能の処理概要

F#ソースコードをトークン化し、キーワード、識別子、リテラル、コメント等の分類情報を提供することで、エディタでのシンタックスハイライトとセマンティックハイライトを実現する。

**業務上の目的・背景**：Visual Studioエディタでのコード可読性向上のため、F#コードの各要素を適切に色分け表示する必要がある。シンタックスハイライトはレキシカル解析、セマンティックハイライトは型解析結果に基づく。

**機能の利用シーン**：
- Visual Studioでのコード編集
- エディタでのスクロール時の表示更新
- 検索結果のハイライト表示
- ドキュメント全体の分類情報取得

**主要な処理内容**：
1. レキシカル分類（シンタックス）
   - FSharpLexerによるトークン化
   - キーワード、リテラル、コメント等の識別
2. セマンティック分類
   - 型チェック結果からの分類情報取得
   - 型、関数、プロパティ等の識別

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

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | コードエディタ | 表示画面 | シンタックスハイライト表示 |

## 機能種別

UI表示 / エディタサービス

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| document | Document | Yes | 対象ドキュメント | - |
| textSpan | TextSpan | Yes | 分類対象のテキスト範囲 | - |
| cancellationToken | CancellationToken | Yes | キャンセルトークン | - |

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| classifiedSpans | List<ClassifiedSpan> | 分類済みスパンのリスト |

### ClassifiedSpan

| フィールド | 説明 |
|-----------|------|
| Span | テキスト範囲（開始位置、長さ） |
| ClassificationType | 分類タイプ名（Keyword, Identifier等） |

## 処理フロー

### 処理シーケンス

```
1. シンタックス分類（AddSyntacticClassificationsAsync）
   └─ ドキュメントのパースオプション取得
   └─ 開いているドキュメント: Tokenizer.classifySpans
   └─ 閉じているドキュメント: getLexicalClassifications

2. セマンティック分類（AddSemanticClassificationsAsync）
   └─ キャッシュチェック
   └─ GetFSharpSemanticClassificationAsync
   └─ 結果をキャッシュに保存

3. 分類結果のマッピング
   └─ FSharpClassificationTypes.getClassificationTypeName
   └─ TextSpanへの変換
```

### フローチャート

```mermaid
flowchart TD
    A[開始: 分類リクエスト] --> B{ドキュメント開いている?}
    B -->|Yes| C[Tokenizer.classifySpans]
    B -->|No| D[getLexicalClassifications]
    C --> E[セマンティック分類]
    D --> E
    E --> F{キャッシュ存在?}
    F -->|Yes| G[キャッシュから取得]
    F -->|No| H[GetFSharpSemanticClassification]
    G --> I[結果マージ]
    H --> J[キャッシュに保存]
    J --> I
    I --> K[ClassifiedSpan返却]
    K --> L[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-58-01 | キャッシュ | 開いていないドキュメントは5分、開いているドキュメントは2分キャッシュ | 常時 |
| BR-58-02 | テレメトリ | 分類処理時間をテレメトリ報告 | 常時 |
| BR-58-03 | 無効化 | ShouldProduceSemanticHighlighting()がfalseの場合は処理しない | 設定依存 |

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

本機能はデータベースを使用しない。DocumentCacheによるメモリキャッシュを使用。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | キャンセル | CancellationToken発火 | 空リスト返却 |
| - | 例外 | 解析エラー | 空リスト返却（ログ記録） |

## パフォーマンス要件

- 閉じたドキュメント: 対象範囲のみをトークン化
- 開いたドキュメント: キャッシュを活用
- セマンティック分類: 行番号をキーとしたルックアップで高速化

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

なし

## 備考

- IFSharpClassificationServiceインターフェースを実装
- Roslyn互換のClassifiedSpanを返却

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ClassificationService.fs | `vsintegration/src/FSharp.Editor/Classification/ClassificationService.fs` | FSharpClassificationServiceクラス（33行目）がエントリーポイント |
| 1-2 | ClassificationService.fs | `vsintegration/src/FSharp.Editor/Classification/ClassificationService.fs` | IFSharpClassificationServiceインターフェース実装（151行目以降） |

#### Step 2: シンタックス分類を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ClassificationService.fs | `vsintegration/src/FSharp.Editor/Classification/ClassificationService.fs` | AddSyntacticClassificationsAsync（155-206行目） |
| 2-2 | ClassificationService.fs | `vsintegration/src/FSharp.Editor/Classification/ClassificationService.fs` | getLexicalClassifications関数（38-75行目） |

**主要処理フロー**:
- **38-75行目**: 閉じたドキュメント用のレキシカル分類
- **66-73行目**: FSharpLexer.Tokenizeでトークン化
- **44-55行目**: トークン種別から分類タイプへの変換

#### Step 3: セマンティック分類を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ClassificationService.fs | `vsintegration/src/FSharp.Editor/Classification/ClassificationService.fs` | AddSemanticClassificationsAsync（208-305行目） |
| 3-2 | ClassificationService.fs | `vsintegration/src/FSharp.Editor/Classification/ClassificationService.fs` | addSemanticClassification関数（77-94行目） |
| 3-3 | ClassificationService.fs | `vsintegration/src/FSharp.Editor/Classification/ClassificationService.fs` | toSemanticClassificationLookup関数（109-125行目） |

#### Step 4: キャッシュ管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ClassificationService.fs | `vsintegration/src/FSharp.Editor/Classification/ClassificationService.fs` | unopenedDocumentsSemanticClassificationCache（145-146行目） |
| 4-2 | ClassificationService.fs | `vsintegration/src/FSharp.Editor/Classification/ClassificationService.fs` | openedDocumentsSemanticClassificationCache（148-149行目） |

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

```
FSharpClassificationService
    │
    ├─ AddSyntacticClassificationsAsync
    │      ├─ isOpenDocument判定
    │      ├─ getLexicalClassifications (閉じたドキュメント)
    │      │      └─ FSharpLexer.Tokenize
    │      └─ Tokenizer.classifySpans (開いたドキュメント)
    │
    └─ AddSemanticClassificationsAsync
           ├─ キャッシュ検索
           │      └─ DocumentCache.TryGetValueAsync
           ├─ GetFSharpSemanticClassificationAsync
           ├─ toSemanticClassificationLookup
           │      └─ Dictionary構築 (行番号 -> 分類項目)
           └─ addSemanticClassificationByLookup
                  └─ addSemanticClassification
```

### データフロー図

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

SourceText            ──▶  FSharpLexer.Tokenize      ──▶  FSharpToken[]
       │
       ▼
FSharpToken           ──▶  分類タイプ変換            ──▶  ClassifiedSpan
       │
       ▼
Document              ──▶  GetFSharpSemanticClassification ──▶ SemanticClassificationItem[]
       │
       ▼
SemanticClassificationItem ──▶ Lookup構築            ──▶  IReadOnlyDictionary
       │
       ▼
Lookup + TextSpan     ──▶  addSemanticClassification ──▶  ClassifiedSpan[]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ClassificationService.fs | `vsintegration/src/FSharp.Editor/Classification/ClassificationService.fs` | ソース | 分類サービスの中核実装 |
| Tokenizer.fs | `vsintegration/src/FSharp.Editor/Classification/Tokenizer.fs` | ソース | トークン化ユーティリティ |
| FSharpClassificationTypes.fs | `vsintegration/src/FSharp.Editor/Classification/FSharpClassificationTypes.fs` | ソース | 分類タイプ定義 |
