scryer-engine 0.3.0

Tree-sitter AST indexing and reference resolution engine for Scryer code intelligence
//! The final link pass: references into later batches link, and what cannot link is counted.

mod support;

use std::fs;

use scryer_db::ScryerDb;
use scryer_engine::{EngineService, IndexOptions};
use support::fixture::index_dir;
use tempfile::tempdir;

#[tokio::test]
async fn unresolved_references_are_counted_and_stored_references_are_reported() -> anyhow::Result<()>
{
    let temp = tempdir()?;
    fs::write(
        temp.path().join("a.py"),
        "def first():\n    zed()\n    missing_one()\n    missing_two()\n",
    )?;
    fs::write(temp.path().join("z.py"), "def zed():\n    return 1\n")?;

    let db = ScryerDb::new_in_memory().await?;
    // Cap 1 stores `a.py` before `z.py`: `zed` only exists in a later batch.
    let options = IndexOptions {
        writer_batch_cap: 1,
        ..IndexOptions::default()
    };
    let (project, report) = index_dir(&db, temp.path(), options).await?;

    assert_eq!(report.unresolved_references, 2, "{report:?}");
    // The call to `zed` (and its edge) linked in the final pass.
    assert_eq!(report.total_references, 1, "{report:?}");
    assert_eq!(report.total_edges, 1, "{report:?}");

    let stats = EngineService::new(db.clone())
        .index_stats(project)
        .await?
        .expect("index stats are stored");
    assert_eq!(stats.unresolved_references, 2);
    Ok(())
}

#[tokio::test]
async fn a_run_with_no_changes_keeps_the_previous_stats() -> anyhow::Result<()> {
    let temp = tempdir()?;
    fs::write(temp.path().join("a.py"), "def first():\n    missing()\n")?;
    let db = ScryerDb::new_in_memory().await?;
    let (project, _) = index_dir(&db, temp.path(), IndexOptions::default()).await?;

    let again = EngineService::new(db.clone())
        .index_project(project, temp.path())
        .await?;
    assert_eq!(again.modified_files + again.added_files, 0);
    let stats = EngineService::new(db).index_stats(project).await?;
    assert_eq!(stats.expect("kept").unresolved_references, 1);
    Ok(())
}