Skip to main content

lisette_semantics/
loader.rs

1use rustc_hash::FxHashMap as HashMap;
2
3/// Source content plus a cwd-relative display path for diagnostics.
4/// `display_path` matches `name` for loaders that have no notion of cwd
5/// (test/overlay loaders); the CLI's filesystem loader sets it to the path
6/// relative to the process cwd.
7#[derive(Debug, Clone)]
8pub struct FileContent {
9    pub source: String,
10    pub display_path: String,
11}
12
13impl FileContent {
14    pub fn new(source: impl Into<String>, display_path: impl Into<String>) -> Self {
15        Self {
16            source: source.into(),
17            display_path: display_path.into(),
18        }
19    }
20}
21
22pub type Files = HashMap<String, FileContent>;
23
24pub trait Loader {
25    /// Scans a folder and returns all `.lis` files keyed by bare filename.
26    fn scan_folder(&self, folder: &str) -> Files;
27}
28
29/// In-memory `Loader` keyed by folder. Use for tests, benches, the wasm
30/// playground, and anywhere the source content does not live on disk.
31#[derive(Debug, Clone, Default)]
32pub struct MemoryLoader {
33    folders: HashMap<String, Files>,
34}
35
36impl MemoryLoader {
37    pub fn new() -> Self {
38        Self::default()
39    }
40
41    /// Insert a file; the diagnostic display path is set to `filename`.
42    pub fn add_file(&mut self, folder: &str, filename: &str, content: &str) {
43        self.add_file_with_display(folder, filename, filename, content);
44    }
45
46    /// Insert a file with an explicit diagnostic display path.
47    pub fn add_file_with_display(
48        &mut self,
49        folder: &str,
50        filename: &str,
51        display_path: &str,
52        content: &str,
53    ) {
54        self.folders.entry(folder.to_string()).or_default().insert(
55            filename.to_string(),
56            FileContent::new(content.to_string(), display_path.to_string()),
57        );
58    }
59
60    /// All registered folder names.
61    pub fn folders(&self) -> Vec<String> {
62        self.folders.keys().cloned().collect()
63    }
64}
65
66impl Loader for MemoryLoader {
67    fn scan_folder(&self, folder: &str) -> Files {
68        self.folders.get(folder).cloned().unwrap_or_default()
69    }
70}