# 機能設計書 71-プロジェクト解析

## 概要

本ドキュメントは、clojure-lsp の API として提供される `analyze-project-and-deps!` 関数の機能設計を記述する。この関数はプロジェクト全体と全ての外部依存関係を解析し、解析結果をキャッシュして後続の API 呼び出しを高速化する機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：Clojure プロジェクトで IDE 機能（コード補完、定義ジャンプ、リファクタリング等）を利用するには、プロジェクトのソースコードと依存ライブラリの解析情報が必要となる。この機能は、REPL 環境や CI/CD パイプラインから clojure-lsp の各種機能を利用する前に、プロジェクト全体の静的解析を完了させるためのエントリーポイントを提供する。

**機能の利用シーン**：REPL からの対話的な利用、CI/CD でのコード品質チェック、バッチ処理でのリファクタリング実行前の事前解析などで利用される。一度解析を完了すると、後続の API 呼び出し（`diagnostics`、`rename!`、`references` 等）がキャッシュされた解析結果を再利用できる。

**主要な処理内容**：
1. プロジェクトルートの特定とバリデーション
2. clj-kondo による静的解析の実行
3. クラスパスの解決と外部依存関係の解析
4. 解析結果の内部データベース（atom）へのキャッシュ
5. 解析完了ステータスの返却

**関連システム・外部連携**：clj-kondo（静的解析ツール）、clj-depend（依存関係検証）、プロジェクトのビルドツール（deps.edn、Leiningen、shadow-cljs 等）からのクラスパス情報取得。

**権限による制御**：本機能は API として提供されるため、呼び出し元のプロセスの権限でファイルシステムにアクセスする。特別なロールや権限制御は存在しない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 該当なし | 該当なし | 該当なし | 本プロジェクトは LSP サーバー実装であり UI 画面は存在しない |

## 機能種別

データ連携 / 計算処理 / キャッシュ管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| :project-root | java.io.File | No | プロジェクトルートディレクトリ | nil または存在するディレクトリを示す File オブジェクト |
| :settings | Map | No | clojure-lsp 設定マップ | nil または map? が true |

### 入力データソース

- ファイルシステム（プロジェクトのソースファイル群）
- クラスパス（deps.edn、project.clj 等から解決）
- 既存の解析キャッシュ（.lsp/.cache ディレクトリ）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | truthy/falsey | 解析が新規実行された場合は truthy、既に解析済みの場合は falsey |

### 出力先

- 内部データベース（atom）へのキャッシュ
- ファイルシステム（.lsp/.cache ディレクトリへの永続化）

## 処理フロー

### 処理シーケンス

