aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/roots.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-09-16 10:54:24 +0100
committerAleksey Kladov <[email protected]>2018-09-16 11:07:39 +0100
commitb5021411a84822cb3f1e3aeffad9550dd15bdeb6 (patch)
tree9dca564f8e51b298dced01c4ce669c756dce3142 /crates/ra_analysis/src/roots.rs
parentba0bfeee12e19da40b5eabc8d0408639af10e96f (diff)
rename all things
Diffstat (limited to 'crates/ra_analysis/src/roots.rs')
-rw-r--r--crates/ra_analysis/src/roots.rs178
1 files changed, 178 insertions, 0 deletions
diff --git a/crates/ra_analysis/src/roots.rs b/crates/ra_analysis/src/roots.rs
new file mode 100644
index 000000000..1835a9b25
--- /dev/null
+++ b/crates/ra_analysis/src/roots.rs
@@ -0,0 +1,178 @@
1use std::{
2 collections::HashMap,
3 sync::Arc,
4 panic,
5};
6
7use once_cell::sync::OnceCell;
8use rayon::prelude::*;
9use ra_editor::LineIndex;
10use ra_syntax::File;
11
12use {
13 FileId,
14 imp::FileResolverImp,
15 symbol_index::SymbolIndex,
16 descriptors::{ModuleDescriptor, ModuleTreeDescriptor},
17 db::Db,
18};
19
20pub(crate) trait SourceRoot {
21 fn contains(&self, file_id: FileId) -> bool;
22 fn module_tree(&self) -> Arc<ModuleTreeDescriptor>;
23 fn lines(&self, file_id: FileId) -> Arc<LineIndex>;
24 fn syntax(&self, file_id: FileId) -> File;
25 fn symbols(&self, acc: &mut Vec<Arc<SymbolIndex>>);
26}
27
28#[derive(Default, Debug)]
29pub(crate) struct WritableSourceRoot {
30 db: Db,
31}
32
33impl WritableSourceRoot {
34 pub fn apply_changes(
35 &self,
36 changes: &mut dyn Iterator<Item=(FileId, Option<String>)>,
37 file_resolver: Option<FileResolverImp>,
38 ) -> WritableSourceRoot {
39 let resolver_changed = file_resolver.is_some();
40 let mut changed_files = Vec::new();
41 let mut new_state = self.db.state().clone();
42
43 for (file_id, text) in changes {
44 changed_files.push(file_id);
45 match text {
46 Some(text) => {
47 new_state.file_map.insert(file_id, Arc::new(text));
48 },
49 None => {
50 new_state.file_map.remove(&file_id);
51 }
52 }
53 }
54 if let Some(file_resolver) = file_resolver {
55 new_state.file_resolver = file_resolver
56 }
57 WritableSourceRoot {
58 db: self.db.with_changes(new_state, &changed_files, resolver_changed)
59 }
60 }
61}
62
63impl SourceRoot for WritableSourceRoot {
64 fn module_tree(&self) -> Arc<ModuleTreeDescriptor> {
65 self.db.make_query(::module_map::module_tree)
66 }
67
68 fn contains(&self, file_id: FileId) -> bool {
69 self.db.state().file_map.contains_key(&file_id)
70 }
71 fn lines(&self, file_id: FileId) -> Arc<LineIndex> {
72 self.db.make_query(|ctx| ::queries::file_lines(ctx, file_id))
73 }
74 fn syntax(&self, file_id: FileId) -> File {
75 self.db.make_query(|ctx| ::queries::file_syntax(ctx, file_id))
76 }
77 fn symbols<'a>(&'a self, acc: &mut Vec<Arc<SymbolIndex>>) {
78 self.db.make_query(|ctx| {
79 let file_set = ::queries::file_set(ctx);
80 let syms = file_set.0.iter()
81 .map(|file_id| ::queries::file_symbols(ctx, *file_id));
82 acc.extend(syms);
83 });
84 }
85}
86
87#[derive(Debug)]
88struct FileData {
89 text: String,
90 lines: OnceCell<Arc<LineIndex>>,
91 syntax: OnceCell<File>,
92}
93
94impl FileData {
95 fn new(text: String) -> FileData {
96 FileData {
97 text,
98 syntax: OnceCell::new(),
99 lines: OnceCell::new(),
100 }
101 }
102 fn lines(&self) -> &Arc<LineIndex> {
103 self.lines.get_or_init(|| Arc::new(LineIndex::new(&self.text)))
104 }
105 fn syntax(&self) -> &File {
106 let text = &self.text;
107 let syntax = &self.syntax;
108 match panic::catch_unwind(panic::AssertUnwindSafe(|| syntax.get_or_init(|| File::parse(text)))) {
109 Ok(file) => file,
110 Err(err) => {
111 error!("Parser paniced on:\n------\n{}\n------\n", text);
112 panic::resume_unwind(err)
113 }
114 }
115 }
116}
117
118#[derive(Debug)]
119pub(crate) struct ReadonlySourceRoot {
120 symbol_index: Arc<SymbolIndex>,
121 file_map: HashMap<FileId, FileData>,
122 module_tree: Arc<ModuleTreeDescriptor>,
123}
124
125impl ReadonlySourceRoot {
126 pub(crate) fn new(files: Vec<(FileId, String)>, file_resolver: FileResolverImp) -> ReadonlySourceRoot {
127 let modules = files.par_iter()
128 .map(|(file_id, text)| {
129 let syntax = File::parse(text);
130 let mod_descr = ModuleDescriptor::new(syntax.ast());
131 (*file_id, syntax, mod_descr)
132 })
133 .collect::<Vec<_>>();
134 let module_tree = ModuleTreeDescriptor::new(
135 modules.iter().map(|it| (it.0, &it.2)),
136 &file_resolver,
137 );
138
139 let symbol_index = SymbolIndex::for_files(
140 modules.par_iter().map(|it| (it.0, it.1.clone()))
141 );
142 let file_map: HashMap<FileId, FileData> = files
143 .into_iter()
144 .map(|(id, text)| (id, FileData::new(text)))
145 .collect();
146
147 ReadonlySourceRoot {
148 symbol_index: Arc::new(symbol_index),
149 file_map,
150 module_tree: Arc::new(module_tree),
151 }
152 }
153
154 fn data(&self, file_id: FileId) -> &FileData {
155 match self.file_map.get(&file_id) {
156 Some(data) => data,
157 None => panic!("unknown file: {:?}", file_id),
158 }
159 }
160}
161
162impl SourceRoot for ReadonlySourceRoot {
163 fn module_tree(&self) -> Arc<ModuleTreeDescriptor> {
164 Arc::clone(&self.module_tree)
165 }
166 fn contains(&self, file_id: FileId) -> bool {
167 self.file_map.contains_key(&file_id)
168 }
169 fn lines(&self, file_id: FileId) -> Arc<LineIndex> {
170 Arc::clone(self.data(file_id).lines())
171 }
172 fn syntax(&self, file_id: FileId) -> File {
173 self.data(file_id).syntax().clone()
174 }
175 fn symbols(&self, acc: &mut Vec<Arc<SymbolIndex>>) {
176 acc.push(Arc::clone(&self.symbol_index))
177 }
178}