diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_analysis/Cargo.toml | 4 | ||||
-rw-r--r-- | crates/ra_analysis/src/db.rs | 40 | ||||
-rw-r--r-- | crates/ra_analysis/src/descriptors.rs | 5 | ||||
-rw-r--r-- | crates/ra_analysis/src/imp.rs | 108 | ||||
-rw-r--r-- | crates/ra_analysis/src/job.rs | 53 | ||||
-rw-r--r-- | crates/ra_analysis/src/lib.rs | 76 | ||||
-rw-r--r-- | crates/ra_analysis/src/module_map.rs | 24 | ||||
-rw-r--r-- | crates/ra_analysis/src/roots.rs | 36 | ||||
-rw-r--r-- | crates/ra_analysis/src/symbol_index.rs | 14 | ||||
-rw-r--r-- | crates/ra_analysis/tests/tests.rs | 65 | ||||
-rw-r--r-- | crates/ra_editor/src/scope/fn_scope.rs | 1 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/caps.rs | 8 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/handlers.rs | 140 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/mod.rs | 41 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/path_map.rs | 4 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/project_model.rs | 4 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/req.rs | 2 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/thread_watcher.rs | 5 |
18 files changed, 369 insertions, 261 deletions
diff --git a/crates/ra_analysis/Cargo.toml b/crates/ra_analysis/Cargo.toml index 17b04182f..f5e742159 100644 --- a/crates/ra_analysis/Cargo.toml +++ b/crates/ra_analysis/Cargo.toml | |||
@@ -7,15 +7,13 @@ authors = ["Aleksey Kladov <[email protected]>"] | |||
7 | [dependencies] | 7 | [dependencies] |
8 | relative-path = "0.3.7" | 8 | relative-path = "0.3.7" |
9 | log = "0.4.2" | 9 | log = "0.4.2" |
10 | crossbeam-channel = "0.2.4" | ||
11 | parking_lot = "0.6.3" | 10 | parking_lot = "0.6.3" |
12 | once_cell = "0.1.5" | 11 | once_cell = "0.1.5" |
13 | rayon = "1.0.2" | 12 | rayon = "1.0.2" |
14 | fst = "0.3.1" | 13 | fst = "0.3.1" |
15 | im = "12.0.0" | ||
16 | ra_syntax = { path = "../ra_syntax" } | 14 | ra_syntax = { path = "../ra_syntax" } |
17 | ra_editor = { path = "../ra_editor" } | 15 | ra_editor = { path = "../ra_editor" } |
18 | salsa = "0.5.0" | 16 | salsa = "0.6.0" |
19 | rustc-hash = "1.0" | 17 | rustc-hash = "1.0" |
20 | 18 | ||
21 | [dev-dependencies] | 19 | [dev-dependencies] |
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs index 99d40a269..956cbe162 100644 --- a/crates/ra_analysis/src/db.rs +++ b/crates/ra_analysis/src/db.rs | |||
@@ -1,22 +1,25 @@ | |||
1 | use crate::{ | 1 | use std::{ |
2 | module_map::{ModuleDescriptorQuery, ModuleTreeQuery, ModulesDatabase}, | 2 | fmt, |
3 | symbol_index::SymbolIndex, | 3 | hash::{Hash, Hasher}, |
4 | FileId, FileResolverImp, | 4 | sync::Arc, |
5 | }; | 5 | }; |
6 | |||
6 | use ra_editor::LineIndex; | 7 | use ra_editor::LineIndex; |
7 | use ra_syntax::File; | 8 | use ra_syntax::File; |
8 | use rustc_hash::FxHashSet; | 9 | use rustc_hash::FxHashSet; |
9 | use salsa; | 10 | use salsa; |
10 | 11 | ||
11 | use std::{ | 12 | use crate::{ |
12 | fmt, | 13 | db, |
13 | hash::{Hash, Hasher}, | 14 | Cancelable, Canceled, |
14 | sync::Arc, | 15 | module_map::{ModuleDescriptorQuery, ModuleTreeQuery, ModulesDatabase}, |
16 | symbol_index::SymbolIndex, | ||
17 | FileId, FileResolverImp, | ||
15 | }; | 18 | }; |
16 | 19 | ||
17 | #[derive(Default)] | 20 | #[derive(Default)] |
18 | pub(crate) struct RootDatabase { | 21 | pub(crate) struct RootDatabase { |
19 | runtime: salsa::runtime::Runtime<RootDatabase>, | 22 | runtime: salsa::Runtime<RootDatabase>, |
20 | } | 23 | } |
21 | 24 | ||
22 | impl fmt::Debug for RootDatabase { | 25 | impl fmt::Debug for RootDatabase { |
@@ -26,11 +29,19 @@ impl fmt::Debug for RootDatabase { | |||
26 | } | 29 | } |
27 | 30 | ||
28 | impl salsa::Database for RootDatabase { | 31 | impl salsa::Database for RootDatabase { |
29 | fn salsa_runtime(&self) -> &salsa::runtime::Runtime<RootDatabase> { | 32 | fn salsa_runtime(&self) -> &salsa::Runtime<RootDatabase> { |
30 | &self.runtime | 33 | &self.runtime |
31 | } | 34 | } |
32 | } | 35 | } |
33 | 36 | ||
37 | pub(crate) fn check_canceled(db: &impl salsa::Database) -> Cancelable<()> { | ||
38 | if db.salsa_runtime().is_current_revision_canceled() { | ||
39 | Err(Canceled) | ||
40 | } else { | ||
41 | Ok(()) | ||
42 | } | ||
43 | } | ||
44 | |||
34 | impl salsa::ParallelDatabase for RootDatabase { | 45 | impl salsa::ParallelDatabase for RootDatabase { |
35 | fn fork(&self) -> Self { | 46 | fn fork(&self) -> Self { |
36 | RootDatabase { | 47 | RootDatabase { |
@@ -69,7 +80,7 @@ salsa::query_group! { | |||
69 | type FileTextQuery; | 80 | type FileTextQuery; |
70 | storage input; | 81 | storage input; |
71 | } | 82 | } |
72 | fn file_set(key: ()) -> Arc<FileSet> { | 83 | fn file_set() -> Arc<FileSet> { |
73 | type FileSetQuery; | 84 | type FileSetQuery; |
74 | storage input; | 85 | storage input; |
75 | } | 86 | } |
@@ -104,7 +115,7 @@ salsa::query_group! { | |||
104 | fn file_lines(file_id: FileId) -> Arc<LineIndex> { | 115 | fn file_lines(file_id: FileId) -> Arc<LineIndex> { |
105 | type FileLinesQuery; | 116 | type FileLinesQuery; |
106 | } | 117 | } |
107 | fn file_symbols(file_id: FileId) -> Arc<SymbolIndex> { | 118 | fn file_symbols(file_id: FileId) -> Cancelable<Arc<SymbolIndex>> { |
108 | type FileSymbolsQuery; | 119 | type FileSymbolsQuery; |
109 | } | 120 | } |
110 | } | 121 | } |
@@ -118,7 +129,8 @@ fn file_lines(db: &impl SyntaxDatabase, file_id: FileId) -> Arc<LineIndex> { | |||
118 | let text = db.file_text(file_id); | 129 | let text = db.file_text(file_id); |
119 | Arc::new(LineIndex::new(&*text)) | 130 | Arc::new(LineIndex::new(&*text)) |
120 | } | 131 | } |
121 | fn file_symbols(db: &impl SyntaxDatabase, file_id: FileId) -> Arc<SymbolIndex> { | 132 | fn file_symbols(db: &impl SyntaxDatabase, file_id: FileId) -> Cancelable<Arc<SymbolIndex>> { |
133 | db::check_canceled(db)?; | ||
122 | let syntax = db.file_syntax(file_id); | 134 | let syntax = db.file_syntax(file_id); |
123 | Arc::new(SymbolIndex::for_file(file_id, syntax)) | 135 | Ok(Arc::new(SymbolIndex::for_file(file_id, syntax))) |
124 | } | 136 | } |
diff --git a/crates/ra_analysis/src/descriptors.rs b/crates/ra_analysis/src/descriptors.rs index 3fca3e581..92da26493 100644 --- a/crates/ra_analysis/src/descriptors.rs +++ b/crates/ra_analysis/src/descriptors.rs | |||
@@ -1,4 +1,5 @@ | |||
1 | use crate::{imp::FileResolverImp, FileId}; | 1 | use std::collections::BTreeMap; |
2 | |||
2 | use ra_syntax::{ | 3 | use ra_syntax::{ |
3 | ast::{self, AstNode, NameOwner}, | 4 | ast::{self, AstNode, NameOwner}, |
4 | text_utils::is_subrange, | 5 | text_utils::is_subrange, |
@@ -6,7 +7,7 @@ use ra_syntax::{ | |||
6 | }; | 7 | }; |
7 | use relative_path::RelativePathBuf; | 8 | use relative_path::RelativePathBuf; |
8 | 9 | ||
9 | use std::collections::BTreeMap; | 10 | use crate::{imp::FileResolverImp, FileId}; |
10 | 11 | ||
11 | #[derive(Debug, PartialEq, Eq, Hash)] | 12 | #[derive(Debug, PartialEq, Eq, Hash)] |
12 | pub struct ModuleDescriptor { | 13 | pub struct ModuleDescriptor { |
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index 2ed6694ba..196627539 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs | |||
@@ -19,8 +19,8 @@ use rustc_hash::FxHashSet; | |||
19 | use crate::{ | 19 | use crate::{ |
20 | descriptors::{FnDescriptor, ModuleTreeDescriptor, Problem}, | 20 | descriptors::{FnDescriptor, ModuleTreeDescriptor, Problem}, |
21 | roots::{ReadonlySourceRoot, SourceRoot, WritableSourceRoot}, | 21 | roots::{ReadonlySourceRoot, SourceRoot, WritableSourceRoot}, |
22 | CrateGraph, CrateId, Diagnostic, FileId, FileResolver, FileSystemEdit, JobToken, Position, | 22 | CrateGraph, CrateId, Diagnostic, FileId, FileResolver, FileSystemEdit, Position, |
23 | Query, SourceChange, SourceFileEdit, | 23 | Query, SourceChange, SourceFileEdit, Cancelable, |
24 | }; | 24 | }; |
25 | 25 | ||
26 | #[derive(Clone, Debug)] | 26 | #[derive(Clone, Debug)] |
@@ -148,19 +148,21 @@ impl AnalysisImpl { | |||
148 | pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> { | 148 | pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> { |
149 | self.root(file_id).lines(file_id) | 149 | self.root(file_id).lines(file_id) |
150 | } | 150 | } |
151 | pub fn world_symbols(&self, query: Query, token: &JobToken) -> Vec<(FileId, FileSymbol)> { | 151 | pub fn world_symbols(&self, query: Query) -> Cancelable<Vec<(FileId, FileSymbol)>> { |
152 | let mut buf = Vec::new(); | 152 | let mut buf = Vec::new(); |
153 | if query.libs { | 153 | if query.libs { |
154 | self.data.libs.iter().for_each(|it| it.symbols(&mut buf)); | 154 | for lib in self.data.libs.iter() { |
155 | lib.symbols(&mut buf)?; | ||
156 | } | ||
155 | } else { | 157 | } else { |
156 | self.data.root.symbols(&mut buf); | 158 | self.data.root.symbols(&mut buf)?; |
157 | } | 159 | } |
158 | query.search(&buf, token) | 160 | Ok(query.search(&buf)) |
159 | } | 161 | } |
160 | pub fn parent_module(&self, file_id: FileId) -> Vec<(FileId, FileSymbol)> { | 162 | pub fn parent_module(&self, file_id: FileId) -> Cancelable<Vec<(FileId, FileSymbol)>> { |
161 | let root = self.root(file_id); | 163 | let root = self.root(file_id); |
162 | let module_tree = root.module_tree(); | 164 | let module_tree = root.module_tree()?; |
163 | module_tree | 165 | let res = module_tree |
164 | .parent_modules(file_id) | 166 | .parent_modules(file_id) |
165 | .iter() | 167 | .iter() |
166 | .map(|link| { | 168 | .map(|link| { |
@@ -174,10 +176,11 @@ impl AnalysisImpl { | |||
174 | }; | 176 | }; |
175 | (file_id, sym) | 177 | (file_id, sym) |
176 | }) | 178 | }) |
177 | .collect() | 179 | .collect(); |
180 | Ok(res) | ||
178 | } | 181 | } |
179 | pub fn crate_for(&self, file_id: FileId) -> Vec<CrateId> { | 182 | pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { |
180 | let module_tree = self.root(file_id).module_tree(); | 183 | let module_tree = self.root(file_id).module_tree()?; |
181 | let crate_graph = &self.data.crate_graph; | 184 | let crate_graph = &self.data.crate_graph; |
182 | let mut res = Vec::new(); | 185 | let mut res = Vec::new(); |
183 | let mut work = VecDeque::new(); | 186 | let mut work = VecDeque::new(); |
@@ -195,7 +198,7 @@ impl AnalysisImpl { | |||
195 | .filter(|&id| visited.insert(id)); | 198 | .filter(|&id| visited.insert(id)); |
196 | work.extend(parents); | 199 | work.extend(parents); |
197 | } | 200 | } |
198 | res | 201 | Ok(res) |
199 | } | 202 | } |
200 | pub fn crate_root(&self, crate_id: CrateId) -> FileId { | 203 | pub fn crate_root(&self, crate_id: CrateId) -> FileId { |
201 | self.data.crate_graph.crate_roots[&crate_id] | 204 | self.data.crate_graph.crate_roots[&crate_id] |
@@ -204,15 +207,14 @@ impl AnalysisImpl { | |||
204 | &self, | 207 | &self, |
205 | file_id: FileId, | 208 | file_id: FileId, |
206 | offset: TextUnit, | 209 | offset: TextUnit, |
207 | token: &JobToken, | 210 | ) -> Cancelable<Vec<(FileId, FileSymbol)>> { |
208 | ) -> Vec<(FileId, FileSymbol)> { | ||
209 | let root = self.root(file_id); | 211 | let root = self.root(file_id); |
210 | let module_tree = root.module_tree(); | 212 | let module_tree = root.module_tree()?; |
211 | let file = root.syntax(file_id); | 213 | let file = root.syntax(file_id); |
212 | let syntax = file.syntax(); | 214 | let syntax = file.syntax(); |
213 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, offset) { | 215 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, offset) { |
214 | // First try to resolve the symbol locally | 216 | // First try to resolve the symbol locally |
215 | if let Some((name, range)) = resolve_local_name(&file, offset, name_ref) { | 217 | return if let Some((name, range)) = resolve_local_name(&file, offset, name_ref) { |
216 | let mut vec = vec![]; | 218 | let mut vec = vec![]; |
217 | vec.push(( | 219 | vec.push(( |
218 | file_id, | 220 | file_id, |
@@ -222,12 +224,11 @@ impl AnalysisImpl { | |||
222 | kind: NAME, | 224 | kind: NAME, |
223 | }, | 225 | }, |
224 | )); | 226 | )); |
225 | 227 | Ok(vec) | |
226 | return vec; | ||
227 | } else { | 228 | } else { |
228 | // If that fails try the index based approach. | 229 | // If that fails try the index based approach. |
229 | return self.index_resolve(name_ref, token); | 230 | self.index_resolve(name_ref) |
230 | } | 231 | }; |
231 | } | 232 | } |
232 | if let Some(name) = find_node_at_offset::<ast::Name>(syntax, offset) { | 233 | if let Some(name) = find_node_at_offset::<ast::Name>(syntax, offset) { |
233 | if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) { | 234 | if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) { |
@@ -250,16 +251,48 @@ impl AnalysisImpl { | |||
250 | }) | 251 | }) |
251 | .collect(); | 252 | .collect(); |
252 | 253 | ||
253 | return res; | 254 | return Ok(res); |
254 | } | 255 | } |
255 | } | 256 | } |
256 | } | 257 | } |
257 | vec![] | 258 | Ok(vec![]) |
258 | } | 259 | } |
259 | 260 | ||
260 | pub fn diagnostics(&self, file_id: FileId) -> Vec<Diagnostic> { | 261 | pub fn find_all_refs(&self, file_id: FileId, offset: TextUnit) -> Vec<(FileId, TextRange)> { |
261 | let root = self.root(file_id); | 262 | let root = self.root(file_id); |
262 | let module_tree = root.module_tree(); | 263 | let file = root.syntax(file_id); |
264 | let syntax = file.syntax(); | ||
265 | |||
266 | let mut ret = vec![]; | ||
267 | |||
268 | // Find the symbol we are looking for | ||
269 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, offset) { | ||
270 | |||
271 | // We are only handing local references for now | ||
272 | if let Some(resolved) = resolve_local_name(&file, offset, name_ref) { | ||
273 | |||
274 | ret.push((file_id, resolved.1)); | ||
275 | |||
276 | if let Some(fn_def) = find_node_at_offset::<ast::FnDef>(syntax, offset) { | ||
277 | |||
278 | let refs : Vec<_> = fn_def.syntax().descendants() | ||
279 | .filter_map(ast::NameRef::cast) | ||
280 | .filter(|n: &ast::NameRef| resolve_local_name(&file, n.syntax().range().start(), *n) == Some(resolved.clone())) | ||
281 | .collect(); | ||
282 | |||
283 | for r in refs { | ||
284 | ret.push((file_id, r.syntax().range())); | ||
285 | } | ||
286 | } | ||
287 | } | ||
288 | } | ||
289 | |||
290 | ret | ||
291 | } | ||
292 | |||
293 | pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { | ||
294 | let root = self.root(file_id); | ||
295 | let module_tree = root.module_tree()?; | ||
263 | let syntax = root.syntax(file_id); | 296 | let syntax = root.syntax(file_id); |
264 | 297 | ||
265 | let mut res = ra_editor::diagnostics(&syntax) | 298 | let mut res = ra_editor::diagnostics(&syntax) |
@@ -314,7 +347,7 @@ impl AnalysisImpl { | |||
314 | }; | 347 | }; |
315 | res.push(diag) | 348 | res.push(diag) |
316 | } | 349 | } |
317 | res | 350 | Ok(res) |
318 | } | 351 | } |
319 | 352 | ||
320 | pub fn assists(&self, file_id: FileId, range: TextRange) -> Vec<SourceChange> { | 353 | pub fn assists(&self, file_id: FileId, range: TextRange) -> Vec<SourceChange> { |
@@ -347,18 +380,23 @@ impl AnalysisImpl { | |||
347 | &self, | 380 | &self, |
348 | file_id: FileId, | 381 | file_id: FileId, |
349 | offset: TextUnit, | 382 | offset: TextUnit, |
350 | token: &JobToken, | 383 | ) -> Cancelable<Option<(FnDescriptor, Option<usize>)>> { |
351 | ) -> Option<(FnDescriptor, Option<usize>)> { | ||
352 | let root = self.root(file_id); | 384 | let root = self.root(file_id); |
353 | let file = root.syntax(file_id); | 385 | let file = root.syntax(file_id); |
354 | let syntax = file.syntax(); | 386 | let syntax = file.syntax(); |
355 | 387 | ||
356 | // Find the calling expression and it's NameRef | 388 | // Find the calling expression and it's NameRef |
357 | let calling_node = FnCallNode::with_node(syntax, offset)?; | 389 | let calling_node = match FnCallNode::with_node(syntax, offset) { |
358 | let name_ref = calling_node.name_ref()?; | 390 | Some(node) => node, |
391 | None => return Ok(None), | ||
392 | }; | ||
393 | let name_ref = match calling_node.name_ref() { | ||
394 | Some(name) => name, | ||
395 | None => return Ok(None), | ||
396 | }; | ||
359 | 397 | ||
360 | // Resolve the function's NameRef (NOTE: this isn't entirely accurate). | 398 | // Resolve the function's NameRef (NOTE: this isn't entirely accurate). |
361 | let file_symbols = self.index_resolve(name_ref, token); | 399 | let file_symbols = self.index_resolve(name_ref)?; |
362 | for (_, fs) in file_symbols { | 400 | for (_, fs) in file_symbols { |
363 | if fs.kind == FN_DEF { | 401 | if fs.kind == FN_DEF { |
364 | if let Some(fn_def) = find_node_at_offset(syntax, fs.node_range.start()) { | 402 | if let Some(fn_def) = find_node_at_offset(syntax, fs.node_range.start()) { |
@@ -400,21 +438,21 @@ impl AnalysisImpl { | |||
400 | } | 438 | } |
401 | } | 439 | } |
402 | 440 | ||
403 | return Some((descriptor, current_parameter)); | 441 | return Ok(Some((descriptor, current_parameter))); |
404 | } | 442 | } |
405 | } | 443 | } |
406 | } | 444 | } |
407 | } | 445 | } |
408 | 446 | ||
409 | None | 447 | Ok(None) |
410 | } | 448 | } |
411 | 449 | ||
412 | fn index_resolve(&self, name_ref: ast::NameRef, token: &JobToken) -> Vec<(FileId, FileSymbol)> { | 450 | fn index_resolve(&self, name_ref: ast::NameRef) -> Cancelable<Vec<(FileId, FileSymbol)>> { |
413 | let name = name_ref.text(); | 451 | let name = name_ref.text(); |
414 | let mut query = Query::new(name.to_string()); | 452 | let mut query = Query::new(name.to_string()); |
415 | query.exact(); | 453 | query.exact(); |
416 | query.limit(4); | 454 | query.limit(4); |
417 | self.world_symbols(query, token) | 455 | self.world_symbols(query) |
418 | } | 456 | } |
419 | 457 | ||
420 | fn resolve_module( | 458 | fn resolve_module( |
diff --git a/crates/ra_analysis/src/job.rs b/crates/ra_analysis/src/job.rs deleted file mode 100644 index 2871f9839..000000000 --- a/crates/ra_analysis/src/job.rs +++ /dev/null | |||
@@ -1,53 +0,0 @@ | |||
1 | use crossbeam_channel::{bounded, Receiver, Sender}; | ||
2 | |||
3 | pub struct JobHandle { | ||
4 | job_alive: Receiver<Never>, | ||
5 | _job_canceled: Sender<Never>, | ||
6 | } | ||
7 | |||
8 | pub struct JobToken { | ||
9 | _job_alive: Sender<Never>, | ||
10 | job_canceled: Receiver<Never>, | ||
11 | } | ||
12 | |||
13 | impl JobHandle { | ||
14 | pub fn new() -> (JobHandle, JobToken) { | ||
15 | let (sender_alive, receiver_alive) = bounded(0); | ||
16 | let (sender_canceled, receiver_canceled) = bounded(0); | ||
17 | let token = JobToken { | ||
18 | _job_alive: sender_alive, | ||
19 | job_canceled: receiver_canceled, | ||
20 | }; | ||
21 | let handle = JobHandle { | ||
22 | job_alive: receiver_alive, | ||
23 | _job_canceled: sender_canceled, | ||
24 | }; | ||
25 | (handle, token) | ||
26 | } | ||
27 | pub fn has_completed(&self) -> bool { | ||
28 | is_closed(&self.job_alive) | ||
29 | } | ||
30 | pub fn cancel(self) {} | ||
31 | } | ||
32 | |||
33 | impl JobToken { | ||
34 | pub fn is_canceled(&self) -> bool { | ||
35 | is_closed(&self.job_canceled) | ||
36 | } | ||
37 | } | ||
38 | |||
39 | // We don't actually send messages through the channels, | ||
40 | // and instead just check if the channel is closed, | ||
41 | // so we use uninhabited enum as a message type | ||
42 | enum Never {} | ||
43 | |||
44 | /// Nonblocking | ||
45 | fn is_closed(chan: &Receiver<Never>) -> bool { | ||
46 | select! { | ||
47 | recv(chan, msg) => match msg { | ||
48 | None => true, | ||
49 | Some(never) => match never {} | ||
50 | } | ||
51 | default => false, | ||
52 | } | ||
53 | } | ||
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index 2eeacaabe..38585f6e9 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs | |||
@@ -7,36 +7,46 @@ extern crate ra_editor; | |||
7 | extern crate ra_syntax; | 7 | extern crate ra_syntax; |
8 | extern crate rayon; | 8 | extern crate rayon; |
9 | extern crate relative_path; | 9 | extern crate relative_path; |
10 | #[macro_use] | ||
11 | extern crate crossbeam_channel; | ||
12 | extern crate im; | ||
13 | extern crate rustc_hash; | 10 | extern crate rustc_hash; |
14 | extern crate salsa; | 11 | extern crate salsa; |
15 | 12 | ||
16 | mod db; | 13 | mod db; |
17 | mod descriptors; | 14 | mod descriptors; |
18 | mod imp; | 15 | mod imp; |
19 | mod job; | ||
20 | mod module_map; | 16 | mod module_map; |
21 | mod roots; | 17 | mod roots; |
22 | mod symbol_index; | 18 | mod symbol_index; |
23 | 19 | ||
24 | use std::{fmt::Debug, sync::Arc}; | 20 | use std::{fmt::Debug, sync::Arc}; |
25 | 21 | ||
26 | use crate::imp::{AnalysisHostImpl, AnalysisImpl, FileResolverImp}; | ||
27 | use ra_syntax::{AtomEdit, File, TextRange, TextUnit}; | 22 | use ra_syntax::{AtomEdit, File, TextRange, TextUnit}; |
28 | use relative_path::{RelativePath, RelativePathBuf}; | 23 | use relative_path::{RelativePath, RelativePathBuf}; |
29 | use rustc_hash::FxHashMap; | 24 | use rustc_hash::FxHashMap; |
30 | 25 | ||
26 | use crate::imp::{AnalysisHostImpl, AnalysisImpl, FileResolverImp}; | ||
27 | |||
31 | pub use crate::{ | 28 | pub use crate::{ |
32 | descriptors::FnDescriptor, | 29 | descriptors::FnDescriptor, |
33 | job::{JobHandle, JobToken}, | ||
34 | }; | 30 | }; |
35 | pub use ra_editor::{ | 31 | pub use ra_editor::{ |
36 | CompletionItem, FileSymbol, Fold, FoldKind, HighlightedRange, LineIndex, Runnable, | 32 | CompletionItem, FileSymbol, Fold, FoldKind, HighlightedRange, LineIndex, Runnable, |
37 | RunnableKind, StructureNode, | 33 | RunnableKind, StructureNode, |
38 | }; | 34 | }; |
39 | 35 | ||
36 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] | ||
37 | pub struct Canceled; | ||
38 | |||
39 | pub type Cancelable<T> = Result<T, Canceled>; | ||
40 | |||
41 | impl std::fmt::Display for Canceled { | ||
42 | fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
43 | fmt.write_str("Canceled") | ||
44 | } | ||
45 | } | ||
46 | |||
47 | impl std::error::Error for Canceled { | ||
48 | } | ||
49 | |||
40 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | 50 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
41 | pub struct FileId(pub u32); | 51 | pub struct FileId(pub u32); |
42 | 52 | ||
@@ -205,57 +215,57 @@ impl Analysis { | |||
205 | let file = self.imp.file_syntax(file_id); | 215 | let file = self.imp.file_syntax(file_id); |
206 | ra_editor::file_structure(&file) | 216 | ra_editor::file_structure(&file) |
207 | } | 217 | } |
208 | pub fn symbol_search(&self, query: Query, token: &JobToken) -> Vec<(FileId, FileSymbol)> { | 218 | pub fn folding_ranges(&self, file_id: FileId) -> Vec<Fold> { |
209 | self.imp.world_symbols(query, token) | 219 | let file = self.imp.file_syntax(file_id); |
220 | ra_editor::folding_ranges(&file) | ||
221 | } | ||
222 | pub fn symbol_search(&self, query: Query) -> Cancelable<Vec<(FileId, FileSymbol)>> { | ||
223 | self.imp.world_symbols(query) | ||
210 | } | 224 | } |
211 | pub fn approximately_resolve_symbol( | 225 | pub fn approximately_resolve_symbol( |
212 | &self, | 226 | &self, |
213 | file_id: FileId, | 227 | file_id: FileId, |
214 | offset: TextUnit, | 228 | offset: TextUnit |
215 | token: &JobToken, | 229 | ) -> Cancelable<Vec<(FileId, FileSymbol)>> { |
216 | ) -> Vec<(FileId, FileSymbol)> { | ||
217 | self.imp | 230 | self.imp |
218 | .approximately_resolve_symbol(file_id, offset, token) | 231 | .approximately_resolve_symbol(file_id, offset) |
232 | } | ||
233 | pub fn find_all_refs(&self, file_id: FileId, offset: TextUnit, ) -> Cancelable<Vec<(FileId, TextRange)>> { | ||
234 | Ok(self.imp.find_all_refs(file_id, offset)) | ||
219 | } | 235 | } |
220 | pub fn parent_module(&self, file_id: FileId) -> Vec<(FileId, FileSymbol)> { | 236 | pub fn parent_module(&self, file_id: FileId) -> Cancelable<Vec<(FileId, FileSymbol)>> { |
221 | self.imp.parent_module(file_id) | 237 | self.imp.parent_module(file_id) |
222 | } | 238 | } |
223 | pub fn crate_for(&self, file_id: FileId) -> Vec<CrateId> { | 239 | pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { |
224 | self.imp.crate_for(file_id) | 240 | self.imp.crate_for(file_id) |
225 | } | 241 | } |
226 | pub fn crate_root(&self, crate_id: CrateId) -> FileId { | 242 | pub fn crate_root(&self, crate_id: CrateId) -> Cancelable<FileId> { |
227 | self.imp.crate_root(crate_id) | 243 | Ok(self.imp.crate_root(crate_id)) |
228 | } | 244 | } |
229 | pub fn runnables(&self, file_id: FileId) -> Vec<Runnable> { | 245 | pub fn runnables(&self, file_id: FileId) -> Cancelable<Vec<Runnable>> { |
230 | let file = self.imp.file_syntax(file_id); | 246 | let file = self.imp.file_syntax(file_id); |
231 | ra_editor::runnables(&file) | 247 | Ok(ra_editor::runnables(&file)) |
232 | } | 248 | } |
233 | pub fn highlight(&self, file_id: FileId) -> Vec<HighlightedRange> { | 249 | pub fn highlight(&self, file_id: FileId) -> Cancelable<Vec<HighlightedRange>> { |
234 | let file = self.imp.file_syntax(file_id); | 250 | let file = self.imp.file_syntax(file_id); |
235 | ra_editor::highlight(&file) | 251 | Ok(ra_editor::highlight(&file)) |
236 | } | 252 | } |
237 | pub fn completions(&self, file_id: FileId, offset: TextUnit) -> Option<Vec<CompletionItem>> { | 253 | pub fn completions(&self, file_id: FileId, offset: TextUnit) -> Cancelable<Option<Vec<CompletionItem>>> { |
238 | let file = self.imp.file_syntax(file_id); | 254 | let file = self.imp.file_syntax(file_id); |
239 | ra_editor::scope_completion(&file, offset) | 255 | Ok(ra_editor::scope_completion(&file, offset)) |
240 | } | 256 | } |
241 | pub fn assists(&self, file_id: FileId, range: TextRange) -> Vec<SourceChange> { | 257 | pub fn assists(&self, file_id: FileId, range: TextRange) -> Cancelable<Vec<SourceChange>> { |
242 | self.imp.assists(file_id, range) | 258 | Ok(self.imp.assists(file_id, range)) |
243 | } | 259 | } |
244 | pub fn diagnostics(&self, file_id: FileId) -> Vec<Diagnostic> { | 260 | pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { |
245 | self.imp.diagnostics(file_id) | 261 | self.imp.diagnostics(file_id) |
246 | } | 262 | } |
247 | pub fn folding_ranges(&self, file_id: FileId) -> Vec<Fold> { | ||
248 | let file = self.imp.file_syntax(file_id); | ||
249 | ra_editor::folding_ranges(&file) | ||
250 | } | ||
251 | |||
252 | pub fn resolve_callable( | 263 | pub fn resolve_callable( |
253 | &self, | 264 | &self, |
254 | file_id: FileId, | 265 | file_id: FileId, |
255 | offset: TextUnit, | 266 | offset: TextUnit, |
256 | token: &JobToken, | 267 | ) -> Cancelable<Option<(FnDescriptor, Option<usize>)>> { |
257 | ) -> Option<(FnDescriptor, Option<usize>)> { | 268 | self.imp.resolve_callable(file_id, offset) |
258 | self.imp.resolve_callable(file_id, offset, token) | ||
259 | } | 269 | } |
260 | } | 270 | } |
261 | 271 | ||
diff --git a/crates/ra_analysis/src/module_map.rs b/crates/ra_analysis/src/module_map.rs index ff0ec3cc7..3c800265a 100644 --- a/crates/ra_analysis/src/module_map.rs +++ b/crates/ra_analysis/src/module_map.rs | |||
@@ -1,37 +1,41 @@ | |||
1 | use std::sync::Arc; | ||
2 | |||
1 | use crate::{ | 3 | use crate::{ |
4 | db, | ||
5 | Cancelable, | ||
2 | db::SyntaxDatabase, | 6 | db::SyntaxDatabase, |
3 | descriptors::{ModuleDescriptor, ModuleTreeDescriptor}, | 7 | descriptors::{ModuleDescriptor, ModuleTreeDescriptor}, |
4 | FileId, | 8 | FileId, |
5 | }; | 9 | }; |
6 | 10 | ||
7 | use std::sync::Arc; | ||
8 | |||
9 | salsa::query_group! { | 11 | salsa::query_group! { |
10 | pub(crate) trait ModulesDatabase: SyntaxDatabase { | 12 | pub(crate) trait ModulesDatabase: SyntaxDatabase { |
11 | fn module_tree(key: ()) -> Arc<ModuleTreeDescriptor> { | 13 | fn module_tree() -> Cancelable<Arc<ModuleTreeDescriptor>> { |
12 | type ModuleTreeQuery; | 14 | type ModuleTreeQuery; |
13 | } | 15 | } |
14 | fn module_descriptor(file_id: FileId) -> Arc<ModuleDescriptor> { | 16 | fn module_descriptor(file_id: FileId) -> Cancelable<Arc<ModuleDescriptor>> { |
15 | type ModuleDescriptorQuery; | 17 | type ModuleDescriptorQuery; |
16 | } | 18 | } |
17 | } | 19 | } |
18 | } | 20 | } |
19 | 21 | ||
20 | fn module_descriptor(db: &impl ModulesDatabase, file_id: FileId) -> Arc<ModuleDescriptor> { | 22 | fn module_descriptor(db: &impl ModulesDatabase, file_id: FileId) -> Cancelable<Arc<ModuleDescriptor>> { |
23 | db::check_canceled(db)?; | ||
21 | let file = db.file_syntax(file_id); | 24 | let file = db.file_syntax(file_id); |
22 | Arc::new(ModuleDescriptor::new(file.ast())) | 25 | Ok(Arc::new(ModuleDescriptor::new(file.ast()))) |
23 | } | 26 | } |
24 | 27 | ||
25 | fn module_tree(db: &impl ModulesDatabase, (): ()) -> Arc<ModuleTreeDescriptor> { | 28 | fn module_tree(db: &impl ModulesDatabase) -> Cancelable<Arc<ModuleTreeDescriptor>> { |
26 | let file_set = db.file_set(()); | 29 | db::check_canceled(db)?; |
30 | let file_set = db.file_set(); | ||
27 | let mut files = Vec::new(); | 31 | let mut files = Vec::new(); |
28 | for &file_id in file_set.files.iter() { | 32 | for &file_id in file_set.files.iter() { |
29 | let module_descr = db.module_descriptor(file_id); | 33 | let module_descr = db.module_descriptor(file_id)?; |
30 | files.push((file_id, module_descr)); | 34 | files.push((file_id, module_descr)); |
31 | } | 35 | } |
32 | let res = ModuleTreeDescriptor::new( | 36 | let res = ModuleTreeDescriptor::new( |
33 | files.iter().map(|(file_id, descr)| (*file_id, &**descr)), | 37 | files.iter().map(|(file_id, descr)| (*file_id, &**descr)), |
34 | &file_set.resolver, | 38 | &file_set.resolver, |
35 | ); | 39 | ); |
36 | Arc::new(res) | 40 | Ok(Arc::new(res)) |
37 | } | 41 | } |
diff --git a/crates/ra_analysis/src/roots.rs b/crates/ra_analysis/src/roots.rs index 1f2b21b27..123c4acfa 100644 --- a/crates/ra_analysis/src/roots.rs +++ b/crates/ra_analysis/src/roots.rs | |||
@@ -8,6 +8,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; | |||
8 | use salsa::Database; | 8 | use salsa::Database; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | Cancelable, | ||
11 | db::{self, FilesDatabase, SyntaxDatabase}, | 12 | db::{self, FilesDatabase, SyntaxDatabase}, |
12 | descriptors::{ModuleDescriptor, ModuleTreeDescriptor}, | 13 | descriptors::{ModuleDescriptor, ModuleTreeDescriptor}, |
13 | imp::FileResolverImp, | 14 | imp::FileResolverImp, |
@@ -18,10 +19,10 @@ use crate::{ | |||
18 | 19 | ||
19 | pub(crate) trait SourceRoot { | 20 | pub(crate) trait SourceRoot { |
20 | fn contains(&self, file_id: FileId) -> bool; | 21 | fn contains(&self, file_id: FileId) -> bool; |
21 | fn module_tree(&self) -> Arc<ModuleTreeDescriptor>; | 22 | fn module_tree(&self) -> Cancelable<Arc<ModuleTreeDescriptor>>; |
22 | fn lines(&self, file_id: FileId) -> Arc<LineIndex>; | 23 | fn lines(&self, file_id: FileId) -> Arc<LineIndex>; |
23 | fn syntax(&self, file_id: FileId) -> File; | 24 | fn syntax(&self, file_id: FileId) -> File; |
24 | fn symbols(&self, acc: &mut Vec<Arc<SymbolIndex>>); | 25 | fn symbols(&self, acc: &mut Vec<Arc<SymbolIndex>>) -> Cancelable<()>; |
25 | } | 26 | } |
26 | 27 | ||
27 | #[derive(Default, Debug, Clone)] | 28 | #[derive(Default, Debug, Clone)] |
@@ -50,7 +51,7 @@ impl WritableSourceRoot { | |||
50 | } | 51 | } |
51 | } | 52 | } |
52 | } | 53 | } |
53 | let file_set = self.db.file_set(()); | 54 | let file_set = self.db.file_set(); |
54 | let mut files: FxHashSet<FileId> = file_set.files.clone(); | 55 | let mut files: FxHashSet<FileId> = file_set.files.clone(); |
55 | for file_id in removed { | 56 | for file_id in removed { |
56 | files.remove(&file_id); | 57 | files.remove(&file_id); |
@@ -64,11 +65,11 @@ impl WritableSourceRoot { | |||
64 | } | 65 | } |
65 | 66 | ||
66 | impl SourceRoot for WritableSourceRoot { | 67 | impl SourceRoot for WritableSourceRoot { |
67 | fn module_tree(&self) -> Arc<ModuleTreeDescriptor> { | 68 | fn module_tree(&self) -> Cancelable<Arc<ModuleTreeDescriptor>> { |
68 | self.db.module_tree(()) | 69 | self.db.module_tree() |
69 | } | 70 | } |
70 | fn contains(&self, file_id: FileId) -> bool { | 71 | fn contains(&self, file_id: FileId) -> bool { |
71 | self.db.file_set(()).files.contains(&file_id) | 72 | self.db.file_set().files.contains(&file_id) |
72 | } | 73 | } |
73 | fn lines(&self, file_id: FileId) -> Arc<LineIndex> { | 74 | fn lines(&self, file_id: FileId) -> Arc<LineIndex> { |
74 | self.db.file_lines(file_id) | 75 | self.db.file_lines(file_id) |
@@ -76,14 +77,12 @@ impl SourceRoot for WritableSourceRoot { | |||
76 | fn syntax(&self, file_id: FileId) -> File { | 77 | fn syntax(&self, file_id: FileId) -> File { |
77 | self.db.file_syntax(file_id) | 78 | self.db.file_syntax(file_id) |
78 | } | 79 | } |
79 | fn symbols<'a>(&'a self, acc: &mut Vec<Arc<SymbolIndex>>) { | 80 | fn symbols<'a>(&'a self, acc: &mut Vec<Arc<SymbolIndex>>) -> Cancelable<()> { |
80 | let db = &self.db; | 81 | for &file_id in self.db.file_set().files.iter() { |
81 | let symbols = db.file_set(()); | 82 | let symbols = self.db.file_symbols(file_id)?; |
82 | let symbols = symbols | 83 | acc.push(symbols) |
83 | .files | 84 | } |
84 | .iter() | 85 | Ok(()) |
85 | .map(|&file_id| db.file_symbols(file_id)); | ||
86 | acc.extend(symbols); | ||
87 | } | 86 | } |
88 | } | 87 | } |
89 | 88 | ||
@@ -167,8 +166,8 @@ impl ReadonlySourceRoot { | |||
167 | } | 166 | } |
168 | 167 | ||
169 | impl SourceRoot for ReadonlySourceRoot { | 168 | impl SourceRoot for ReadonlySourceRoot { |
170 | fn module_tree(&self) -> Arc<ModuleTreeDescriptor> { | 169 | fn module_tree(&self) -> Cancelable<Arc<ModuleTreeDescriptor>> { |
171 | Arc::clone(&self.module_tree) | 170 | Ok(Arc::clone(&self.module_tree)) |
172 | } | 171 | } |
173 | fn contains(&self, file_id: FileId) -> bool { | 172 | fn contains(&self, file_id: FileId) -> bool { |
174 | self.file_map.contains_key(&file_id) | 173 | self.file_map.contains_key(&file_id) |
@@ -179,7 +178,8 @@ impl SourceRoot for ReadonlySourceRoot { | |||
179 | fn syntax(&self, file_id: FileId) -> File { | 178 | fn syntax(&self, file_id: FileId) -> File { |
180 | self.data(file_id).syntax().clone() | 179 | self.data(file_id).syntax().clone() |
181 | } | 180 | } |
182 | fn symbols(&self, acc: &mut Vec<Arc<SymbolIndex>>) { | 181 | fn symbols(&self, acc: &mut Vec<Arc<SymbolIndex>>) -> Cancelable<()> { |
183 | acc.push(Arc::clone(&self.symbol_index)) | 182 | acc.push(Arc::clone(&self.symbol_index)); |
183 | Ok(()) | ||
184 | } | 184 | } |
185 | } | 185 | } |
diff --git a/crates/ra_analysis/src/symbol_index.rs b/crates/ra_analysis/src/symbol_index.rs index 51eef8170..a0f3c0437 100644 --- a/crates/ra_analysis/src/symbol_index.rs +++ b/crates/ra_analysis/src/symbol_index.rs | |||
@@ -1,4 +1,8 @@ | |||
1 | use crate::{FileId, JobToken, Query}; | 1 | use std::{ |
2 | hash::{Hash, Hasher}, | ||
3 | sync::Arc, | ||
4 | }; | ||
5 | |||
2 | use fst::{self, Streamer}; | 6 | use fst::{self, Streamer}; |
3 | use ra_editor::{file_symbols, FileSymbol}; | 7 | use ra_editor::{file_symbols, FileSymbol}; |
4 | use ra_syntax::{ | 8 | use ra_syntax::{ |
@@ -7,10 +11,7 @@ use ra_syntax::{ | |||
7 | }; | 11 | }; |
8 | use rayon::prelude::*; | 12 | use rayon::prelude::*; |
9 | 13 | ||
10 | use std::{ | 14 | use crate::{FileId, Query}; |
11 | hash::{Hash, Hasher}, | ||
12 | sync::Arc, | ||
13 | }; | ||
14 | 15 | ||
15 | #[derive(Debug)] | 16 | #[derive(Debug)] |
16 | pub(crate) struct SymbolIndex { | 17 | pub(crate) struct SymbolIndex { |
@@ -59,7 +60,6 @@ impl Query { | |||
59 | pub(crate) fn search( | 60 | pub(crate) fn search( |
60 | self, | 61 | self, |
61 | indices: &[Arc<SymbolIndex>], | 62 | indices: &[Arc<SymbolIndex>], |
62 | token: &JobToken, | ||
63 | ) -> Vec<(FileId, FileSymbol)> { | 63 | ) -> Vec<(FileId, FileSymbol)> { |
64 | let mut op = fst::map::OpBuilder::new(); | 64 | let mut op = fst::map::OpBuilder::new(); |
65 | for file_symbols in indices.iter() { | 65 | for file_symbols in indices.iter() { |
@@ -69,7 +69,7 @@ impl Query { | |||
69 | let mut stream = op.union(); | 69 | let mut stream = op.union(); |
70 | let mut res = Vec::new(); | 70 | let mut res = Vec::new(); |
71 | while let Some((_, indexed_values)) = stream.next() { | 71 | while let Some((_, indexed_values)) = stream.next() { |
72 | if res.len() >= self.limit || token.is_canceled() { | 72 | if res.len() >= self.limit { |
73 | break; | 73 | break; |
74 | } | 74 | } |
75 | for indexed_value in indexed_values { | 75 | for indexed_value in indexed_values { |
diff --git a/crates/ra_analysis/tests/tests.rs b/crates/ra_analysis/tests/tests.rs index e0c637d65..7ae3d0eeb 100644 --- a/crates/ra_analysis/tests/tests.rs +++ b/crates/ra_analysis/tests/tests.rs | |||
@@ -7,13 +7,15 @@ extern crate test_utils; | |||
7 | 7 | ||
8 | use std::sync::Arc; | 8 | use std::sync::Arc; |
9 | 9 | ||
10 | use ra_analysis::{ | 10 | use ra_syntax::TextRange; |
11 | Analysis, AnalysisHost, CrateGraph, CrateId, FileId, FileResolver, FnDescriptor, JobHandle, | ||
12 | }; | ||
13 | use relative_path::{RelativePath, RelativePathBuf}; | 11 | use relative_path::{RelativePath, RelativePathBuf}; |
14 | use rustc_hash::FxHashMap; | 12 | use rustc_hash::FxHashMap; |
15 | use test_utils::{assert_eq_dbg, extract_offset}; | 13 | use test_utils::{assert_eq_dbg, extract_offset}; |
16 | 14 | ||
15 | use ra_analysis::{ | ||
16 | Analysis, AnalysisHost, CrateGraph, CrateId, FileId, FileResolver, FnDescriptor, | ||
17 | }; | ||
18 | |||
17 | #[derive(Debug)] | 19 | #[derive(Debug)] |
18 | struct FileMap(Vec<(FileId, RelativePathBuf)>); | 20 | struct FileMap(Vec<(FileId, RelativePathBuf)>); |
19 | 21 | ||
@@ -62,24 +64,22 @@ fn get_signature(text: &str) -> (FnDescriptor, Option<usize>) { | |||
62 | let (offset, code) = extract_offset(text); | 64 | let (offset, code) = extract_offset(text); |
63 | let code = code.as_str(); | 65 | let code = code.as_str(); |
64 | 66 | ||
65 | let (_handle, token) = JobHandle::new(); | ||
66 | let snap = analysis(&[("/lib.rs", code)]); | 67 | let snap = analysis(&[("/lib.rs", code)]); |
67 | 68 | ||
68 | snap.resolve_callable(FileId(1), offset, &token).unwrap() | 69 | snap.resolve_callable(FileId(1), offset).unwrap().unwrap() |
69 | } | 70 | } |
70 | 71 | ||
71 | #[test] | 72 | #[test] |
72 | fn test_resolve_module() { | 73 | fn test_resolve_module() { |
73 | let snap = analysis(&[("/lib.rs", "mod foo;"), ("/foo.rs", "")]); | 74 | let snap = analysis(&[("/lib.rs", "mod foo;"), ("/foo.rs", "")]); |
74 | let (_handle, token) = JobHandle::new(); | 75 | let symbols = snap.approximately_resolve_symbol(FileId(1), 4.into()).unwrap(); |
75 | let symbols = snap.approximately_resolve_symbol(FileId(1), 4.into(), &token); | ||
76 | assert_eq_dbg( | 76 | assert_eq_dbg( |
77 | r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#, | 77 | r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#, |
78 | &symbols, | 78 | &symbols, |
79 | ); | 79 | ); |
80 | 80 | ||
81 | let snap = analysis(&[("/lib.rs", "mod foo;"), ("/foo/mod.rs", "")]); | 81 | let snap = analysis(&[("/lib.rs", "mod foo;"), ("/foo/mod.rs", "")]); |
82 | let symbols = snap.approximately_resolve_symbol(FileId(1), 4.into(), &token); | 82 | let symbols = snap.approximately_resolve_symbol(FileId(1), 4.into()).unwrap(); |
83 | assert_eq_dbg( | 83 | assert_eq_dbg( |
84 | r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#, | 84 | r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#, |
85 | &symbols, | 85 | &symbols, |
@@ -89,7 +89,7 @@ fn test_resolve_module() { | |||
89 | #[test] | 89 | #[test] |
90 | fn test_unresolved_module_diagnostic() { | 90 | fn test_unresolved_module_diagnostic() { |
91 | let snap = analysis(&[("/lib.rs", "mod foo;")]); | 91 | let snap = analysis(&[("/lib.rs", "mod foo;")]); |
92 | let diagnostics = snap.diagnostics(FileId(1)); | 92 | let diagnostics = snap.diagnostics(FileId(1)).unwrap(); |
93 | assert_eq_dbg( | 93 | assert_eq_dbg( |
94 | r#"[Diagnostic { | 94 | r#"[Diagnostic { |
95 | message: "unresolved module", | 95 | message: "unresolved module", |
@@ -106,14 +106,14 @@ fn test_unresolved_module_diagnostic() { | |||
106 | #[test] | 106 | #[test] |
107 | fn test_unresolved_module_diagnostic_no_diag_for_inline_mode() { | 107 | fn test_unresolved_module_diagnostic_no_diag_for_inline_mode() { |
108 | let snap = analysis(&[("/lib.rs", "mod foo {}")]); | 108 | let snap = analysis(&[("/lib.rs", "mod foo {}")]); |
109 | let diagnostics = snap.diagnostics(FileId(1)); | 109 | let diagnostics = snap.diagnostics(FileId(1)).unwrap(); |
110 | assert_eq_dbg(r#"[]"#, &diagnostics); | 110 | assert_eq_dbg(r#"[]"#, &diagnostics); |
111 | } | 111 | } |
112 | 112 | ||
113 | #[test] | 113 | #[test] |
114 | fn test_resolve_parent_module() { | 114 | fn test_resolve_parent_module() { |
115 | let snap = analysis(&[("/lib.rs", "mod foo;"), ("/foo.rs", "")]); | 115 | let snap = analysis(&[("/lib.rs", "mod foo;"), ("/foo.rs", "")]); |
116 | let symbols = snap.parent_module(FileId(2)); | 116 | let symbols = snap.parent_module(FileId(2)).unwrap(); |
117 | assert_eq_dbg( | 117 | assert_eq_dbg( |
118 | r#"[(FileId(1), FileSymbol { name: "foo", node_range: [0; 8), kind: MODULE })]"#, | 118 | r#"[(FileId(1), FileSymbol { name: "foo", node_range: [0; 8), kind: MODULE })]"#, |
119 | &symbols, | 119 | &symbols, |
@@ -124,7 +124,7 @@ fn test_resolve_parent_module() { | |||
124 | fn test_resolve_crate_root() { | 124 | fn test_resolve_crate_root() { |
125 | let mut host = analysis_host(&[("/lib.rs", "mod foo;"), ("/foo.rs", "")]); | 125 | let mut host = analysis_host(&[("/lib.rs", "mod foo;"), ("/foo.rs", "")]); |
126 | let snap = host.analysis(); | 126 | let snap = host.analysis(); |
127 | assert!(snap.crate_for(FileId(2)).is_empty()); | 127 | assert!(snap.crate_for(FileId(2)).unwrap().is_empty()); |
128 | 128 | ||
129 | let crate_graph = CrateGraph { | 129 | let crate_graph = CrateGraph { |
130 | crate_roots: { | 130 | crate_roots: { |
@@ -136,7 +136,7 @@ fn test_resolve_crate_root() { | |||
136 | host.set_crate_graph(crate_graph); | 136 | host.set_crate_graph(crate_graph); |
137 | let snap = host.analysis(); | 137 | let snap = host.analysis(); |
138 | 138 | ||
139 | assert_eq!(snap.crate_for(FileId(2)), vec![CrateId(1)],); | 139 | assert_eq!(snap.crate_for(FileId(2)).unwrap(), vec![CrateId(1)],); |
140 | } | 140 | } |
141 | 141 | ||
142 | #[test] | 142 | #[test] |
@@ -225,3 +225,42 @@ fn bar() { | |||
225 | assert_eq!(desc.ret_type, None); | 225 | assert_eq!(desc.ret_type, None); |
226 | assert_eq!(param, Some(1)); | 226 | assert_eq!(param, Some(1)); |
227 | } | 227 | } |
228 | |||
229 | fn get_all_refs(text: &str) -> Vec<(FileId, TextRange)> { | ||
230 | let (offset, code) = extract_offset(text); | ||
231 | let code = code.as_str(); | ||
232 | |||
233 | let snap = analysis(&[("/lib.rs", code)]); | ||
234 | |||
235 | snap.find_all_refs(FileId(1), offset).unwrap() | ||
236 | } | ||
237 | |||
238 | #[test] | ||
239 | fn test_find_all_refs_for_local() { | ||
240 | let code = r#" | ||
241 | fn main() { | ||
242 | let mut i = 1; | ||
243 | let j = 1; | ||
244 | i = i<|> + j; | ||
245 | |||
246 | { | ||
247 | i = 0; | ||
248 | } | ||
249 | |||
250 | i = 5; | ||
251 | }"#; | ||
252 | |||
253 | let refs = get_all_refs(code); | ||
254 | assert_eq!(refs.len(), 5); | ||
255 | } | ||
256 | |||
257 | #[test] | ||
258 | fn test_find_all_refs_for_param_inside() { | ||
259 | let code = r#" | ||
260 | fn foo(i : u32) -> u32 { | ||
261 | i<|> | ||
262 | }"#; | ||
263 | |||
264 | let refs = get_all_refs(code); | ||
265 | assert_eq!(refs.len(), 2); | ||
266 | } | ||
diff --git a/crates/ra_editor/src/scope/fn_scope.rs b/crates/ra_editor/src/scope/fn_scope.rs index 9088e5a60..f10bdf657 100644 --- a/crates/ra_editor/src/scope/fn_scope.rs +++ b/crates/ra_editor/src/scope/fn_scope.rs | |||
@@ -270,7 +270,6 @@ pub fn resolve_local_name<'a>( | |||
270 | .filter(|entry| shadowed.insert(entry.name())) | 270 | .filter(|entry| shadowed.insert(entry.name())) |
271 | .filter(|entry| entry.name() == name_ref.text()) | 271 | .filter(|entry| entry.name() == name_ref.text()) |
272 | .nth(0); | 272 | .nth(0); |
273 | eprintln!("ret = {:?}", ret); | ||
274 | ret | 273 | ret |
275 | } | 274 | } |
276 | 275 | ||
diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs index 1dd495791..b6436b646 100644 --- a/crates/ra_lsp_server/src/caps.rs +++ b/crates/ra_lsp_server/src/caps.rs | |||
@@ -2,7 +2,7 @@ use languageserver_types::{ | |||
2 | CodeActionProviderCapability, CompletionOptions, DocumentOnTypeFormattingOptions, | 2 | CodeActionProviderCapability, CompletionOptions, DocumentOnTypeFormattingOptions, |
3 | ExecuteCommandOptions, FoldingRangeProviderCapability, ServerCapabilities, | 3 | ExecuteCommandOptions, FoldingRangeProviderCapability, ServerCapabilities, |
4 | SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind, | 4 | SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind, |
5 | TextDocumentSyncOptions, | 5 | TextDocumentSyncOptions, RenameProviderCapability, RenameOptions |
6 | }; | 6 | }; |
7 | 7 | ||
8 | pub fn server_capabilities() -> ServerCapabilities { | 8 | pub fn server_capabilities() -> ServerCapabilities { |
@@ -27,7 +27,7 @@ pub fn server_capabilities() -> ServerCapabilities { | |||
27 | definition_provider: Some(true), | 27 | definition_provider: Some(true), |
28 | type_definition_provider: None, | 28 | type_definition_provider: None, |
29 | implementation_provider: None, | 29 | implementation_provider: None, |
30 | references_provider: None, | 30 | references_provider: Some(true), |
31 | document_highlight_provider: None, | 31 | document_highlight_provider: None, |
32 | document_symbol_provider: Some(true), | 32 | document_symbol_provider: Some(true), |
33 | workspace_symbol_provider: Some(true), | 33 | workspace_symbol_provider: Some(true), |
@@ -40,7 +40,9 @@ pub fn server_capabilities() -> ServerCapabilities { | |||
40 | more_trigger_character: None, | 40 | more_trigger_character: None, |
41 | }), | 41 | }), |
42 | folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)), | 42 | folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)), |
43 | rename_provider: None, | 43 | rename_provider: Some(RenameProviderCapability::Options(RenameOptions{ |
44 | prepare_provider: Some(true) | ||
45 | })), | ||
44 | color_provider: None, | 46 | color_provider: None, |
45 | execute_command_provider: Some(ExecuteCommandOptions { | 47 | execute_command_provider: Some(ExecuteCommandOptions { |
46 | commands: vec!["apply_code_action".to_string()], | 48 | commands: vec!["apply_code_action".to_string()], |
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 3e58e6f54..11f34eb93 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs | |||
@@ -1,11 +1,13 @@ | |||
1 | use rustc_hash::FxHashMap; | 1 | use std::collections::HashMap; |
2 | 2 | ||
3 | use rustc_hash::FxHashMap; | ||
3 | use languageserver_types::{ | 4 | use languageserver_types::{ |
4 | CodeActionResponse, Command, CompletionItem, CompletionItemKind, Diagnostic, | 5 | CodeActionResponse, Command, CompletionItem, CompletionItemKind, Diagnostic, |
5 | DiagnosticSeverity, DocumentSymbol, FoldingRange, FoldingRangeKind, FoldingRangeParams, | 6 | DiagnosticSeverity, DocumentSymbol, FoldingRange, FoldingRangeKind, FoldingRangeParams, |
6 | InsertTextFormat, Location, Position, SymbolInformation, TextDocumentIdentifier, TextEdit, | 7 | InsertTextFormat, Location, Position, SymbolInformation, TextDocumentIdentifier, TextEdit, |
8 | RenameParams, WorkspaceEdit, PrepareRenameResponse | ||
7 | }; | 9 | }; |
8 | use ra_analysis::{FileId, FoldKind, JobToken, Query, RunnableKind}; | 10 | use ra_analysis::{FileId, FoldKind, Query, RunnableKind}; |
9 | use ra_syntax::text_utils::contains_offset_nonstrict; | 11 | use ra_syntax::text_utils::contains_offset_nonstrict; |
10 | use serde_json::to_value; | 12 | use serde_json::to_value; |
11 | 13 | ||
@@ -20,7 +22,6 @@ use crate::{ | |||
20 | pub fn handle_syntax_tree( | 22 | pub fn handle_syntax_tree( |
21 | world: ServerWorld, | 23 | world: ServerWorld, |
22 | params: req::SyntaxTreeParams, | 24 | params: req::SyntaxTreeParams, |
23 | _token: JobToken, | ||
24 | ) -> Result<String> { | 25 | ) -> Result<String> { |
25 | let id = params.text_document.try_conv_with(&world)?; | 26 | let id = params.text_document.try_conv_with(&world)?; |
26 | let res = world.analysis().syntax_tree(id); | 27 | let res = world.analysis().syntax_tree(id); |
@@ -30,7 +31,6 @@ pub fn handle_syntax_tree( | |||
30 | pub fn handle_extend_selection( | 31 | pub fn handle_extend_selection( |
31 | world: ServerWorld, | 32 | world: ServerWorld, |
32 | params: req::ExtendSelectionParams, | 33 | params: req::ExtendSelectionParams, |
33 | _token: JobToken, | ||
34 | ) -> Result<req::ExtendSelectionResult> { | 34 | ) -> Result<req::ExtendSelectionResult> { |
35 | let file_id = params.text_document.try_conv_with(&world)?; | 35 | let file_id = params.text_document.try_conv_with(&world)?; |
36 | let file = world.analysis().file_syntax(file_id); | 36 | let file = world.analysis().file_syntax(file_id); |
@@ -48,7 +48,6 @@ pub fn handle_extend_selection( | |||
48 | pub fn handle_find_matching_brace( | 48 | pub fn handle_find_matching_brace( |
49 | world: ServerWorld, | 49 | world: ServerWorld, |
50 | params: req::FindMatchingBraceParams, | 50 | params: req::FindMatchingBraceParams, |
51 | _token: JobToken, | ||
52 | ) -> Result<Vec<Position>> { | 51 | ) -> Result<Vec<Position>> { |
53 | let file_id = params.text_document.try_conv_with(&world)?; | 52 | let file_id = params.text_document.try_conv_with(&world)?; |
54 | let file = world.analysis().file_syntax(file_id); | 53 | let file = world.analysis().file_syntax(file_id); |
@@ -71,7 +70,6 @@ pub fn handle_find_matching_brace( | |||
71 | pub fn handle_join_lines( | 70 | pub fn handle_join_lines( |
72 | world: ServerWorld, | 71 | world: ServerWorld, |
73 | params: req::JoinLinesParams, | 72 | params: req::JoinLinesParams, |
74 | _token: JobToken, | ||
75 | ) -> Result<req::SourceChange> { | 73 | ) -> Result<req::SourceChange> { |
76 | let file_id = params.text_document.try_conv_with(&world)?; | 74 | let file_id = params.text_document.try_conv_with(&world)?; |
77 | let line_index = world.analysis().file_line_index(file_id); | 75 | let line_index = world.analysis().file_line_index(file_id); |
@@ -85,7 +83,6 @@ pub fn handle_join_lines( | |||
85 | pub fn handle_on_enter( | 83 | pub fn handle_on_enter( |
86 | world: ServerWorld, | 84 | world: ServerWorld, |
87 | params: req::TextDocumentPositionParams, | 85 | params: req::TextDocumentPositionParams, |
88 | _token: JobToken, | ||
89 | ) -> Result<Option<req::SourceChange>> { | 86 | ) -> Result<Option<req::SourceChange>> { |
90 | let file_id = params.text_document.try_conv_with(&world)?; | 87 | let file_id = params.text_document.try_conv_with(&world)?; |
91 | let line_index = world.analysis().file_line_index(file_id); | 88 | let line_index = world.analysis().file_line_index(file_id); |
@@ -99,7 +96,6 @@ pub fn handle_on_enter( | |||
99 | pub fn handle_on_type_formatting( | 96 | pub fn handle_on_type_formatting( |
100 | world: ServerWorld, | 97 | world: ServerWorld, |
101 | params: req::DocumentOnTypeFormattingParams, | 98 | params: req::DocumentOnTypeFormattingParams, |
102 | _token: JobToken, | ||
103 | ) -> Result<Option<Vec<TextEdit>>> { | 99 | ) -> Result<Option<Vec<TextEdit>>> { |
104 | if params.ch != "=" { | 100 | if params.ch != "=" { |
105 | return Ok(None); | 101 | return Ok(None); |
@@ -119,7 +115,6 @@ pub fn handle_on_type_formatting( | |||
119 | pub fn handle_document_symbol( | 115 | pub fn handle_document_symbol( |
120 | world: ServerWorld, | 116 | world: ServerWorld, |
121 | params: req::DocumentSymbolParams, | 117 | params: req::DocumentSymbolParams, |
122 | _token: JobToken, | ||
123 | ) -> Result<Option<req::DocumentSymbolResponse>> { | 118 | ) -> Result<Option<req::DocumentSymbolResponse>> { |
124 | let file_id = params.text_document.try_conv_with(&world)?; | 119 | let file_id = params.text_document.try_conv_with(&world)?; |
125 | let line_index = world.analysis().file_line_index(file_id); | 120 | let line_index = world.analysis().file_line_index(file_id); |
@@ -158,7 +153,6 @@ pub fn handle_document_symbol( | |||
158 | pub fn handle_workspace_symbol( | 153 | pub fn handle_workspace_symbol( |
159 | world: ServerWorld, | 154 | world: ServerWorld, |
160 | params: req::WorkspaceSymbolParams, | 155 | params: req::WorkspaceSymbolParams, |
161 | token: JobToken, | ||
162 | ) -> Result<Option<Vec<SymbolInformation>>> { | 156 | ) -> Result<Option<Vec<SymbolInformation>>> { |
163 | let all_symbols = params.query.contains('#'); | 157 | let all_symbols = params.query.contains('#'); |
164 | let libs = params.query.contains('*'); | 158 | let libs = params.query.contains('*'); |
@@ -178,11 +172,11 @@ pub fn handle_workspace_symbol( | |||
178 | q.limit(128); | 172 | q.limit(128); |
179 | q | 173 | q |
180 | }; | 174 | }; |
181 | let mut res = exec_query(&world, query, &token)?; | 175 | let mut res = exec_query(&world, query)?; |
182 | if res.is_empty() && !all_symbols { | 176 | if res.is_empty() && !all_symbols { |
183 | let mut query = Query::new(params.query); | 177 | let mut query = Query::new(params.query); |
184 | query.limit(128); | 178 | query.limit(128); |
185 | res = exec_query(&world, query, &token)?; | 179 | res = exec_query(&world, query)?; |
186 | } | 180 | } |
187 | 181 | ||
188 | return Ok(Some(res)); | 182 | return Ok(Some(res)); |
@@ -190,10 +184,9 @@ pub fn handle_workspace_symbol( | |||
190 | fn exec_query( | 184 | fn exec_query( |
191 | world: &ServerWorld, | 185 | world: &ServerWorld, |
192 | query: Query, | 186 | query: Query, |
193 | token: &JobToken, | ||
194 | ) -> Result<Vec<SymbolInformation>> { | 187 | ) -> Result<Vec<SymbolInformation>> { |
195 | let mut res = Vec::new(); | 188 | let mut res = Vec::new(); |
196 | for (file_id, symbol) in world.analysis().symbol_search(query, token) { | 189 | for (file_id, symbol) in world.analysis().symbol_search(query)? { |
197 | let line_index = world.analysis().file_line_index(file_id); | 190 | let line_index = world.analysis().file_line_index(file_id); |
198 | let info = SymbolInformation { | 191 | let info = SymbolInformation { |
199 | name: symbol.name.to_string(), | 192 | name: symbol.name.to_string(), |
@@ -211,7 +204,6 @@ pub fn handle_workspace_symbol( | |||
211 | pub fn handle_goto_definition( | 204 | pub fn handle_goto_definition( |
212 | world: ServerWorld, | 205 | world: ServerWorld, |
213 | params: req::TextDocumentPositionParams, | 206 | params: req::TextDocumentPositionParams, |
214 | token: JobToken, | ||
215 | ) -> Result<Option<req::GotoDefinitionResponse>> { | 207 | ) -> Result<Option<req::GotoDefinitionResponse>> { |
216 | let file_id = params.text_document.try_conv_with(&world)?; | 208 | let file_id = params.text_document.try_conv_with(&world)?; |
217 | let line_index = world.analysis().file_line_index(file_id); | 209 | let line_index = world.analysis().file_line_index(file_id); |
@@ -219,7 +211,7 @@ pub fn handle_goto_definition( | |||
219 | let mut res = Vec::new(); | 211 | let mut res = Vec::new(); |
220 | for (file_id, symbol) in world | 212 | for (file_id, symbol) in world |
221 | .analysis() | 213 | .analysis() |
222 | .approximately_resolve_symbol(file_id, offset, &token) | 214 | .approximately_resolve_symbol(file_id, offset)? |
223 | { | 215 | { |
224 | let line_index = world.analysis().file_line_index(file_id); | 216 | let line_index = world.analysis().file_line_index(file_id); |
225 | let location = to_location(file_id, symbol.node_range, &world, &line_index)?; | 217 | let location = to_location(file_id, symbol.node_range, &world, &line_index)?; |
@@ -231,11 +223,10 @@ pub fn handle_goto_definition( | |||
231 | pub fn handle_parent_module( | 223 | pub fn handle_parent_module( |
232 | world: ServerWorld, | 224 | world: ServerWorld, |
233 | params: TextDocumentIdentifier, | 225 | params: TextDocumentIdentifier, |
234 | _token: JobToken, | ||
235 | ) -> Result<Vec<Location>> { | 226 | ) -> Result<Vec<Location>> { |
236 | let file_id = params.try_conv_with(&world)?; | 227 | let file_id = params.try_conv_with(&world)?; |
237 | let mut res = Vec::new(); | 228 | let mut res = Vec::new(); |
238 | for (file_id, symbol) in world.analysis().parent_module(file_id) { | 229 | for (file_id, symbol) in world.analysis().parent_module(file_id)? { |
239 | let line_index = world.analysis().file_line_index(file_id); | 230 | let line_index = world.analysis().file_line_index(file_id); |
240 | let location = to_location(file_id, symbol.node_range, &world, &line_index)?; | 231 | let location = to_location(file_id, symbol.node_range, &world, &line_index)?; |
241 | res.push(location); | 232 | res.push(location); |
@@ -246,20 +237,19 @@ pub fn handle_parent_module( | |||
246 | pub fn handle_runnables( | 237 | pub fn handle_runnables( |
247 | world: ServerWorld, | 238 | world: ServerWorld, |
248 | params: req::RunnablesParams, | 239 | params: req::RunnablesParams, |
249 | _token: JobToken, | ||
250 | ) -> Result<Vec<req::Runnable>> { | 240 | ) -> Result<Vec<req::Runnable>> { |
251 | let file_id = params.text_document.try_conv_with(&world)?; | 241 | let file_id = params.text_document.try_conv_with(&world)?; |
252 | let line_index = world.analysis().file_line_index(file_id); | 242 | let line_index = world.analysis().file_line_index(file_id); |
253 | let offset = params.position.map(|it| it.conv_with(&line_index)); | 243 | let offset = params.position.map(|it| it.conv_with(&line_index)); |
254 | let mut res = Vec::new(); | 244 | let mut res = Vec::new(); |
255 | for runnable in world.analysis().runnables(file_id) { | 245 | for runnable in world.analysis().runnables(file_id)? { |
256 | if let Some(offset) = offset { | 246 | if let Some(offset) = offset { |
257 | if !contains_offset_nonstrict(runnable.range, offset) { | 247 | if !contains_offset_nonstrict(runnable.range, offset) { |
258 | continue; | 248 | continue; |
259 | } | 249 | } |
260 | } | 250 | } |
261 | 251 | ||
262 | let args = runnable_args(&world, file_id, &runnable.kind); | 252 | let args = runnable_args(&world, file_id, &runnable.kind)?; |
263 | 253 | ||
264 | let r = req::Runnable { | 254 | let r = req::Runnable { |
265 | range: runnable.range.conv_with(&line_index), | 255 | range: runnable.range.conv_with(&line_index), |
@@ -279,9 +269,9 @@ pub fn handle_runnables( | |||
279 | } | 269 | } |
280 | return Ok(res); | 270 | return Ok(res); |
281 | 271 | ||
282 | fn runnable_args(world: &ServerWorld, file_id: FileId, kind: &RunnableKind) -> Vec<String> { | 272 | fn runnable_args(world: &ServerWorld, file_id: FileId, kind: &RunnableKind) -> Result<Vec<String>> { |
283 | let spec = if let Some(&crate_id) = world.analysis().crate_for(file_id).first() { | 273 | let spec = if let Some(&crate_id) = world.analysis().crate_for(file_id)?.first() { |
284 | let file_id = world.analysis().crate_root(crate_id); | 274 | let file_id = world.analysis().crate_root(crate_id)?; |
285 | let path = world.path_map.get_path(file_id); | 275 | let path = world.path_map.get_path(file_id); |
286 | world | 276 | world |
287 | .workspaces | 277 | .workspaces |
@@ -316,7 +306,7 @@ pub fn handle_runnables( | |||
316 | } | 306 | } |
317 | } | 307 | } |
318 | } | 308 | } |
319 | res | 309 | Ok(res) |
320 | } | 310 | } |
321 | 311 | ||
322 | fn spec_args(pkg_name: &str, tgt_name: &str, tgt_kind: TargetKind, buf: &mut Vec<String>) { | 312 | fn spec_args(pkg_name: &str, tgt_name: &str, tgt_kind: TargetKind, buf: &mut Vec<String>) { |
@@ -350,21 +340,19 @@ pub fn handle_runnables( | |||
350 | pub fn handle_decorations( | 340 | pub fn handle_decorations( |
351 | world: ServerWorld, | 341 | world: ServerWorld, |
352 | params: TextDocumentIdentifier, | 342 | params: TextDocumentIdentifier, |
353 | _token: JobToken, | ||
354 | ) -> Result<Vec<Decoration>> { | 343 | ) -> Result<Vec<Decoration>> { |
355 | let file_id = params.try_conv_with(&world)?; | 344 | let file_id = params.try_conv_with(&world)?; |
356 | Ok(highlight(&world, file_id)) | 345 | highlight(&world, file_id) |
357 | } | 346 | } |
358 | 347 | ||
359 | pub fn handle_completion( | 348 | pub fn handle_completion( |
360 | world: ServerWorld, | 349 | world: ServerWorld, |
361 | params: req::CompletionParams, | 350 | params: req::CompletionParams, |
362 | _token: JobToken, | ||
363 | ) -> Result<Option<req::CompletionResponse>> { | 351 | ) -> Result<Option<req::CompletionResponse>> { |
364 | let file_id = params.text_document.try_conv_with(&world)?; | 352 | let file_id = params.text_document.try_conv_with(&world)?; |
365 | let line_index = world.analysis().file_line_index(file_id); | 353 | let line_index = world.analysis().file_line_index(file_id); |
366 | let offset = params.position.conv_with(&line_index); | 354 | let offset = params.position.conv_with(&line_index); |
367 | let items = match world.analysis().completions(file_id, offset) { | 355 | let items = match world.analysis().completions(file_id, offset)? { |
368 | None => return Ok(None), | 356 | None => return Ok(None), |
369 | Some(items) => items, | 357 | Some(items) => items, |
370 | }; | 358 | }; |
@@ -391,7 +379,6 @@ pub fn handle_completion( | |||
391 | pub fn handle_folding_range( | 379 | pub fn handle_folding_range( |
392 | world: ServerWorld, | 380 | world: ServerWorld, |
393 | params: FoldingRangeParams, | 381 | params: FoldingRangeParams, |
394 | _token: JobToken, | ||
395 | ) -> Result<Option<Vec<FoldingRange>>> { | 382 | ) -> Result<Option<Vec<FoldingRange>>> { |
396 | let file_id = params.text_document.try_conv_with(&world)?; | 383 | let file_id = params.text_document.try_conv_with(&world)?; |
397 | let line_index = world.analysis().file_line_index(file_id); | 384 | let line_index = world.analysis().file_line_index(file_id); |
@@ -424,7 +411,6 @@ pub fn handle_folding_range( | |||
424 | pub fn handle_signature_help( | 411 | pub fn handle_signature_help( |
425 | world: ServerWorld, | 412 | world: ServerWorld, |
426 | params: req::TextDocumentPositionParams, | 413 | params: req::TextDocumentPositionParams, |
427 | token: JobToken, | ||
428 | ) -> Result<Option<req::SignatureHelp>> { | 414 | ) -> Result<Option<req::SignatureHelp>> { |
429 | use languageserver_types::{ParameterInformation, SignatureInformation}; | 415 | use languageserver_types::{ParameterInformation, SignatureInformation}; |
430 | 416 | ||
@@ -433,7 +419,7 @@ pub fn handle_signature_help( | |||
433 | let offset = params.position.conv_with(&line_index); | 419 | let offset = params.position.conv_with(&line_index); |
434 | 420 | ||
435 | if let Some((descriptor, active_param)) = | 421 | if let Some((descriptor, active_param)) = |
436 | world.analysis().resolve_callable(file_id, offset, &token) | 422 | world.analysis().resolve_callable(file_id, offset)? |
437 | { | 423 | { |
438 | let parameters: Vec<ParameterInformation> = descriptor | 424 | let parameters: Vec<ParameterInformation> = descriptor |
439 | .params | 425 | .params |
@@ -460,19 +446,90 @@ pub fn handle_signature_help( | |||
460 | } | 446 | } |
461 | } | 447 | } |
462 | 448 | ||
449 | pub fn handle_prepare_rename( | ||
450 | world: ServerWorld, | ||
451 | params: req::TextDocumentPositionParams, | ||
452 | ) -> Result<Option<PrepareRenameResponse>> { | ||
453 | let file_id = params.text_document.try_conv_with(&world)?; | ||
454 | let line_index = world.analysis().file_line_index(file_id); | ||
455 | let offset = params.position.conv_with(&line_index); | ||
456 | |||
457 | // We support renaming references like handle_rename does. | ||
458 | // In the future we may want to reject the renaming of things like keywords here too. | ||
459 | let refs = world.analysis().find_all_refs(file_id, offset)?; | ||
460 | if refs.is_empty() { | ||
461 | return Ok(None); | ||
462 | } | ||
463 | |||
464 | let r = refs.first().unwrap(); | ||
465 | let loc = to_location(r.0, r.1, &world, &line_index)?; | ||
466 | |||
467 | Ok(Some(PrepareRenameResponse::Range(loc.range))) | ||
468 | } | ||
469 | |||
470 | pub fn handle_rename( | ||
471 | world: ServerWorld, | ||
472 | params: RenameParams, | ||
473 | ) -> Result<Option<WorkspaceEdit>> { | ||
474 | let file_id = params.text_document.try_conv_with(&world)?; | ||
475 | let line_index = world.analysis().file_line_index(file_id); | ||
476 | let offset = params.position.conv_with(&line_index); | ||
477 | |||
478 | if params.new_name.is_empty() { | ||
479 | return Ok(None); | ||
480 | } | ||
481 | |||
482 | let refs = world.analysis().find_all_refs(file_id, offset)?; | ||
483 | if refs.is_empty() { | ||
484 | return Ok(None); | ||
485 | } | ||
486 | |||
487 | let mut changes = HashMap::new(); | ||
488 | for r in refs { | ||
489 | if let Ok(loc) = to_location(r.0, r.1, &world, &line_index) { | ||
490 | changes.entry(loc.uri).or_insert(Vec::new()).push( | ||
491 | TextEdit { | ||
492 | range: loc.range, | ||
493 | new_text: params.new_name.clone() | ||
494 | }); | ||
495 | } | ||
496 | } | ||
497 | |||
498 | Ok(Some(WorkspaceEdit { | ||
499 | changes: Some(changes), | ||
500 | |||
501 | // TODO: return this instead if client/server support it. See #144 | ||
502 | document_changes : None, | ||
503 | })) | ||
504 | } | ||
505 | |||
506 | pub fn handle_references( | ||
507 | world: ServerWorld, | ||
508 | params: req::ReferenceParams, | ||
509 | ) -> Result<Option<Vec<Location>>> { | ||
510 | let file_id = params.text_document.try_conv_with(&world)?; | ||
511 | let line_index = world.analysis().file_line_index(file_id); | ||
512 | let offset = params.position.conv_with(&line_index); | ||
513 | |||
514 | let refs = world.analysis().find_all_refs(file_id, offset)?; | ||
515 | |||
516 | Ok(Some(refs.into_iter() | ||
517 | .filter_map(|r| to_location(r.0, r.1, &world, &line_index).ok()) | ||
518 | .collect())) | ||
519 | } | ||
520 | |||
463 | pub fn handle_code_action( | 521 | pub fn handle_code_action( |
464 | world: ServerWorld, | 522 | world: ServerWorld, |
465 | params: req::CodeActionParams, | 523 | params: req::CodeActionParams, |
466 | _token: JobToken, | ||
467 | ) -> Result<Option<CodeActionResponse>> { | 524 | ) -> Result<Option<CodeActionResponse>> { |
468 | let file_id = params.text_document.try_conv_with(&world)?; | 525 | let file_id = params.text_document.try_conv_with(&world)?; |
469 | let line_index = world.analysis().file_line_index(file_id); | 526 | let line_index = world.analysis().file_line_index(file_id); |
470 | let range = params.range.conv_with(&line_index); | 527 | let range = params.range.conv_with(&line_index); |
471 | 528 | ||
472 | let assists = world.analysis().assists(file_id, range).into_iter(); | 529 | let assists = world.analysis().assists(file_id, range)?.into_iter(); |
473 | let fixes = world | 530 | let fixes = world |
474 | .analysis() | 531 | .analysis() |
475 | .diagnostics(file_id) | 532 | .diagnostics(file_id)? |
476 | .into_iter() | 533 | .into_iter() |
477 | .filter_map(|d| Some((d.range, d.fix?))) | 534 | .filter_map(|d| Some((d.range, d.fix?))) |
478 | .filter(|(range, _fix)| contains_offset_nonstrict(*range, range.start())) | 535 | .filter(|(range, _fix)| contains_offset_nonstrict(*range, range.start())) |
@@ -501,7 +558,7 @@ pub fn publish_diagnostics( | |||
501 | let line_index = world.analysis().file_line_index(file_id); | 558 | let line_index = world.analysis().file_line_index(file_id); |
502 | let diagnostics = world | 559 | let diagnostics = world |
503 | .analysis() | 560 | .analysis() |
504 | .diagnostics(file_id) | 561 | .diagnostics(file_id)? |
505 | .into_iter() | 562 | .into_iter() |
506 | .map(|d| Diagnostic { | 563 | .map(|d| Diagnostic { |
507 | range: d.range.conv_with(&line_index), | 564 | range: d.range.conv_with(&line_index), |
@@ -522,19 +579,20 @@ pub fn publish_decorations( | |||
522 | let uri = world.file_id_to_uri(file_id)?; | 579 | let uri = world.file_id_to_uri(file_id)?; |
523 | Ok(req::PublishDecorationsParams { | 580 | Ok(req::PublishDecorationsParams { |
524 | uri, | 581 | uri, |
525 | decorations: highlight(&world, file_id), | 582 | decorations: highlight(&world, file_id)?, |
526 | }) | 583 | }) |
527 | } | 584 | } |
528 | 585 | ||
529 | fn highlight(world: &ServerWorld, file_id: FileId) -> Vec<Decoration> { | 586 | fn highlight(world: &ServerWorld, file_id: FileId) -> Result<Vec<Decoration>> { |
530 | let line_index = world.analysis().file_line_index(file_id); | 587 | let line_index = world.analysis().file_line_index(file_id); |
531 | world | 588 | let res = world |
532 | .analysis() | 589 | .analysis() |
533 | .highlight(file_id) | 590 | .highlight(file_id)? |
534 | .into_iter() | 591 | .into_iter() |
535 | .map(|h| Decoration { | 592 | .map(|h| Decoration { |
536 | range: h.range.conv_with(&line_index), | 593 | range: h.range.conv_with(&line_index), |
537 | tag: h.tag, | 594 | tag: h.tag, |
538 | }) | 595 | }) |
539 | .collect() | 596 | .collect(); |
597 | Ok(res) | ||
540 | } | 598 | } |
diff --git a/crates/ra_lsp_server/src/main_loop/mod.rs b/crates/ra_lsp_server/src/main_loop/mod.rs index a11baf4aa..b35ebd38b 100644 --- a/crates/ra_lsp_server/src/main_loop/mod.rs +++ b/crates/ra_lsp_server/src/main_loop/mod.rs | |||
@@ -8,9 +8,9 @@ use gen_lsp_server::{ | |||
8 | handle_shutdown, ErrorCode, RawMessage, RawNotification, RawRequest, RawResponse, | 8 | handle_shutdown, ErrorCode, RawMessage, RawNotification, RawRequest, RawResponse, |
9 | }; | 9 | }; |
10 | use languageserver_types::NumberOrString; | 10 | use languageserver_types::NumberOrString; |
11 | use ra_analysis::{FileId, JobHandle, JobToken, LibraryData}; | 11 | use ra_analysis::{FileId, LibraryData}; |
12 | use rayon::{self, ThreadPool}; | 12 | use rayon::{self, ThreadPool}; |
13 | use rustc_hash::FxHashMap; | 13 | use rustc_hash::FxHashSet; |
14 | use serde::{de::DeserializeOwned, Serialize}; | 14 | use serde::{de::DeserializeOwned, Serialize}; |
15 | 15 | ||
16 | use crate::{ | 16 | use crate::{ |
@@ -47,7 +47,7 @@ pub fn main_loop( | |||
47 | info!("server initialized, serving requests"); | 47 | info!("server initialized, serving requests"); |
48 | let mut state = ServerWorldState::new(); | 48 | let mut state = ServerWorldState::new(); |
49 | 49 | ||
50 | let mut pending_requests = FxHashMap::default(); | 50 | let mut pending_requests = FxHashSet::default(); |
51 | let mut subs = Subscriptions::new(); | 51 | let mut subs = Subscriptions::new(); |
52 | let main_res = main_loop_inner( | 52 | let main_res = main_loop_inner( |
53 | internal_mode, | 53 | internal_mode, |
@@ -92,7 +92,7 @@ fn main_loop_inner( | |||
92 | fs_worker: Worker<PathBuf, (PathBuf, Vec<FileEvent>)>, | 92 | fs_worker: Worker<PathBuf, (PathBuf, Vec<FileEvent>)>, |
93 | ws_worker: Worker<PathBuf, Result<CargoWorkspace>>, | 93 | ws_worker: Worker<PathBuf, Result<CargoWorkspace>>, |
94 | state: &mut ServerWorldState, | 94 | state: &mut ServerWorldState, |
95 | pending_requests: &mut FxHashMap<u64, JobHandle>, | 95 | pending_requests: &mut FxHashSet<u64>, |
96 | subs: &mut Subscriptions, | 96 | subs: &mut Subscriptions, |
97 | ) -> Result<()> { | 97 | ) -> Result<()> { |
98 | let (libdata_sender, libdata_receiver) = unbounded(); | 98 | let (libdata_sender, libdata_receiver) = unbounded(); |
@@ -204,14 +204,13 @@ fn main_loop_inner( | |||
204 | fn on_task( | 204 | fn on_task( |
205 | task: Task, | 205 | task: Task, |
206 | msg_sender: &Sender<RawMessage>, | 206 | msg_sender: &Sender<RawMessage>, |
207 | pending_requests: &mut FxHashMap<u64, JobHandle>, | 207 | pending_requests: &mut FxHashSet<u64>, |
208 | ) { | 208 | ) { |
209 | match task { | 209 | match task { |
210 | Task::Respond(response) => { | 210 | Task::Respond(response) => { |
211 | if let Some(handle) = pending_requests.remove(&response.id) { | 211 | if pending_requests.remove(&response.id) { |
212 | assert!(handle.has_completed()); | 212 | msg_sender.send(RawMessage::Response(response)) |
213 | } | 213 | } |
214 | msg_sender.send(RawMessage::Response(response)) | ||
215 | } | 214 | } |
216 | Task::Notify(n) => msg_sender.send(RawMessage::Notification(n)), | 215 | Task::Notify(n) => msg_sender.send(RawMessage::Notification(n)), |
217 | } | 216 | } |
@@ -219,7 +218,7 @@ fn on_task( | |||
219 | 218 | ||
220 | fn on_request( | 219 | fn on_request( |
221 | world: &mut ServerWorldState, | 220 | world: &mut ServerWorldState, |
222 | pending_requests: &mut FxHashMap<u64, JobHandle>, | 221 | pending_requests: &mut FxHashSet<u64>, |
223 | pool: &ThreadPool, | 222 | pool: &ThreadPool, |
224 | sender: &Sender<Task>, | 223 | sender: &Sender<Task>, |
225 | req: RawRequest, | 224 | req: RawRequest, |
@@ -248,10 +247,13 @@ fn on_request( | |||
248 | .on::<req::CodeActionRequest>(handlers::handle_code_action)? | 247 | .on::<req::CodeActionRequest>(handlers::handle_code_action)? |
249 | .on::<req::FoldingRangeRequest>(handlers::handle_folding_range)? | 248 | .on::<req::FoldingRangeRequest>(handlers::handle_folding_range)? |
250 | .on::<req::SignatureHelpRequest>(handlers::handle_signature_help)? | 249 | .on::<req::SignatureHelpRequest>(handlers::handle_signature_help)? |
250 | .on::<req::PrepareRenameRequest>(handlers::handle_prepare_rename)? | ||
251 | .on::<req::Rename>(handlers::handle_rename)? | ||
252 | .on::<req::References>(handlers::handle_references)? | ||
251 | .finish(); | 253 | .finish(); |
252 | match req { | 254 | match req { |
253 | Ok((id, handle)) => { | 255 | Ok(id) => { |
254 | let inserted = pending_requests.insert(id, handle).is_none(); | 256 | let inserted = pending_requests.insert(id); |
255 | assert!(inserted, "duplicate request: {}", id); | 257 | assert!(inserted, "duplicate request: {}", id); |
256 | Ok(None) | 258 | Ok(None) |
257 | } | 259 | } |
@@ -262,7 +264,7 @@ fn on_request( | |||
262 | fn on_notification( | 264 | fn on_notification( |
263 | msg_sender: &Sender<RawMessage>, | 265 | msg_sender: &Sender<RawMessage>, |
264 | state: &mut ServerWorldState, | 266 | state: &mut ServerWorldState, |
265 | pending_requests: &mut FxHashMap<u64, JobHandle>, | 267 | pending_requests: &mut FxHashSet<u64>, |
266 | subs: &mut Subscriptions, | 268 | subs: &mut Subscriptions, |
267 | not: RawNotification, | 269 | not: RawNotification, |
268 | ) -> Result<()> { | 270 | ) -> Result<()> { |
@@ -274,9 +276,7 @@ fn on_notification( | |||
274 | panic!("string id's not supported: {:?}", id); | 276 | panic!("string id's not supported: {:?}", id); |
275 | } | 277 | } |
276 | }; | 278 | }; |
277 | if let Some(handle) = pending_requests.remove(&id) { | 279 | pending_requests.remove(&id); |
278 | handle.cancel(); | ||
279 | } | ||
280 | return Ok(()); | 280 | return Ok(()); |
281 | } | 281 | } |
282 | Err(not) => not, | 282 | Err(not) => not, |
@@ -333,7 +333,7 @@ fn on_notification( | |||
333 | 333 | ||
334 | struct PoolDispatcher<'a> { | 334 | struct PoolDispatcher<'a> { |
335 | req: Option<RawRequest>, | 335 | req: Option<RawRequest>, |
336 | res: Option<(u64, JobHandle)>, | 336 | res: Option<u64>, |
337 | pool: &'a ThreadPool, | 337 | pool: &'a ThreadPool, |
338 | world: &'a ServerWorldState, | 338 | world: &'a ServerWorldState, |
339 | sender: &'a Sender<Task>, | 339 | sender: &'a Sender<Task>, |
@@ -342,7 +342,7 @@ struct PoolDispatcher<'a> { | |||
342 | impl<'a> PoolDispatcher<'a> { | 342 | impl<'a> PoolDispatcher<'a> { |
343 | fn on<'b, R>( | 343 | fn on<'b, R>( |
344 | &'b mut self, | 344 | &'b mut self, |
345 | f: fn(ServerWorld, R::Params, JobToken) -> Result<R::Result>, | 345 | f: fn(ServerWorld, R::Params) -> Result<R::Result>, |
346 | ) -> Result<&'b mut Self> | 346 | ) -> Result<&'b mut Self> |
347 | where | 347 | where |
348 | R: req::Request, | 348 | R: req::Request, |
@@ -355,11 +355,10 @@ impl<'a> PoolDispatcher<'a> { | |||
355 | }; | 355 | }; |
356 | match req.cast::<R>() { | 356 | match req.cast::<R>() { |
357 | Ok((id, params)) => { | 357 | Ok((id, params)) => { |
358 | let (handle, token) = JobHandle::new(); | ||
359 | let world = self.world.snapshot(); | 358 | let world = self.world.snapshot(); |
360 | let sender = self.sender.clone(); | 359 | let sender = self.sender.clone(); |
361 | self.pool.spawn(move || { | 360 | self.pool.spawn(move || { |
362 | let resp = match f(world, params, token) { | 361 | let resp = match f(world, params) { |
363 | Ok(resp) => RawResponse::ok::<R>(id, &resp), | 362 | Ok(resp) => RawResponse::ok::<R>(id, &resp), |
364 | Err(e) => { | 363 | Err(e) => { |
365 | RawResponse::err(id, ErrorCode::InternalError as i32, e.to_string()) | 364 | RawResponse::err(id, ErrorCode::InternalError as i32, e.to_string()) |
@@ -368,14 +367,14 @@ impl<'a> PoolDispatcher<'a> { | |||
368 | let task = Task::Respond(resp); | 367 | let task = Task::Respond(resp); |
369 | sender.send(task); | 368 | sender.send(task); |
370 | }); | 369 | }); |
371 | self.res = Some((id, handle)); | 370 | self.res = Some(id); |
372 | } | 371 | } |
373 | Err(req) => self.req = Some(req), | 372 | Err(req) => self.req = Some(req), |
374 | } | 373 | } |
375 | Ok(self) | 374 | Ok(self) |
376 | } | 375 | } |
377 | 376 | ||
378 | fn finish(&mut self) -> ::std::result::Result<(u64, JobHandle), RawRequest> { | 377 | fn finish(&mut self) -> ::std::result::Result<u64, RawRequest> { |
379 | match (self.res.take(), self.req.take()) { | 378 | match (self.res.take(), self.req.take()) { |
380 | (Some(res), None) => Ok(res), | 379 | (Some(res), None) => Ok(res), |
381 | (None, Some(req)) => Err(req), | 380 | (None, Some(req)) => Err(req), |
diff --git a/crates/ra_lsp_server/src/path_map.rs b/crates/ra_lsp_server/src/path_map.rs index 585013acd..d32829382 100644 --- a/crates/ra_lsp_server/src/path_map.rs +++ b/crates/ra_lsp_server/src/path_map.rs | |||
@@ -1,9 +1,9 @@ | |||
1 | use std::path::{Component, Path, PathBuf}; | ||
2 | |||
1 | use im; | 3 | use im; |
2 | use ra_analysis::{FileId, FileResolver}; | 4 | use ra_analysis::{FileId, FileResolver}; |
3 | use relative_path::RelativePath; | 5 | use relative_path::RelativePath; |
4 | 6 | ||
5 | use std::path::{Component, Path, PathBuf}; | ||
6 | |||
7 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | 7 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
8 | pub enum Root { | 8 | pub enum Root { |
9 | Workspace, | 9 | Workspace, |
diff --git a/crates/ra_lsp_server/src/project_model.rs b/crates/ra_lsp_server/src/project_model.rs index cedb67bae..cabb336a3 100644 --- a/crates/ra_lsp_server/src/project_model.rs +++ b/crates/ra_lsp_server/src/project_model.rs | |||
@@ -1,9 +1,9 @@ | |||
1 | use std::path::{Path, PathBuf}; | ||
2 | |||
1 | use cargo_metadata::{metadata_run, CargoOpt}; | 3 | use cargo_metadata::{metadata_run, CargoOpt}; |
2 | use ra_syntax::SmolStr; | 4 | use ra_syntax::SmolStr; |
3 | use rustc_hash::{FxHashMap, FxHashSet}; | 5 | use rustc_hash::{FxHashMap, FxHashSet}; |
4 | 6 | ||
5 | use std::path::{Path, PathBuf}; | ||
6 | |||
7 | use crate::{ | 7 | use crate::{ |
8 | thread_watcher::{ThreadWatcher, Worker}, | 8 | thread_watcher::{ThreadWatcher, Worker}, |
9 | Result, | 9 | Result, |
diff --git a/crates/ra_lsp_server/src/req.rs b/crates/ra_lsp_server/src/req.rs index b76bfbcbc..6cd04d84c 100644 --- a/crates/ra_lsp_server/src/req.rs +++ b/crates/ra_lsp_server/src/req.rs | |||
@@ -7,7 +7,7 @@ pub use languageserver_types::{ | |||
7 | CompletionResponse, DocumentOnTypeFormattingParams, DocumentSymbolParams, | 7 | CompletionResponse, DocumentOnTypeFormattingParams, DocumentSymbolParams, |
8 | DocumentSymbolResponse, ExecuteCommandParams, Hover, InitializeResult, | 8 | DocumentSymbolResponse, ExecuteCommandParams, Hover, InitializeResult, |
9 | PublishDiagnosticsParams, SignatureHelp, TextDocumentEdit, TextDocumentPositionParams, | 9 | PublishDiagnosticsParams, SignatureHelp, TextDocumentEdit, TextDocumentPositionParams, |
10 | TextEdit, WorkspaceSymbolParams, | 10 | TextEdit, WorkspaceSymbolParams, ReferenceParams, |
11 | }; | 11 | }; |
12 | 12 | ||
13 | pub enum SyntaxTree {} | 13 | pub enum SyntaxTree {} |
diff --git a/crates/ra_lsp_server/src/thread_watcher.rs b/crates/ra_lsp_server/src/thread_watcher.rs index 6cc586456..5143c77ae 100644 --- a/crates/ra_lsp_server/src/thread_watcher.rs +++ b/crates/ra_lsp_server/src/thread_watcher.rs | |||
@@ -1,8 +1,9 @@ | |||
1 | use crate::Result; | 1 | use std::thread; |
2 | |||
2 | use crossbeam_channel::{bounded, unbounded, Receiver, Sender}; | 3 | use crossbeam_channel::{bounded, unbounded, Receiver, Sender}; |
3 | use drop_bomb::DropBomb; | 4 | use drop_bomb::DropBomb; |
4 | 5 | ||
5 | use std::thread; | 6 | use crate::Result; |
6 | 7 | ||
7 | pub struct Worker<I, O> { | 8 | pub struct Worker<I, O> { |
8 | pub inp: Sender<I>, | 9 | pub inp: Sender<I>, |