```
1. パラメータバリデーション
   └─ :project-root と :settings の事前条件チェック
2. コンポーネント構築
   └─ db*、logger、producer、各種チャネルの初期化
3. API セットアップ
   └─ :api? フラグの設定と診断チャネルの監視開始
4. 既存キャッシュの確認
   └─ 解析済みかつ project-and-full-dependencies タイプならスキップ
5. プロジェクト初期化
   └─ 設定読み込み、クラスパス解決、ソースパス特定
6. 外部依存関係の解析
   └─ クラスパス上の jar ファイルを clj-kondo で解析
7. プロジェクトソースの解析
   └─ ソースパス内のファイルを解析
8. キャッシュの永続化
   └─ 解析結果を .lsp/.cache に保存
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{パラメータ有効?}
    B -->|No| C[AssertionError]
    B -->|Yes| D[コンポーネント構築]
    D --> E[API セットアップ]
    E --> F{既に解析済み?}
    F -->|Yes| G[nil を返却]
    F -->|No| H[プロジェクト初期化]
    H --> I[外部依存解析]
    I --> J[プロジェクト解析]
    J --> K[キャッシュ永続化]
    K --> L[truthy を返却]
    G --> M[終了]
    L --> M
    C --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-71-1 | キャッシュ優先 | 同一プロジェクトが既に解析済みの場合は再解析をスキップ | project-analysis-type が :project-and-full-dependencies |
| BR-71-2 | ハッシュ検証 | プロジェクト設定や kondo 設定が変更された場合は再解析 | project-hash、settings-hash、kondo-config-hash の変更 |

### 計算ロジック

解析タイプの決定：
- `:project-and-full-dependencies`: プロジェクトと全ての外部依存を解析（本関数のデフォルト）
- `:project-and-shallow-analysis`: プロジェクトと浅い依存解析
- `:project-only`: プロジェクトのみ

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 該当なし | 該当なし | 該当なし | RDB は使用しない。atom によるインメモリ DB を使用 |

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

本機能は RDB を使用せず、Clojure の atom でインメモリデータベースを管理する。

主要なデータ構造：
- `:analysis`: clj-kondo 解析結果
- `:classpath`: 解決されたクラスパス
- `:settings`: 適用された設定
- `:project-root-uri`: プロジェクトルート URI

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| AssertionError | バリデーションエラー | project-root が File でない、または存在しない | 有効な File オブジェクトを渡す |
| ExceptionInfo | 解析エラー | プロジェクト解析中のエラー | エラーメッセージを確認し原因を特定 |

### リトライ仕様

リトライ機構は実装されていない。エラー発生時は呼び出し元で再試行を行う。

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

RDB を使用しないため、トランザクション管理は不要。atom の swap! による原子的更新で一貫性を保証。

## パフォーマンス要件

- 初回解析：プロジェクト規模と依存関係数に依存（数秒〜数分）
- キャッシュ利用時：即座に完了（数ミリ秒）
- 外部依存解析はバッチ処理で並列実行

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

- ファイルシステムへのアクセスはプロセス権限に依存
- 外部ライブラリのコードを解析するが実行はしない
- キャッシュファイルは .lsp/.cache ディレクトリにローカル保存

## 備考

- REPL 環境での使用を想定した API 設計
- 解析結果は JVM プロセス内でのみ有効（プロセス終了で消失、ただしファイルキャッシュから復元可能）

---

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

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

### 推奨読解順序

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

まず、解析結果を格納するデータベース構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | db.clj | `lib/src/clojure_lsp/db.clj` | initial-db の構造、atom による状態管理 |

**読解のコツ**: `initial-db` マップの各キー（`:analysis`、`:classpath`、`:settings` 等）が解析処理で更新される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | api.clj | `lib/src/clojure_lsp/api.clj` | 公開 API の定義、入力バリデーション |

**主要処理フロー**:
1. **22-53行目**: `analyze-project-and-deps!` 関数定義、docstring、事前条件、internal-api への委譲

#### Step 3: 内部 API 実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | internal_api.clj | `lib/src/clojure_lsp/internal_api.clj` | 実際の解析ロジック |

**主要処理フロー**:
- **87-102行目**: コンポーネント構築（db*、logger、producer 等）
- **166-171行目**: setup-api! でAPI モードの初期化
- **194-199行目**: setup-project-and-full-deps-analysis! で解析タイプ設定
- **288-290行目**: analyze-project-and-deps!* の実装

#### Step 4: プロジェクト初期化処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | startup.clj | `lib/src/clojure_lsp/startup.clj` | プロジェクト初期化の詳細処理 |

**主要処理フロー**:
- **224-325行目**: initialize-project 関数で設定読み込み、クラスパス解決、解析実行
- **120-145行目**: analyze-external-classpath! で外部依存解析
- **71-91行目**: analyze-source-paths! でプロジェクトソース解析

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

```
api/analyze-project-and-deps!
    |
    +-- internal-api/analyze-project-and-deps!
            |
            +-- build-components
            |       +-- clean-db!
            |       +-- ->CLILogger
            |       +-- ->APIProducer
            |
            +-- analyze-project-and-deps!*
                    |
                    +-- setup-api!
                    |
                    +-- setup-project-and-full-deps-analysis!
                            |
                            +-- analyze!
                                    |
                                    +-- startup/initialize-project
                                            |
                                            +-- config/resolve-for-root
                                            +-- classpath/scan-classpath!
                                            +-- analyze-external-classpath!
                                            +-- analyze-source-paths!
```

### データフロー図

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

{:project-root File      api/analyze-project-and-deps!        {:result truthy/falsey}
 :settings Map}          |                                    |
        |                v                                    |
        +-------------> internal-api                          |
                        |                                     |
                        v                                     |
                   startup/initialize-project                 |
                        |                                     |
        +---------------+---------------+                     |
        v               v               v                     |
   classpath解決    clj-kondo解析    設定マージ              |
        |               |               |                     |
        v               v               v                     |
        +---------------+---------------+                     |
                        |                                     |
                        v                                     |
                   atom (db*) 更新 -----------------------> キャッシュ永続化
                                                              (.lsp/.cache)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| api.clj | `lib/src/clojure_lsp/api.clj` | ソース | 公開 API 定義 |
| internal_api.clj | `lib/src/clojure_lsp/internal_api.clj` | ソース | 内部実装 |
| startup.clj | `lib/src/clojure_lsp/startup.clj` | ソース | プロジェクト初期化 |
| db.clj | `lib/src/clojure_lsp/db.clj` | ソース | データベース管理 |
| kondo.clj | `lib/src/clojure_lsp/kondo.clj` | ソース | clj-kondo 統合 |
| classpath.clj | `lib/src/clojure_lsp/classpath.clj` | ソース | クラスパス解決 |
| config.clj | `lib/src/clojure_lsp/config.clj` | ソース | 設定管理 |
| api_test.clj | `lib/test/clojure_lsp/api_test.clj` | テスト | API テスト |
