# 機能設計書 69-JDKソース解析

## 概要

本ドキュメントは、Clojure LSPにおけるJDKソース解析機能の設計を定義する。この機能は、JDKのソースコードを解析してjava.*パッケージのクラス定義情報を取得し、Javaクラス補完や定義ジャンプの精度を向上させる。

### 本機能の処理概要

**業務上の目的・背景**：Clojure開発では、java.util.*, java.io.*, java.lang.* などの標準JDKクラスを頻繁に使用する。これらのクラスに対する補完や定義ジャンプを正確に行うため、JDKのソースコードを解析してクラス定義情報を取得する必要がある。この機能は、JDKソースを自動検出・ダウンロードし、clj-kondoで解析してグローバルキャッシュに保存する。

**機能の利用シーン**：
- LSPサーバー起動時にJDKソースの解析（または解析結果のキャッシュロード）
- java.* パッケージのクラスに対する補完候補の提供
- JDKクラスの定義ジャンプ

**主要な処理内容**：
1. JDKソースの場所を特定（ローカル自動検出、カスタムパス、ダウンロード）
2. src.zip を展開してJavaファイルを取得
3. clj-kondoでJavaソースを解析
4. 解析結果をグローバルキャッシュに保存

**関連システム・外部連携**：clj-kondo（Java解析）、ファイルシステム（キャッシュ）、HTTP（JDKソースダウンロード）。

**権限による制御**：:java :download-jdk-source? 設定でダウンロードの可否を制御。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 該当なし | 該当なし | 該当なし | 本機能はLSPサーバー起動時に自動実行される |

## 機能種別

解析処理 / キャッシュ管理 / 初期化処理

## 入力仕様

### 入力パラメータ

本機能は設定に基づいて自動実行される。

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| :java :jdk-source-uri | string | No | カスタムJDKソースのパス/URL | ファイルパスまたはURL |
| :java :home-path | string | No | JAVA_HOME パス | 有効なディレクトリパス |
| :java :download-jdk-source? | boolean | No | JDKソースのダウンロード許可（デフォルト: false） | true/false |

### 入力データソース

- 設定ファイル（.lsp/config.edn）
- 環境変数（JAVA_HOME）
- システムプロパティ（java.home）
- ローカルファイルシステム（src.zip の自動検出）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 解析結果 | map | Javaクラス定義情報 |
| チェックサム | map | 解析済みファイルのチェックサム |

### 出力先

- 内部DB（:analysis に統合）
- グローバルキャッシュファイル

## 処理フロー

### 処理シーケンス

```
1. JDKソースの場所を決定
   └─ jdk-analysis-decision で5つのシナリオを判定
2. 既にインストール済みの場合
   └─ キャッシュからロード
3. ローカルJDKソースが見つかった場合
   └─ src.zip を展開してグローバルキャッシュに配置
4. カスタムURIが指定された場合
   └─ 指定されたパス/URLからソースを取得
5. ダウンロードが許可されている場合
   └─ デフォルトOpenJDKソースをダウンロード
6. Javaファイルをclj-kondoで解析
   └─ java.* パッケージのみを保持
7. 解析結果をキャッシュに保存
```

### フローチャート

