sway_types/
source_engine.rs1use crate::{ProgramId, SourceId};
2use parking_lot::RwLock;
3use std::{
4 collections::{BTreeSet, HashMap},
5 path::PathBuf,
6};
7
8#[derive(Debug, Default)]
18pub struct SourceEngine {
19 next_source_id: RwLock<u32>,
20 path_to_source_map: RwLock<HashMap<PathBuf, SourceId>>,
21 source_to_path_map: RwLock<HashMap<SourceId, PathBuf>>,
22 next_program_id: RwLock<u16>,
23 manifest_path_to_program_map: RwLock<HashMap<PathBuf, ProgramId>>,
24 module_to_sources_map: RwLock<HashMap<ProgramId, BTreeSet<SourceId>>>,
25}
26
27impl Clone for SourceEngine {
28 fn clone(&self) -> Self {
29 SourceEngine {
30 next_source_id: RwLock::new(*self.next_source_id.read()),
31 path_to_source_map: RwLock::new(self.path_to_source_map.read().clone()),
32 source_to_path_map: RwLock::new(self.source_to_path_map.read().clone()),
33 next_program_id: RwLock::new(*self.next_program_id.read()),
34 manifest_path_to_program_map: RwLock::new(
35 self.manifest_path_to_program_map.read().clone(),
36 ),
37 module_to_sources_map: RwLock::new(self.module_to_sources_map.read().clone()),
38 }
39 }
40}
41
42impl SourceEngine {
43 const AUTOGENERATED_PATH: &'static str = "<autogenerated>";
44
45 pub fn is_span_in_autogenerated(&self, span: &crate::Span) -> Option<bool> {
46 span.source_id().map(|s| self.is_source_id_autogenerated(s))
47 }
48
49 pub fn is_source_id_autogenerated(&self, source_id: &SourceId) -> bool {
50 self.get_path(source_id).starts_with("<autogenerated>")
51 }
52
53 pub fn get_source_id(&self, path: &PathBuf) -> SourceId {
57 {
58 let source_map = self.path_to_source_map.read();
59 if source_map.contains_key(path) {
60 return source_map.get(path).copied().unwrap();
61 }
62 }
63
64 let program_id = self.get_or_create_program_id_from_manifest_path(path);
65 self.get_source_id_with_program_id(path, program_id)
66 }
67
68 pub fn get_source_id_with_program_id(&self, path: &PathBuf, program_id: ProgramId) -> SourceId {
69 {
70 let source_map = self.path_to_source_map.read();
71 if source_map.contains_key(path) {
72 return source_map.get(path).copied().unwrap();
73 }
74 }
75
76 let source_id = SourceId::new(program_id.0, *self.next_source_id.read());
77 {
78 let mut next_id = self.next_source_id.write();
79 *next_id += 1;
80
81 let mut source_map = self.path_to_source_map.write();
82 source_map.insert(path.clone(), source_id);
83
84 let mut path_map = self.source_to_path_map.write();
85 path_map.insert(source_id, path.clone());
86 }
87
88 let mut module_map = self.module_to_sources_map.write();
89 module_map.entry(program_id).or_default().insert(source_id);
90
91 source_id
92 }
93
94 pub fn get_autogenerated_source_id(&self, program_id: ProgramId) -> SourceId {
95 self.get_source_id_with_program_id(&Self::AUTOGENERATED_PATH.into(), program_id)
96 }
97
98 pub fn get_path(&self, source_id: &SourceId) -> PathBuf {
100 self.source_to_path_map
101 .read()
102 .get(source_id)
103 .unwrap()
104 .clone()
105 }
106
107 pub fn get_program_id_from_manifest_path(&self, path: &PathBuf) -> Option<ProgramId> {
109 let manifest_path = sway_utils::find_parent_manifest_dir(path).unwrap_or(path.clone());
110 self.manifest_path_to_program_map
111 .read()
112 .get(&manifest_path)
113 .copied()
114 }
115
116 pub fn get_or_create_program_id_from_manifest_path(&self, path: &PathBuf) -> ProgramId {
117 let manifest_path = sway_utils::find_parent_manifest_dir(path).unwrap_or(path.clone());
118 let mut module_map = self.manifest_path_to_program_map.write();
119 *module_map.entry(manifest_path.clone()).or_insert_with(|| {
120 let mut next_id = self.next_program_id.write();
121 *next_id += 1;
122 ProgramId::new(*next_id)
123 })
124 }
125
126 pub fn get_manifest_path_from_program_id(&self, program_id: &ProgramId) -> Option<PathBuf> {
128 let path_to_module_map = self.manifest_path_to_program_map.read();
129 path_to_module_map
130 .iter()
131 .find(|(_, &id)| id == *program_id)
132 .map(|(path, _)| path.clone())
133 }
134
135 pub fn get_file_name(&self, source_id: &SourceId) -> Option<String> {
137 self.get_path(source_id)
138 .as_path()
139 .file_name()
140 .map(|file_name| file_name.to_string_lossy())
141 .map(|file_name| file_name.to_string())
142 }
143
144 pub fn all_files(&self) -> Vec<PathBuf> {
145 let s = self.source_to_path_map.read();
146 let mut v = s.values().cloned().collect::<Vec<_>>();
147 v.sort();
148 v
149 }
150
151 pub fn get_source_ids_from_program_id(
152 &self,
153 program_id: ProgramId,
154 ) -> Option<BTreeSet<SourceId>> {
155 let s = self.module_to_sources_map.read();
156 s.get(&program_id).cloned()
157 }
158}