# 機能設計書 70-タスクリスト

## 概要

本ドキュメントは、Visual Studio統合におけるF#のタスクリスト機能の設計について記述する。この機能は、コード内のコメントから`TODO`、`FIXME`、`HACK`などのタスクマーカーを検出し、Visual Studioのタスクリストウィンドウに表示する。

### 本機能の処理概要

**業務上の目的・背景**：
開発中のコードには、後で対応が必要な箇所をコメントでマークすることが一般的である。本機能により、これらのタスクマーカーを一覧で確認でき、作業漏れを防止し、コード品質の向上に寄与する。

**機能の利用シーン**：
- プロジェクト内のTODOコメントを一覧で確認したい場合
- 未解決の課題（FIXME）を追跡したい場合
- 一時的な回避策（HACK）を後で修正するための管理
- コードレビュー前にタスクの残存を確認する場合

**主要な処理内容**：
1. ドキュメント内の各行をトークン化
2. コメントトークンを抽出・連結
3. タスクディスクリプタ（TODO、FIXME等）との照合
4. マッチしたタスクの位置とテキストを記録
5. FSharpTaskListItemとして返却

**関連システム・外部連携**：
- Microsoft.CodeAnalysis.ExternalAccess.FSharp.TaskList: Roslynタスクリストインターフェース
- FSharp.Compiler.Tokenization: トークン化API
- Visual Studio タスクリストウィンドウ

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 専用の設定画面なし |

## 機能種別

コード解析・タスク管理機能

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| doc | Document | Yes | 対象のドキュメント | null不可 |
| descriptors | FSharpTaskListDescriptor[] | Yes | 検索するタスクディスクリプタ | null不可 |
| cancellationToken | CancellationToken | Yes | キャンセルトークン | - |

### 入力データソース

- ドキュメントのソーステキスト
- Visual Studioのタスクディスクリプタ設定（TODO、FIXME等）
- F#パーシングオプション

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| TaskListItems | ImmutableArray<FSharpTaskListItem> | 検出されたタスク項目のコレクション |
| Descriptor | FSharpTaskListDescriptor | タスクの種類（TODO等） |
| Text | string | タスクのテキスト |
| Document | Document | 所属ドキュメント |
| Span | TextSpan | タスクの位置 |

### 出力先

Visual Studio タスクリストウィンドウ

## 処理フロー

### 処理シーケンス

```
1. ソーステキスト取得
   └─ document.GetTextAsync

2. パーシングオプション取得
   └─ getDefinesAndLangVersionでdefines、langVersion取得

3. 行ごとの処理
   └─ 各行についてトークン化と検索を実行

4. トークン化
   └─ Tokenizer.tokenizeLineで行をトークン化

5. コメント抽出
   └─ コメントトークンを抽出し連結

6. ディスクリプタ照合
   └─ 各ディスクリプタについてIndexOfで検索

7. タスクアイテム生成
   └─ マッチした場合FSharpTaskListItemを生成

8. 結果返却
   └─ ImmutableArray<FSharpTaskListItem>として返却
```

### フローチャート

```mermaid
flowchart TD
    A[タスクリスト更新リクエスト] --> B[GetTextAsync]
    B --> C[getDefinesAndLangVersion]
    C --> D[各行をループ]
    D --> E[Tokenizer.tokenizeLine]
    E --> F[extractContractedComments]
    F --> G{コメントあり?}
    G -->|No| H[次の行]
    H --> D
    G -->|Yes| I[各ディスクリプタをチェック]
    I --> J[IndexOf検索]
    J --> K{マッチ?}
    K -->|No| L[次のディスクリプタ]
    L --> I
    K -->|Yes| M{単語境界チェック}
    M -->|No| L
    M -->|Yes| N[FSharpTaskListItem生成]
    N --> L
    I --> H
    D --> O[ImmutableArray生成]
    O --> P[返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-70-01 | コメント連結 | 隣接するコメントトークンは1つに連結 | コメント抽出時 |
| BR-70-02 | 単語境界チェック | ディスクリプタの直後が英字の場合は除外（例：TODOabcは除外） | マッチ判定時 |
| BR-70-03 | 大文字小文字無視 | ディスクリプタの検索は大文字小文字を区別しない | 検索時 |
| BR-70-04 | コメント終端トリム | `*)`や`)`などのコメント終端文字はトリム | テキスト抽出時 |

### 計算ロジック

コメント連結ロジック（38-56行目）:
```fsharp
let extractContractedComments (tokens: Tokenizer.SavedTokenInfo[]) =
    let granularTokens =
        tokens |> Array.filter (fun t -> t.Kind = LexerSymbolKind.Comment)

    let contractedTokens =
        ([], granularTokens)
        ||> Array.fold (fun acc token ->
            let token = {| Left = token.LeftColumn; Right = token.RightColumn |}
            match acc with
            | [] -> [ token ]
            | head :: tail when token.Left - head.Right <= 1 ->
                {| token with Left = head.Left |} :: tail
            | _ -> token :: acc)

    contractedTokens
