# 機能設計書 84-DebuggerDisplay追加

## 概要

本ドキュメントは、Roslyn IDEにおけるDebuggerDisplay属性追加リファクタリング機能の設計を記載する。この機能は、クラスや構造体にSystem.Diagnostics.DebuggerDisplay属性を追加し、デバッグ時の表示をカスタマイズするためのコードを自動生成する。

### 本機能の処理概要

DebuggerDisplay属性追加機能は、開発者がデバッグ時にオブジェクトの内容を見やすく表示するためのコードを自動生成する。DebuggerDisplay属性は、デバッガーの変数ウィンドウやウォッチウィンドウでオブジェクトを表示する際に使用される文字列を指定するために使われる。

**業務上の目的・背景**：デバッグ時に複雑なオブジェクトの内容を確認する際、デフォルトの表示（型名のみ）では十分な情報が得られない。DebuggerDisplay属性を使用することで、オブジェクトの重要なプロパティを一目で確認でき、デバッグ効率が向上する。しかし、この属性を手動で正しく記述するには知識が必要であり、本機能がその作業を自動化する。

**機能の利用シーン**：
- クラスや構造体を作成し、デバッグ表示をカスタマイズしたい場合
- ToStringメソッドにカーソルがある状態でライトバルブを表示した場合
- GetDebuggerDisplayメソッドにカーソルがある状態でライトバルブを表示した場合
- 型定義のヘッダー部分でライトバルブを表示した場合

**主要な処理内容**：
1. 対象型（クラスまたは構造体）の検出
2. 既存のDebuggerDisplay属性の有無確認
3. DebuggerDisplay属性の生成と追加
4. GetDebuggerDisplayメソッドの生成（未存在の場合）

**関連システム・外部連携**：System.Diagnostics名前空間

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | コードエディタ | 主画面 | ライトバルブメニューからリファクタリング実行 |

## 機能種別

コードリファクタリング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| context | CodeRefactoringContext | Yes | リファクタリングコンテキスト | - |

### 入力データソース

- エディタ上のカーソル位置
- ドキュメントの構文木とセマンティックモデル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| CodeAction | CodeAction | DebuggerDisplay属性追加アクション |

### 出力先

エディタ（コード変更）

## 処理フロー

### 処理シーケンス

