Skip to main content

harn_modules/
source_reads.rs

1//! Where module sources come from: disk, the embedded stdlib, or a caller's
2//! unsaved buffers, plus the count of disk reads that editor caching is
3//! measured against.
4
5use std::collections::HashMap;
6use std::path::{Path, PathBuf};
7
8use super::{
9    build_inner, normalize_path, stdlib, stdlib_module_name, PackageContext, ParsedSourceRetention,
10};
11use crate::ModuleGraph;
12
13/// Return the source for a resolved module path.
14///
15/// Real paths are read from disk. `<std>/<module>` virtual paths are backed by
16/// the embedded stdlib source table, so callers can parse resolved stdlib
17/// modules without knowing about the stdlib mirror layout.
18pub fn read_module_source(path: &Path) -> Option<String> {
19    if let Some(stdlib_module) = stdlib_module_name(path) {
20        return stdlib::get_stdlib_source(stdlib_module).map(ToString::to_string);
21    }
22    MODULE_DISK_READS.with(|reads| reads.set(reads.get() + 1));
23    std::fs::read_to_string(path).ok()
24}
25
26thread_local! {
27    static MODULE_DISK_READS: std::cell::Cell<usize> = const { std::cell::Cell::new(0) };
28}
29
30/// How many module sources this thread has read from disk while building
31/// module graphs. Embedded stdlib modules and caller-supplied sources are not
32/// disk reads.
33pub fn module_source_disk_reads() -> usize {
34    MODULE_DISK_READS.with(std::cell::Cell::get)
35}
36
37/// Build a module graph using caller-owned source for one root file.
38///
39/// Imported modules still resolve from their normal filesystem or embedded
40/// stdlib locations. This keeps editor diagnostics aligned with unsaved root
41/// buffers without creating a second module resolver.
42pub fn build_with_source(file: &Path, source: &str) -> ModuleGraph {
43    let file = normalize_path(file);
44    let source_overrides = HashMap::from([(file.clone(), source.to_string())]);
45    build_inner(
46        &[file],
47        ParsedSourceRetention::None,
48        Some(&source_overrides),
49        PackageContext::Project,
50        None,
51    )
52    .graph
53}
54
55/// Build a module graph for one root file using caller-owned source for any
56/// module in `sources`, such as an editor's unsaved buffers. Modules without an
57/// entry resolve from their filesystem or embedded stdlib locations.
58pub fn build_with_sources(file: &Path, sources: &HashMap<PathBuf, String>) -> ModuleGraph {
59    let file = normalize_path(file);
60    let source_overrides: HashMap<PathBuf, String> = sources
61        .iter()
62        .map(|(path, source)| (normalize_path(path), source.clone()))
63        .collect();
64    build_inner(
65        &[file],
66        ParsedSourceRetention::None,
67        Some(&source_overrides),
68        PackageContext::Project,
69        None,
70    )
71    .graph
72}