# バッチ設計書 53-get-fsharp-errors.sh

## 概要

本ドキュメントは、F#診断サーバーへのクライアントスクリプト `.github/skills/fsharp-diagnostics/scripts/get-fsharp-errors.sh` の設計書です。このスクリプトはUnixソケット経由でF#診断サーバーと通信し、F#ソースファイルの構文解析、型チェック、参照検索などの診断機能を提供します。

### 本バッチの処理概要

このバッチは、F#言語サービスを活用した診断機能を提供するクライアントスクリプトです。バックグラウンドで動作するF#診断サーバー（FSharpDiagServer）と通信し、ソースファイルの解析結果やエラー情報を取得します。サーバーが起動していない場合は自動的に起動し、Unixソケットを介してJSON形式でリクエスト/レスポンスを交換します。

**業務上の目的・背景**：F#コンパイラプロジェクトの開発において、ソースコードの品質確認やエラー検出は重要なタスクです。このスクリプトは、IDEを使用せずにコマンドラインからF#コードの診断情報を取得することを可能にします。特に、CI/CD環境やスクリプトベースの自動化において、F#ファイルの検証を行う際に使用されます。また、開発者がローカル環境で素早くコードの問題を検出するためのツールとしても機能します。

**バッチの実行タイミング**：
- 開発者がF#ファイルのエラーチェックを行う際
- CI/CDパイプラインでのコード品質チェック
- プロジェクト全体の型チェックを行う際
- 参照検索や型ヒントを取得する際
- サーバーの起動確認（ping）やシャットダウン

**主要な処理内容**：
1. Gitリポジトリルートの検出
2. リポジトリ固有のUnixソケットパスの生成（SHA256ハッシュベース）
3. サーバーの存在確認とpingによる応答チェック
4. サーバーが起動していない場合は自動起動（dotnet run）
5. ソケット接続を待機（最大60秒）
6. JSONコマンドをサーバーに送信
7. サーバーからの応答を標準出力に出力

**前後の処理との関連**：このスクリプトは `server/` ディレクトリにあるF#診断サーバー（FSharpDiagServer）に依存しています。サーバーは.NET上で動作し、FSharp.Compiler.Serviceを使用してF#コードの解析を行います。サーバーはリポジトリごとに独立したUnixソケットで通信し、複数のリポジトリを同時に扱うことができます。

**影響範囲**：
- `$HOME/.fsharp-diag/` ディレクトリ：ソケットファイルとログファイルの保存
- サーバープロセス：バックグラウンドで動作する.NETプロセス
- ネットワーク：ローカルUnixソケット通信のみ（外部ネットワークなし）

## バッチ種別

診断 / 開発支援ツール

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時 |
| 実行時刻 | 任意 |
| 実行曜日 | 該当なし |
| 実行日 | 該当なし |
| トリガー | 手動 / CI/CDパイプライン / 開発ツール連携 |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| bashシェル | Linux/macOS環境 |
| .NET SDK | サーバーの起動に必要 |
| netcat (nc) | Unixソケット通信に使用 |
| git | リポジトリルートの検出に使用 |
| shasum | ソケットパス生成に使用 |

### 実行可否判定