```
1. カーソル位置から対象ノードを取得
   └─ TryGetRelevantNodeAsyncでTypeDeclarationまたはMethodDeclarationを取得
2. 対象型の検証
   └─ クラスまたは構造体であること、静的でないこと
3. 既存属性のチェック
   └─ HasDebuggerDisplayAttributeで既存属性を確認
4. コードアクション登録
   └─ RegisterRefactoringでアクションを登録
5. 属性追加実行
   └─ Applyで属性とメソッドを追加
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[カーソル位置のノード取得]
    B --> C{型宣言または<br>メソッド宣言?}
    C -->|No| D[終了]
    C -->|Yes| E[セマンティックモデル取得]
    E --> F{クラスまたは構造体?}
    F -->|No| D
    F -->|Yes| G{静的型?}
    G -->|Yes| D
    G -->|No| H{既にDebuggerDisplay<br>属性あり?}
    H -->|Yes| D
    H -->|No| I[コードアクション登録]
    I --> J[アクション実行時]
    J --> K[DebuggerDisplay属性追加]
    K --> L{GetDebuggerDisplay<br>メソッドあり?}
    L -->|Yes| D
    L -->|No| M[GetDebuggerDisplayメソッド追加]
    M --> D
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 対象型制限 | クラスまたは構造体のみ対象 | インターフェース、列挙型、デリゲートは除外 |
| BR-02 | 静的型除外 | 静的クラスは対象外 | static classは処理しない |
| BR-03 | 既存属性チェック | 既にDebuggerDisplay属性がある場合は対象外 | 重複追加を防止 |
| BR-04 | メソッド生成条件 | GetDebuggerDisplayメソッドがない場合のみ生成 | 既存メソッドは保持 |

### 計算ロジック

生成されるDebuggerDisplay属性の値は`{GetDebuggerDisplay(),nq}`形式。`nq`は引用符なし(no quotes)を意味する。

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

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 処理スキップ | DebuggerDisplayAttribute型が見つからない | コードアクションを表示しない |
| - | 処理スキップ | 対象型が条件を満たさない | コードアクションを表示しない |

### リトライ仕様

なし

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

なし（エディタバッファへの変更のみ）

## パフォーマンス要件

- コードアクション計算はライトバルブ表示時に100ms以内

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

特になし

## 備考

- ToStringメソッドにカーソルがある場合は低優先度（CodeActionPriority.Low）
- GetDebuggerDisplayメソッドにカーソルがある場合は通常優先度（CodeActionPriority.Default）
- C# 10以降では定数補間文字列を使用可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | AbstractAddDebuggerDisplayCodeRefactoringProvider.cs | `src/Features/Core/Portable/AddDebuggerDisplay/AbstractAddDebuggerDisplayCodeRefactoringProvider.cs` | リファクタリングプロバイダー基底クラス |

**主要処理フロー**:
1. **31-64行目**: ComputeRefactoringsAsyncでリファクタリング計算
2. **33行目**: ドキュメントとキャンセルトークン取得
3. **35-38行目**: 型宣言またはメソッド宣言からリファクタリング対象を特定
4. **47-49行目**: DebuggerDisplayAttribute型の存在確認
5. **53-57行目**: 静的型やインターフェースを除外
6. **59-63行目**: コードアクション登録

#### Step 2: リファクタリング対象の検出を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AbstractAddDebuggerDisplayCodeRefactoringProvider.cs | `src/Features/Core/Portable/AddDebuggerDisplay/AbstractAddDebuggerDisplayCodeRefactoringProvider.cs` | 対象ノード検出ロジック |

**主要処理フロー**:
- **66-73行目**: GetRelevantTypeFromHeaderAsyncで型宣言ヘッダーから取得
- **75-97行目**: GetRelevantTypeFromMethodAsyncでメソッドから取得
- **99-103行目**: IsToStringMethodでToStringメソッドを判定
- **102-103行目**: IsDebuggerDisplayMethodでGetDebuggerDisplayメソッドを判定

#### Step 3: コード変更を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AbstractAddDebuggerDisplayCodeRefactoringProvider.cs | `src/Features/Core/Portable/AddDebuggerDisplay/AbstractAddDebuggerDisplayCodeRefactoringProvider.cs` | 属性・メソッド追加ロジック |

**主要処理フロー**:
- **113-148行目**: 属性引数の生成（定数補間文字列またはnameof式）
- **122-133行目**: SupportsConstantInterpolatedStringsがtrueなら補間文字列使用
- **137-141行目**: そうでなければ文字列連結を使用
- **150-154行目**: 属性をSimplifier.Annotationで簡略化
- **156行目**: editor.AddAttributeで属性追加
- **160-173行目**: GetDebuggerDisplayメソッドがなければ生成

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

```
AbstractAddDebuggerDisplayCodeRefactoringProvider.ComputeRefactoringsAsync
    │
    ├─ GetRelevantTypeFromHeaderAsync
    │      └─ TryGetRelevantNodeAsync<TTypeDeclarationSyntax>
    │
    ├─ GetRelevantTypeFromMethodAsync
    │      ├─ TryGetRelevantNodeAsync<TMethodDeclarationSyntax>
    │      ├─ IsDebuggerDisplayMethod
    │      └─ IsToStringMethod
    │
    ├─ HasDebuggerDisplayAttribute
    │      └─ typeSymbol.GetAttributes()
    │
    └─ ApplyAsync
           ├─ SyntaxEditor.AddAttribute
           │      └─ generator.Attribute (属性生成)
           │
           └─ SyntaxEditor.AddMember
                  └─ generator.MethodDeclaration (メソッド生成)
```

### データフロー図

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

カーソル位置 ───▶ TryGetRelevantNodeAsync
                        │
                        ▼
                  型宣言/メソッド宣言
                        │
                        ▼
SemanticModel ──▶ シンボル解決
                        │
                        ▼
                  HasDebuggerDisplayAttribute
                        │
                        ▼
                  CodeAction登録 ───▶ ライトバルブメニュー
                        │
                        ▼
                  ApplyAsync ───▶ 変更後Document
                        │
                        ├─ 属性追加
                        │
                        └─ メソッド追加
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AbstractAddDebuggerDisplayCodeRefactoringProvider.cs | `src/Features/Core/Portable/AddDebuggerDisplay/AbstractAddDebuggerDisplayCodeRefactoringProvider.cs` | ソース | リファクタリング基底クラス |
| CSharpAddDebuggerDisplayCodeRefactoringProvider.cs | `src/Features/CSharp/Portable/AddDebuggerDisplay/CSharpAddDebuggerDisplayCodeRefactoringProvider.cs` | ソース | C#言語固有実装 |
| VisualBasicAddDebuggerDisplayCodeRefactoringProvider.cs | `src/Features/VisualBasic/Portable/AddDebuggerDisplay/VisualBasicAddDebuggerDisplayCodeRefactoringProvider.cs` | ソース | VB言語固有実装 |