```mermaid
flowchart TD
    A[retrieve-jdk-source-and-analyze!] --> B{既にインストール済み?}
    B -->|Yes| C[キャッシュからロード]
    B -->|No| D{ローカルJDK検出?}
    D -->|Yes| E[src.zip を展開]
    D -->|No| F{カスタムURI指定?}
    F -->|Yes| G[指定パスから取得]
    F -->|No| H{ダウンロード許可?}
    H -->|Yes| I[OpenJDKをダウンロード]
    H -->|No| J[スキップ]
    E --> K[java.* パッケージのみ保持]
    G --> K
    I --> K
    K --> L[clj-kondo で解析]
    L --> M[グローバルキャッシュに保存]
    C --> N[内部DBにマージ]
    M --> N
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 自動検出優先 | ローカルJDKソースの自動検出を最優先 | カスタムURI未指定時 |
| BR-02 | java.* 限定 | java.* パッケージのみを解析対象として保持 | 常時 |
| BR-03 | チェックサム管理 | ファイルのチェックサムで解析済み判定 | 常時 |
| BR-04 | デフォルトダウンロードOff | download-jdk-source? はデフォルトfalse | 常時 |

### 計算ロジック

**JDK検出パスの優先順位**:
1. :java :home-path 設定
2. java.home システムプロパティ
3. JAVA_HOME 環境変数
4. which java からの検出

**検索対象src.zipパス**:
- {JAVA_HOME}/src.zip
- {JAVA_HOME}/lib/src.zip
- {JAVA_HOME}/../src.zip
- {JAVA_HOME}/../lib/src.zip

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 解析結果マージ | db[:analysis] | UPDATE | Java解析結果を統合 |
| チェックサム更新 | db[:analysis-checksums] | UPDATE | 解析済みファイルのチェックサム |

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

#### db[:analysis]

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | :java-class-definitions | JDKクラス定義 | lsp.kondo/db-with-analysis 経由 |

#### グローバルキャッシュ

| 操作 | 項目 | 更新値・取得条件 | 備考 |
|-----|-----|-----------------|------|
| WRITE | analysis | 解析結果全体 | db/read-and-update-global-cache! |
| WRITE | analysis-checksums | チェックサムマップ | 同上 |
| WRITE | version | キャッシュバージョン | 同上 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 警告ログ | JDKソースが見つからない | 警告を出力してスキップ |
| - | エラーログ | ダウンロード失敗 | エラーを出力してスキップ |
| - | エラーログ | 解析失敗 | エラーを出力してスキップ |

### リトライ仕様

リトライは実装されていない。次回起動時に再試行。

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

- swap! によるアトミック更新
- ファイルキャッシュは非アトミック

## パフォーマンス要件

- 初回解析: 数十秒〜数分（JDKソースサイズに依存）
- キャッシュからのロード: 数秒以内

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

- ダウンロードURLはデフォルトで公式GitHubリポジトリ
- カスタムURLを指定可能だが、ユーザーの責任

## 備考

- デフォルトJDKソースURL: https://raw.githubusercontent.com/clojure-lsp/jdk-source/main/openjdk-19/reduced/source.zip
- グローバルキャッシュ: ~/.cache/clojure-lsp/jdk/

---

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

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

### 推奨読解順序

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

JDK解析のデータフローとキャッシュ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | db.clj | `lib/src/clojure_lsp/db.clj` | グローバルキャッシュの構造 |

**読解のコツ**: グローバルキャッシュは {:analysis {...} :analysis-checksums {...} :version ...} の形式。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | handlers.clj | `lib/src/clojure_lsp/handlers.clj` | initialize 後の非同期タスク（189-200行目） |

**主要処理フロー**:
- **193-194行目**: :java 設定が有効な場合、f.java-interop/retrieve-jdk-source-and-analyze! を呼び出し

#### Step 3: コア機能を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | java_interop.clj | `lib/src/clojure_lsp/feature/java_interop.clj` | jdk-analysis-decision（200-233行目） |
| 3-2 | java_interop.clj | `lib/src/clojure_lsp/feature/java_interop.clj` | find-local-jdk-source（135-150行目） |
| 3-3 | java_interop.clj | `lib/src/clojure_lsp/feature/java_interop.clj` | download-jdk!（152-181行目） |
| 3-4 | java_interop.clj | `lib/src/clojure_lsp/feature/java_interop.clj` | analyze-and-cache-jdk-source!（183-195行目） |
| 3-5 | java_interop.clj | `lib/src/clojure_lsp/feature/java_interop.clj` | retrieve-jdk-source-and-analyze!（247-326行目） |

**主要処理フロー**:
- **200-233行目**: jdk-analysis-decision - 5つのシナリオを判定
  - :jdk-already-installed
  - :automatic-local-jdk
  - :manual-local-jdk
  - :download-jdk
  - :no-source-found
- **135-150行目**: find-local-jdk-source - ローカルJDKソースの自動検出
- **152-181行目**: download-jdk! - JDKソースのダウンロード
- **183-195行目**: analyze-and-cache-jdk-source! - 解析とキャッシュ保存
- **247-326行目**: retrieve-jdk-source-and-analyze! - メイン処理フロー

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

```
handlers.clj::initialize (非同期タスク)
    │
    └─ java_interop.clj::retrieve-jdk-source-and-analyze!
           │
           ├─ jdk-analysis-decision (シナリオ判定)
           │      │
           │      ├─ find-local-jdk-source
           │      │
           │      └─ settings から :jdk-source-uri, :download-jdk-source? 取得
           │
           ├─ (case result)
           │      ├─ :jdk-already-installed → キャッシュロード
           │      ├─ :automatic-local-jdk → fs/unzip
           │      ├─ :manual-local-jdk → fs/unzip
           │      └─ :download-jdk → download-jdk!
           │
           ├─ java.* パッケージ以外を削除
           │
           └─ analyze-and-cache-jdk-source!
                  │
                  ├─ kondo.clj::run-kondo-on-jdk-source!
                  │
                  └─ db.clj::read-and-update-global-cache!
```

### データフロー図

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

設定:                      retrieve-jdk-source-and-analyze!
:jdk-source-uri                │
:download-jdk-source?          ▼
        │               jdk-analysis-decision
        │                      │
        │           ┌──────────┼──────────┐
        │           ▼          ▼          ▼
        │     :automatic  :manual     :download
        │     -local-jdk  -local-jdk  -jdk
        │           │          │          │
        │           ▼          ▼          ▼
        │        fs/unzip   fs/unzip  download-jdk!
        │           │          │          │
        └───────────┼──────────┼──────────┘
                    ▼
              java.* パッケージのみ保持
                    │
                    ▼
              run-kondo-on-jdk-source!
                    │
                    ▼
              {:analysis {:java-class-definitions [...]}}
                    │
           ┌───────┴───────┐
           ▼               ▼
      内部DB更新      グローバルキャッシュ保存
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| java_interop.clj | `lib/src/clojure_lsp/feature/java_interop.clj` | ソース | JDK解析のコアロジック |
| handlers.clj | `lib/src/clojure_lsp/handlers.clj` | ソース | 初期化時の呼び出し |
| db.clj | `lib/src/clojure_lsp/db.clj` | ソース | グローバルキャッシュ管理 |
| kondo.clj | `lib/src/clojure_lsp/kondo.clj` | ソース | clj-kondo解析 |
| http.clj | `lib/src/clojure_lsp/http.clj` | ソース | HTTPダウンロード |
| java_interop_test.clj | `lib/test/clojure_lsp/feature/java_interop_test.clj` | テスト | ユニットテスト |
