use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex, OnceLock};
use crate::package_imports::resolve_import_path_with_snapshots;
use crate::package_snapshot::PackageSnapshot;
use crate::ModuleInfo;
struct Remembered {
source: String,
module: Arc<ModuleInfo>,
}
fn memo() -> &'static Mutex<HashMap<PathBuf, Arc<Remembered>>> {
static MEMO: OnceLock<Mutex<HashMap<PathBuf, Arc<Remembered>>>> = OnceLock::new();
MEMO.get_or_init(Mutex::default)
}
pub(crate) fn recall(
path: &Path,
source: &str,
package_snapshots: &[PackageSnapshot],
) -> Option<Arc<ModuleInfo>> {
let remembered = memo()
.lock()
.expect("module load memo poisoned")
.get(path)
.cloned()?;
if remembered.source != source {
return None;
}
let resolutions_hold = remembered.module.imports.iter().all(|import| {
resolve_import_path_with_snapshots(path, &import.raw_path, package_snapshots) == import.path
});
resolutions_hold.then(|| Arc::clone(&remembered.module))
}
pub(crate) fn remember(path: &Path, source: String, module: &Arc<ModuleInfo>) {
memo().lock().expect("module load memo poisoned").insert(
path.to_path_buf(),
Arc::new(Remembered {
source,
module: Arc::clone(module),
}),
);
}
#[cfg(test)]
mod tests {
use std::collections::HashSet;
use crate::build;
#[test]
fn remembered_projection_follows_new_import_targets_and_edits() {
let dir = tempfile::tempdir().unwrap();
let entry = dir.path().join("entry.harn");
let dep = dir.path().join("dep.harn");
std::fs::write(
&entry,
"import { helper } from \"./dep\"\npub fn run() { 1 }\n",
)
.unwrap();
let graph = build(std::slice::from_ref(&entry));
assert_eq!(graph.imported_names_for_file(&entry), None);
std::fs::write(&dep, "pub fn helper() { 1 }\n").unwrap();
let graph = build(std::slice::from_ref(&entry));
assert_eq!(
graph.imported_names_for_file(&entry),
Some(HashSet::from(["helper".to_string()]))
);
std::fs::write(&dep, "pub fn helpex() { 1 }\n").unwrap();
let graph = build(std::slice::from_ref(&entry));
assert_eq!(graph.exported_kind(&dep, "helper"), None);
assert!(graph.exported_kind(&dep, "helpex").is_some());
}
}