mod support;
use scryer_db::{ScryerDb, Symbol, SymbolReference};
use scryer_engine::IndexOptions;
use support::fixture::index_files;
async fn via_of_calls(
db: &ScryerDb,
project: u64,
name: &str,
) -> anyhow::Result<Vec<(u32, String)>> {
let mut conn = db.lock().await;
let ids: Vec<u64> = Symbol::filter_by_project_id(project)
.exec(&mut *conn)
.await?
.into_iter()
.filter(|s| s.name == name)
.map(|s| s.id)
.collect();
let mut out: Vec<(u32, String)> = SymbolReference::filter_by_project_id(project)
.exec(&mut *conn)
.await?
.into_iter()
.filter(|r| r.role == "call" && ids.contains(&r.symbol_id))
.map(|r| (r.line_number, r.via))
.collect();
out.sort();
Ok(out)
}
#[tokio::test]
async fn a_path_call_is_exact_and_a_method_on_an_unknown_receiver_is_by_name() -> anyhow::Result<()>
{
let (db, project) = index_files(
&[(
"src/lib.rs",
"pub fn target() {}\n\
pub struct S;\n\
impl S { pub fn run(&self) {} }\n\
pub fn by_path() { crate::target(); }\n\
pub fn by_scope() { target(); }\n\
pub fn by_method(s: Unknown) { s.run(); }\n",
)],
IndexOptions::default(),
)
.await?;
assert_eq!(
via_of_calls(&db, project, "target").await?,
vec![(4, "exact".into()), (5, "exact".into())]
);
assert_eq!(
via_of_calls(&db, project, "run").await?,
vec![(6, "name".into())]
);
Ok(())
}
#[tokio::test]
async fn a_name_that_several_symbols_share_is_not_exact() -> anyhow::Result<()> {
let (db, project) = index_files(
&[
("a.py", "def go():\n helper()\n"),
("b.py", "def helper():\n return 1\n"),
("c.py", "def helper():\n return 2\n"),
],
IndexOptions::default(),
)
.await?;
let vias = via_of_calls(&db, project, "helper").await?;
assert_eq!(vias.len(), 1, "{vias:?}");
assert_eq!(vias[0].1, "name", "{vias:?}");
Ok(())
}