harn_modules/
source_reads.rs1use 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
13pub fn read_module_source(path: &Path) -> Option<String> {
19 read_module_source_checked(path).ok().flatten()
20}
21
22pub(crate) fn read_module_source_checked(path: &Path) -> Result<Option<String>, String> {
25 if let Some(stdlib_module) = stdlib_module_name(path) {
26 return Ok(stdlib::get_stdlib_source(stdlib_module).map(ToString::to_string));
27 }
28 MODULE_DISK_READS.with(|reads| reads.set(reads.get() + 1));
29 match std::fs::read_to_string(path) {
30 Ok(source) => Ok(Some(source)),
31 Err(error) if error.kind() == std::io::ErrorKind::PermissionDenied => Err(format!(
34 "read denied: {} (outside confined roots)",
35 path.display()
36 )),
37 Err(_) => Ok(None),
38 }
39}
40
41thread_local! {
42 static MODULE_DISK_READS: std::cell::Cell<usize> = const { std::cell::Cell::new(0) };
43}
44
45pub fn module_source_disk_reads() -> usize {
49 MODULE_DISK_READS.with(std::cell::Cell::get)
50}
51
52pub fn build_with_source(file: &Path, source: &str) -> ModuleGraph {
58 let file = normalize_path(file);
59 let source_overrides = HashMap::from([(file.clone(), source.to_string())]);
60 build_inner(
61 &[file],
62 ParsedSourceRetention::None,
63 Some(&source_overrides),
64 PackageContext::Project,
65 None,
66 )
67 .graph
68}
69
70pub fn build_with_sources(file: &Path, sources: &HashMap<PathBuf, String>) -> ModuleGraph {
74 let file = normalize_path(file);
75 let source_overrides: HashMap<PathBuf, String> = sources
76 .iter()
77 .map(|(path, source)| (normalize_path(path), source.clone()))
78 .collect();
79 build_inner(
80 &[file],
81 ParsedSourceRetention::None,
82 Some(&source_overrides),
83 PackageContext::Project,
84 None,
85 )
86 .graph
87}