```

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

該当なし（メモリ内解析のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | トークン化失敗 | 行のトークン化に失敗 | 該当行をスキップ |
| - | 範囲外アクセス | インデックス計算が範囲外 | 該当トークンをスキップ |

### リトライ仕様

リトライなし。

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

該当なし（読み取り専用操作）

## パフォーマンス要件

- ファイル変更時に非同期で更新
- 大規模ファイルでもバックグラウンド処理

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

該当なし

## 備考

- FSharpTaskListServiceがIFSharpTaskListServiceを実装
- backgroundTaskで非同期処理を実行
- extractContractedCommentsで隣接コメントを連結して処理

---

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

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

### 推奨読解順序

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

タスクリストで使用される主要なデータ型を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | TaskListService.fs | `vsintegration/src/FSharp.Editor/TaskList/TaskListService.fs` | FSharpTaskListItem、FSharpTaskListDescriptor |

**読解のコツ**:
- FSharpTaskListItem: タスク項目を表す型（Descriptor、Text、Document、Span）
- FSharpTaskListDescriptor: タスク種別を表す型（Text、Priority等）

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

IFSharpTaskListServiceの実装から読み始める。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | TaskListService.fs | `vsintegration/src/FSharp.Editor/TaskList/TaskListService.fs` | FSharpTaskListServiceクラス |

**主要処理フロー**:
1. **18-19行目**: クラス定義とExportアトリビュート
2. **118-125行目**: IFSharpTaskListService.GetTaskListItemsAsync実装

#### Step 3: ヘルパー関数を理解する

getDefinesAndLangVersionとextractContractedCommentsを理解。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TaskListService.fs | `vsintegration/src/FSharp.Editor/TaskList/TaskListService.fs` | ヘルパー関数 |

**主要処理フロー**:
- **21-37行目**: getDefinesAndLangVersion関数（パーシングオプション取得）
- **38-56行目**: extractContractedComments関数（コメント連結）

#### Step 4: タスク検出ロジックを理解する

GetTaskListItemsメンバーがタスク検出の中核。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | TaskListService.fs | `vsintegration/src/FSharp.Editor/TaskList/TaskListService.fs` | GetTaskListItemsメンバー |

**主要処理フロー**:
- **58-116行目**: GetTaskListItemsメンバー
- **69行目**: 空のビルダー作成
- **71-84行目**: 行ごとのトークン化とコメント抽出
- **91-114行目**: ディスクリプタ照合とタスクアイテム生成
- **103-104行目**: IndexOfで検索
- **106行目**: マッチ位置の調整
- **109-110行目**: 単語境界チェック
- **111行目**: テキスト抽出とトリム
- **114行目**: FSharpTaskListItem生成

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

```
IFSharpTaskListService.GetTaskListItemsAsync
    │
    ├─ doc.GetTextAsync
    │      └─ SourceText取得
    │
    ├─ getDefinesAndLangVersion
    │      │
    │      └─ doc.GetFSharpCompilationOptionsAsync
    │             └─ defines, langVersion, strictIndentation
    │
    └─ GetTaskListItems
           │
           ├─ [各行ループ]
           │      │
           │      ├─ Tokenizer.tokenizeLine
           │      │
           │      └─ extractContractedComments
           │             │
           │             └─ コメントトークン連結
           │
           └─ [各コメント、各ディスクリプタループ]
                  │
                  ├─ String.IndexOf (大文字小文字無視)
                  │
                  ├─ 単語境界チェック
                  │
                  ├─ テキストトリム
                  │
                  └─ FSharpTaskListItem生成
```

### データフロー図

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

Document ─────────────▶ GetTextAsync ─────────────────────┐
                              │                           │
                              ▼                           │
                        SourceText                        │
                              │                           │
                              ▼                           │
descriptors[] ────────▶ GetTaskListItems ─────────────────┤
                              │                           │
                              ├─ [各行]                   │
                              │      │                    │
                              │      └─ tokenizeLine      │
                              │             │             │
                              │             ▼             │
                              │      extractContractedComments
                              │             │             │
                              │             ▼             │
                              │      連結されたコメント   │
                              │             │             │
                              └─ [各ディスクリプタ]       │
                                     │                    │
                                     └─ IndexOf検索       │
                                            │             │
                                            ▼             ▼
                        ImmutableArray<FSharpTaskListItem> ──▶ タスクリストUI
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| TaskListService.fs | `vsintegration/src/FSharp.Editor/TaskList/TaskListService.fs` | ソース | タスクリストサービス実装 |
| Tokenizer.fs | `vsintegration/src/FSharp.Editor/Common/Tokenizer.fs` | ソース | トークン化処理 |
