use crate::{ModuleId, SourceId};
use std::{
collections::{BTreeSet, HashMap},
path::PathBuf,
sync::RwLock,
};
#[derive(Debug, Default)]
pub struct SourceEngine {
next_source_id: RwLock<u32>,
path_to_source_map: RwLock<HashMap<PathBuf, SourceId>>,
source_to_path_map: RwLock<HashMap<SourceId, PathBuf>>,
next_module_id: RwLock<u16>,
path_to_module_map: RwLock<HashMap<PathBuf, ModuleId>>,
module_to_sources_map: RwLock<HashMap<ModuleId, BTreeSet<SourceId>>>,
}
impl Clone for SourceEngine {
fn clone(&self) -> Self {
SourceEngine {
next_source_id: RwLock::new(*self.next_source_id.read().unwrap()),
path_to_source_map: RwLock::new(self.path_to_source_map.read().unwrap().clone()),
source_to_path_map: RwLock::new(self.source_to_path_map.read().unwrap().clone()),
next_module_id: RwLock::new(*self.next_module_id.read().unwrap()),
path_to_module_map: RwLock::new(self.path_to_module_map.read().unwrap().clone()),
module_to_sources_map: RwLock::new(self.module_to_sources_map.read().unwrap().clone()),
}
}
}
impl SourceEngine {
pub fn get_source_id(&self, path: &PathBuf) -> SourceId {
{
let source_map = self.path_to_source_map.read().unwrap();
if source_map.contains_key(path) {
return source_map.get(path).cloned().unwrap();
}
}
let manifest_path = sway_utils::find_parent_manifest_dir(path).unwrap_or(path.clone());
let module_id = {
let mut module_map = self.path_to_module_map.write().unwrap();
*module_map.entry(manifest_path.clone()).or_insert_with(|| {
let mut next_id = self.next_module_id.write().unwrap();
*next_id += 1;
ModuleId::new(*next_id)
})
};
let source_id = SourceId::new(module_id.id, *self.next_source_id.read().unwrap());
{
let mut next_id = self.next_source_id.write().unwrap();
*next_id += 1;
let mut source_map = self.path_to_source_map.write().unwrap();
source_map.insert(path.clone(), source_id);
let mut path_map = self.source_to_path_map.write().unwrap();
path_map.insert(source_id, path.clone());
}
let mut module_map = self.module_to_sources_map.write().unwrap();
module_map.entry(module_id).or_default().insert(source_id);
source_id
}
pub fn get_path(&self, source_id: &SourceId) -> PathBuf {
self.source_to_path_map
.read()
.unwrap()
.get(source_id)
.unwrap()
.clone()
}
pub fn get_module_id(&self, path: &PathBuf) -> Option<ModuleId> {
self.path_to_module_map.read().unwrap().get(path).cloned()
}
pub fn get_file_name(&self, source_id: &SourceId) -> Option<String> {
self.get_path(source_id)
.as_path()
.file_name()
.map(|file_name| file_name.to_string_lossy())
.map(|file_name| file_name.to_string())
}
}