#![cfg(feature = "code-intel-js")]
use std::fs;
use basemind::config::ConfigV1;
use basemind::path::RelPath;
use basemind::scanner::{ScanSource, scan, scan_paths};
use basemind::store::{Store, VIEW_WORKING};
fn count_def_start(src: &str) -> u32 {
(src.find("const count").unwrap() + "const ".len()) as u32
}
#[test]
fn scan_paths_refreshes_resolved_edges_after_edit() {
basemind::store::init_isolated_cache();
let dir = tempfile::tempdir().unwrap();
let root = dir.path();
let before = "const count = 1;\nfunction f() {\n return count + count;\n}\n";
let app_abs = root.join("app.js");
fs::write(&app_abs, before).unwrap();
let mut store = Store::open(root, VIEW_WORKING).unwrap();
let cfg = ConfigV1::with_defaults();
scan(
root,
&mut store,
&cfg,
ScanSource::WorkingTree,
basemind::scanner::EmbedMode::Inline,
)
.unwrap();
if store.lookup("app.js").is_none() {
eprintln!("javascript grammar unavailable in this environment — skipping resolution assertions");
return;
}
let app = RelPath::from("app.js");
let def_start = count_def_start(before);
let baseline = basemind::query::resolved_references(&store, &app, def_start);
assert_eq!(baseline.len(), 2, "full scan must resolve both uses; got {baseline:?}");
let after = "const count = 1;\nfunction f() {\n return count + count + count;\n}\n";
fs::write(&app_abs, after).unwrap();
scan_paths(root, &mut store, &cfg, &[app_abs], basemind::scanner::EmbedMode::Inline).unwrap();
let mut uses = basemind::query::resolved_references(&store, &app, def_start);
uses.sort_by_key(|(_, s)| *s);
assert_eq!(
uses.len(),
3,
"scan_paths must re-run resolution and reflect the added use; got {uses:?}"
);
assert!(
uses.iter().all(|(p, _)| p.as_str() == Some("app.js")),
"resolved uses must stay in app.js"
);
let first_use = (after.find("return count").unwrap() + "return ".len()) as u32;
assert_eq!(
basemind::query::definition_of(&store, &app, first_use),
Some((app.clone(), def_start)),
"goto-definition of a use must still point at the const after the incremental re-scan"
);
}
#[test]
fn scan_paths_purges_resolved_edges_for_removed_file() {
basemind::store::init_isolated_cache();
let dir = tempfile::tempdir().unwrap();
let root = dir.path();
let src = "const count = 1;\nfunction f() {\n return count + count;\n}\n";
let keep_abs = root.join("keep.js");
let gone_abs = root.join("gone.js");
fs::write(&keep_abs, src).unwrap();
fs::write(&gone_abs, src).unwrap();
let mut store = Store::open(root, VIEW_WORKING).unwrap();
let cfg = ConfigV1::with_defaults();
scan(
root,
&mut store,
&cfg,
ScanSource::WorkingTree,
basemind::scanner::EmbedMode::Inline,
)
.unwrap();
if store.lookup("gone.js").is_none() || store.lookup("keep.js").is_none() {
eprintln!("javascript grammar unavailable in this environment — skipping resolution assertions");
return;
}
let keep = RelPath::from("keep.js");
let gone = RelPath::from("gone.js");
let def_start = count_def_start(src);
assert_eq!(basemind::query::resolved_references(&store, &gone, def_start).len(), 2);
assert_eq!(basemind::query::resolved_references(&store, &keep, def_start).len(), 2);
fs::remove_file(&gone_abs).unwrap();
scan_paths(
root,
&mut store,
&cfg,
&[gone_abs],
basemind::scanner::EmbedMode::Inline,
)
.unwrap();
assert!(
basemind::query::resolved_references(&store, &gone, def_start).is_empty(),
"removed file's resolved edges must be purged by scan_paths"
);
assert_eq!(
basemind::query::resolved_references(&store, &keep, def_start).len(),
2,
"surviving file's resolved edges must remain intact"
);
}