#![cfg(feature = "code-intel-stack")]
use std::fs;
use basemind::config::ConfigV1;
use basemind::path::RelPath;
use basemind::scanner::{ScanSource, scan};
use basemind::store::{Store, VIEW_WORKING};
fn scan_repo(files: &[(&str, &str)]) -> (tempfile::TempDir, Store) {
basemind::store::init_isolated_cache();
let dir = tempfile::tempdir().unwrap();
let root = dir.path();
for (name, src) in files {
let path = root.join(name);
if let Some(parent) = path.parent() {
fs::create_dir_all(parent).unwrap();
}
fs::write(path, 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();
(dir, store)
}
#[test]
fn python_resolves_cross_file_function_and_class_on_direct_import() {
let lib = "def foo():\n return 1\n\n\nclass Bar:\n pass\n";
let main = "from lib import foo, Bar\nfoo()\nBar()\n";
let (_d, store) = scan_repo(&[("lib.py", lib), ("main.py", main)]);
if store.lookup("lib.py").is_none() {
eprintln!("python grammar unavailable — skipping");
return;
}
let lib_rel = RelPath::from("lib.py");
let foo_def = (lib.find("def foo").unwrap() + "def ".len()) as u32;
let bar_def = (lib.find("class Bar").unwrap() + "class ".len()) as u32;
let foo_uses = basemind::query::resolved_references(&store, &lib_rel, foo_def);
assert!(
foo_uses.iter().any(|(p, _)| p.as_str() == Some("main.py")),
"the Python function `foo` must resolve cross-file to main.py; got {foo_uses:?}"
);
let bar_uses = basemind::query::resolved_references(&store, &lib_rel, bar_def);
assert!(
bar_uses.iter().any(|(p, _)| p.as_str() == Some("main.py")),
"the Python class `Bar` must resolve cross-file to main.py; got {bar_uses:?}"
);
}
#[test]
fn python_resolves_cross_file_through_package_reexport() {
let query = "class QuerySet:\n def all(self):\n return self\n";
let init = "from pkg.query import QuerySet\n";
let app = "from pkg import QuerySet\n\n\ndef use():\n return QuerySet()\n";
let (_d, store) = scan_repo(&[("pkg/query.py", query), ("pkg/__init__.py", init), ("app.py", app)]);
if store.lookup("pkg/query.py").is_none() {
eprintln!("python grammar unavailable — skipping");
return;
}
let query_rel = RelPath::from("pkg/query.py");
let qs_def = (query.find("class QuerySet").unwrap() + "class ".len()) as u32;
let uses = basemind::query::resolved_references(&store, &query_rel, qs_def);
assert!(
uses.iter().any(|(p, _)| p.as_str() == Some("app.py")),
"QuerySet must resolve to the package-importing caller app.py via the __init__ re-export; got {uses:?}"
);
}
#[test]
fn java_resolves_cross_file_class_via_import() {
let lib = "package app;\npublic class Lib {\n public static int greet() { return 1; }\n}\n";
let main = "package other;\nimport app.Lib;\npublic class Main {\n int run() { return Lib.greet(); }\n}\n";
let (_d, store) = scan_repo(&[("app/Lib.java", lib), ("other/Main.java", main)]);
if store.lookup("app/Lib.java").is_none() {
eprintln!("java grammar unavailable — skipping");
return;
}
let lib_rel = RelPath::from("app/Lib.java");
let class_def = (lib.find("class Lib").unwrap() + "class ".len()) as u32;
let uses = basemind::query::resolved_references(&store, &lib_rel, class_def);
assert!(
uses.iter().any(|(p, _)| p.as_str() == Some("other/Main.java")),
"the Java class `Lib` must resolve cross-file to the importing Main.java; got {uses:?}"
);
}