aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/imp.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api/src/imp.rs')
-rw-r--r--crates/ra_ide_api/src/imp.rs263
1 files changed, 0 insertions, 263 deletions
diff --git a/crates/ra_ide_api/src/imp.rs b/crates/ra_ide_api/src/imp.rs
deleted file mode 100644
index b139efabf..000000000
--- a/crates/ra_ide_api/src/imp.rs
+++ /dev/null
@@ -1,263 +0,0 @@
1use std::{
2 sync::Arc,
3 time,
4};
5
6use hir::{
7 self, Problem, source_binder
8};
9use ra_db::{
10 SourceDatabase, SourceRoot, SourceRootId,
11 salsa::{Database, SweepStrategy},
12};
13use ra_ide_api_light::{self, LocalEdit, Severity};
14use ra_syntax::{
15 algo::find_node_at_offset, ast::{self, NameOwner}, AstNode,
16 SourceFile,
17 TextRange,
18};
19
20use crate::{
21 AnalysisChange,
22 CrateId, db, Diagnostic, FileId, FilePosition, FileSystemEdit,
23 Query, RootChange, SourceChange, SourceFileEdit,
24 symbol_index::{FileSymbol, SymbolsDatabase},
25 status::syntax_tree_stats
26};
27
28const GC_COOLDOWN: time::Duration = time::Duration::from_millis(100);
29
30impl db::RootDatabase {
31 pub(crate) fn apply_change(&mut self, change: AnalysisChange) {
32 log::info!("apply_change {:?}", change);
33 if !change.new_roots.is_empty() {
34 let mut local_roots = Vec::clone(&self.local_roots());
35 for (root_id, is_local) in change.new_roots {
36 self.set_source_root(root_id, Default::default());
37 if is_local {
38 local_roots.push(root_id);
39 }
40 }
41 self.set_local_roots(Arc::new(local_roots));
42 }
43
44 for (root_id, root_change) in change.roots_changed {
45 self.apply_root_change(root_id, root_change);
46 }
47 for (file_id, text) in change.files_changed {
48 self.set_file_text(file_id, text)
49 }
50 if !change.libraries_added.is_empty() {
51 let mut libraries = Vec::clone(&self.library_roots());
52 for library in change.libraries_added {
53 libraries.push(library.root_id);
54 self.set_source_root(library.root_id, Default::default());
55 self.set_constant_library_symbols(library.root_id, Arc::new(library.symbol_index));
56 self.apply_root_change(library.root_id, library.root_change);
57 }
58 self.set_library_roots(Arc::new(libraries));
59 }
60 if let Some(crate_graph) = change.crate_graph {
61 self.set_crate_graph(Arc::new(crate_graph))
62 }
63 }
64
65 fn apply_root_change(&mut self, root_id: SourceRootId, root_change: RootChange) {
66 let mut source_root = SourceRoot::clone(&self.source_root(root_id));
67 for add_file in root_change.added {
68 self.set_file_text(add_file.file_id, add_file.text);
69 self.set_file_relative_path(add_file.file_id, add_file.path.clone());
70 self.set_file_source_root(add_file.file_id, root_id);
71 source_root.files.insert(add_file.path, add_file.file_id);
72 }
73 for remove_file in root_change.removed {
74 self.set_file_text(remove_file.file_id, Default::default());
75 source_root.files.remove(&remove_file.path);
76 }
77 self.set_source_root(root_id, Arc::new(source_root));
78 }
79
80 pub(crate) fn maybe_collect_garbage(&mut self) {
81 if self.last_gc_check.elapsed() > GC_COOLDOWN {
82 self.last_gc_check = time::Instant::now();
83 let retained_trees = syntax_tree_stats(self).retained;
84 if retained_trees > 100 {
85 log::info!(
86 "automatic garbadge collection, {} retained trees",
87 retained_trees
88 );
89 self.collect_garbage();
90 }
91 }
92 }
93
94 pub(crate) fn collect_garbage(&mut self) {
95 self.last_gc = time::Instant::now();
96
97 let sweep = SweepStrategy::default()
98 .discard_values()
99 .sweep_all_revisions();
100
101 self.query(ra_db::ParseQuery).sweep(sweep);
102
103 self.query(hir::db::HirParseQuery).sweep(sweep);
104 self.query(hir::db::FileItemsQuery).sweep(sweep);
105 self.query(hir::db::FileItemQuery).sweep(sweep);
106
107 self.query(hir::db::LowerModuleQuery).sweep(sweep);
108 self.query(hir::db::LowerModuleSourceMapQuery).sweep(sweep);
109 self.query(hir::db::BodySyntaxMappingQuery).sweep(sweep);
110 }
111}
112
113impl db::RootDatabase {
114 /// Returns `Vec` for the same reason as `parent_module`
115 pub(crate) fn crate_for(&self, file_id: FileId) -> Vec<CrateId> {
116 let module = match source_binder::module_from_file_id(self, file_id) {
117 Some(it) => it,
118 None => return Vec::new(),
119 };
120 let krate = match module.krate(self) {
121 Some(it) => it,
122 None => return Vec::new(),
123 };
124 vec![krate.crate_id()]
125 }
126
127 pub(crate) fn find_all_refs(&self, position: FilePosition) -> Vec<(FileId, TextRange)> {
128 let file = self.parse(position.file_id);
129 // Find the binding associated with the offset
130 let (binding, descr) = match find_binding(self, &file, position) {
131 None => return Vec::new(),
132 Some(it) => it,
133 };
134
135 let mut ret = binding
136 .name()
137 .into_iter()
138 .map(|name| (position.file_id, name.syntax().range()))
139 .collect::<Vec<_>>();
140 ret.extend(
141 descr
142 .scopes(self)
143 .find_all_refs(binding)
144 .into_iter()
145 .map(|ref_desc| (position.file_id, ref_desc.range)),
146 );
147
148 return ret;
149
150 fn find_binding<'a>(
151 db: &db::RootDatabase,
152 source_file: &'a SourceFile,
153 position: FilePosition,
154 ) -> Option<(&'a ast::BindPat, hir::Function)> {
155 let syntax = source_file.syntax();
156 if let Some(binding) = find_node_at_offset::<ast::BindPat>(syntax, position.offset) {
157 let descr = source_binder::function_from_child_node(
158 db,
159 position.file_id,
160 binding.syntax(),
161 )?;
162 return Some((binding, descr));
163 };
164 let name_ref = find_node_at_offset::<ast::NameRef>(syntax, position.offset)?;
165 let descr =
166 source_binder::function_from_child_node(db, position.file_id, name_ref.syntax())?;
167 let scope = descr.scopes(db);
168 let resolved = scope.resolve_local_name(name_ref)?;
169 let resolved = resolved.ptr().to_node(source_file);
170 let binding = find_node_at_offset::<ast::BindPat>(syntax, resolved.range().end())?;
171 Some((binding, descr))
172 }
173 }
174
175 pub(crate) fn diagnostics(&self, file_id: FileId) -> Vec<Diagnostic> {
176 let syntax = self.parse(file_id);
177
178 let mut res = ra_ide_api_light::diagnostics(&syntax)
179 .into_iter()
180 .map(|d| Diagnostic {
181 range: d.range,
182 message: d.msg,
183 severity: d.severity,
184 fix: d.fix.map(|fix| SourceChange::from_local_edit(file_id, fix)),
185 })
186 .collect::<Vec<_>>();
187 if let Some(m) = source_binder::module_from_file_id(self, file_id) {
188 for (name_node, problem) in m.problems(self) {
189 let source_root = self.file_source_root(file_id);
190 let diag = match problem {
191 Problem::UnresolvedModule { candidate } => {
192 let create_file = FileSystemEdit::CreateFile {
193 source_root,
194 path: candidate.clone(),
195 };
196 let fix = SourceChange {
197 label: "create module".to_string(),
198 source_file_edits: Vec::new(),
199 file_system_edits: vec![create_file],
200 cursor_position: None,
201 };
202 Diagnostic {
203 range: name_node.range(),
204 message: "unresolved module".to_string(),
205 severity: Severity::Error,
206 fix: Some(fix),
207 }
208 }
209 Problem::NotDirOwner { move_to, candidate } => {
210 let move_file = FileSystemEdit::MoveFile {
211 src: file_id,
212 dst_source_root: source_root,
213 dst_path: move_to.clone(),
214 };
215 let create_file = FileSystemEdit::CreateFile {
216 source_root,
217 path: move_to.join(candidate),
218 };
219 let fix = SourceChange {
220 label: "move file and create module".to_string(),
221 source_file_edits: Vec::new(),
222 file_system_edits: vec![move_file, create_file],
223 cursor_position: None,
224 };
225 Diagnostic {
226 range: name_node.range(),
227 message: "can't declare module at this location".to_string(),
228 severity: Severity::Error,
229 fix: Some(fix),
230 }
231 }
232 };
233 res.push(diag)
234 }
235 };
236 res
237 }
238
239 pub(crate) fn index_resolve(&self, name_ref: &ast::NameRef) -> Vec<FileSymbol> {
240 let name = name_ref.text();
241 let mut query = Query::new(name.to_string());
242 query.exact();
243 query.limit(4);
244 crate::symbol_index::world_symbols(self, query)
245 }
246}
247
248impl SourceChange {
249 pub(crate) fn from_local_edit(file_id: FileId, edit: LocalEdit) -> SourceChange {
250 let file_edit = SourceFileEdit {
251 file_id,
252 edit: edit.edit,
253 };
254 SourceChange {
255 label: edit.label,
256 source_file_edits: vec![file_edit],
257 file_system_edits: vec![],
258 cursor_position: edit
259 .cursor_position
260 .map(|offset| FilePosition { offset, file_id }),
261 }
262 }
263}