- Gitリポジトリ内で実行されることが推奨（リポジトリルートの検出に使用）
- 対象のF#ファイルまたはプロジェクトファイルが存在すること
- .NET SDKがインストールされていること

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| --ping | flag | No | - | サーバーへのping確認 |
| --shutdown | flag | No | - | サーバーのシャットダウン |
| --parse-only | flag | No | - | 構文解析のみ実行（型チェックなし） |
| --check-project | flag | No | - | プロジェクト全体の型チェック |
| --find-refs | flag | No | - | 指定位置からの参照検索 |
| --type-hints | flag | No | - | 指定範囲の型ヒント取得 |
| file.fs | string | 条件付き | - | 解析対象のF#ファイル（checkコマンド時） |
| line | number | 条件付き | - | 行番号（--find-refs時） |
| col | number | 条件付き | - | 列番号（--find-refs時） |
| startLine | number | 条件付き | - | 開始行（--type-hints時） |
| endLine | number | 条件付き | - | 終了行（--type-hints時） |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| F#ソースファイル | .fs | 解析対象のソースコード |
| F#プロジェクトファイル | .fsproj | プロジェクト設定 |
| Gitリポジトリ情報 | .git | リポジトリルートの検出 |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| 標準出力 | JSON | サーバーからの応答（診断結果、エラー情報など） |
| 標準エラー出力 | テキスト | エラーメッセージ（サーバー起動失敗など） |
| ~/.fsharp-diag/*.sock | Unixソケット | サーバーとの通信チャネル |
| ~/.fsharp-diag/*.log | テキスト | サーバーログ |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| ファイル名 | {hash}.sock（ソケット）、{hash}.log（ログ） |
| 出力先 | $HOME/.fsharp-diag/ |
| 文字コード | UTF-8 |
| 区切り文字 | 該当なし（JSON形式） |

## 処理フロー

### 処理シーケンス

```
1. スクリプトディレクトリとサーバープロジェクトパスの解決
   └─ SCRIPT_DIR、SERVER_PROJECTの設定

2. Gitリポジトリルートの検出
   └─ git rev-parse --show-toplevelまたはpwdを使用

3. ソケットパスの生成
   └─ リポジトリルートのSHA256ハッシュ（先頭16文字）を使用

4. コマンドの解析
   ├─ --ping: サーバー確認とpingコマンド送信
   ├─ --shutdown: shutdownコマンド送信
   ├─ --parse-only: ファイルの構文解析のみ
   ├─ --check-project: プロジェクト全体のチェック
   ├─ --find-refs: 参照検索
   ├─ --type-hints: 型ヒント取得
   └─ デフォルト: ファイルの型チェック

5. サーバーの確認・起動（ensure_server関数）
   ├─ ソケットファイルの存在確認
   ├─ pingによる応答確認
   ├─ 無応答の場合は古いソケットを削除
   ├─ dotnet runでサーバーをバックグラウンド起動
   └─ ソケット出現を最大60秒待機

6. リクエストの送信（send_request関数）
   └─ ncコマンドでUnixソケット経由でJSON送信

7. 応答の出力
   └─ サーバーからのJSON応答を標準出力に出力
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[パス解決]
    B --> C[リポジトリルート検出]
    C --> D[ソケットパス生成]
    D --> E{コマンド種別}
    E -->|--ping| F[ensure_server]
    E -->|--shutdown| G[send_request shutdown]
    E -->|--parse-only| H[ファイルパス解決]
    E -->|--check-project| I[ensure_server]
    E -->|--find-refs| J[パラメータ解析]
    E -->|--type-hints| K[パラメータ解析]
    E -->|default| L[ファイルパス解決]

    F --> F1[ping送信]
    H --> H1[ensure_server]
    H1 --> H2[parseOnly送信]
    I --> I1[checkProject送信]
    J --> J1[ensure_server]
    J1 --> J2[findRefs送信]
    K --> K1[ensure_server]
    K1 --> K2[typeHints送信]
    L --> L1[ensure_server]
    L1 --> L2[check送信]

    F1 --> Z[応答出力]
    G --> Z
    H2 --> Z
    I1 --> Z
    J2 --> Z
    K2 --> Z
    L2 --> Z
    Z --> ZZ[バッチ終了]

    subgraph ensure_server
        ES1[ソケット存在確認] --> ES2{存在?}
        ES2 -->|あり| ES3[ping送信]
        ES3 --> ES4{応答?}
        ES4 -->|ok| ES5[正常]
        ES4 -->|なし| ES6[古いソケット削除]
        ES2 -->|なし| ES7[サーバー起動]
        ES6 --> ES7
        ES7 --> ES8[ソケット待機 max60秒]
        ES8 --> ES9{出現?}
        ES9 -->|あり| ES5
        ES9 -->|なし| ES10[エラー終了]
    end
```

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

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

このバッチはデータベース操作を行いません。

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 該当なし | - | - | - |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | 引数エラー | 不正なオプションが指定された場合 | usageメッセージを参照 |
| 1 | サーバー起動エラー | サーバーが60秒以内に起動しない場合 | ログファイルを確認し、.NET SDK環境を確認 |
| 1 | ファイル不存在 | 指定されたF#ファイルが存在しない場合 | ファイルパスを確認 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | サーバー起動待機：60回（1秒間隔） |
| リトライ間隔 | 1秒 |
| リトライ対象エラー | サーバー起動待機 |

### 障害時対応

1. `~/.fsharp-diag/{hash}.log` でサーバーログを確認
2. `--shutdown` で既存サーバーを停止し、再起動を試行
3. `~/.fsharp-diag/` ディレクトリの古いソケットファイルを手動削除
4. .NET SDKが正しくインストールされているか確認
5. サーバープロジェクトが正しくビルドできるか確認

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | 該当なし（ステートレスなリクエスト/レスポンス） |
| コミットタイミング | 該当なし |
| ロールバック条件 | 該当なし |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 1ファイル/1リクエスト |
| 目標処理時間 | 初回起動時：60秒以内、以降：数秒以内 |
| メモリ使用量上限 | サーバープロセスに依存 |

## 排他制御

- サーバーはリポジトリごとに独立したソケットで動作
- 同一リポジトリへの複数クライアントからの同時リクエストはサーバー側でシリアライズ
- 古いソケットは自動的に削除され、新しいサーバーが起動

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| サーバーログ | サーバー動作中 | 処理内容、エラー情報 |
| エラーログ | サーバー起動失敗時 | "Server failed to start within 60s. Check log: {path}" |
| Usage | 不正な引数時 | 使用方法の説明 |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| サーバー応答時間 | 60秒 | スクリプト終了コード |
| 終了コード | 0以外 | 呼び出し元スクリプト |

## 備考

- このスクリプトはF#コンパイラプロジェクトの開発支援ツールとして提供されている
- サーバーはnohupでバックグラウンド起動され、明示的にshutdownするまで動作し続ける
- リポジトリごとに独立したソケットを使用するため、複数のリポジトリを同時に扱える
- set -euo pipefailにより、エラー時に即座に終了する堅牢なスクリプト
- 対応コマンド：ping、shutdown、parseOnly、check、checkProject、findRefs、typeHints
- サーバーはFSharp.Compiler.Serviceを使用してF#コードの解析を行う
