aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_lsp_server/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_lsp_server/src')
-rw-r--r--crates/ra_lsp_server/src/caps.rs20
-rw-r--r--crates/ra_lsp_server/src/cargo_target_spec.rs5
-rw-r--r--crates/ra_lsp_server/src/conv.rs59
-rw-r--r--crates/ra_lsp_server/src/main.rs26
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs55
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs75
-rw-r--r--crates/ra_lsp_server/src/main_loop/subscriptions.rs4
-rw-r--r--crates/ra_lsp_server/src/project_model/cargo_workspace.rs17
-rw-r--r--crates/ra_lsp_server/src/project_model/sysroot.rs9
-rw-r--r--crates/ra_lsp_server/src/server_world.rs28
10 files changed, 72 insertions, 226 deletions
diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs
index 39992788d..2af2b89fe 100644
--- a/crates/ra_lsp_server/src/caps.rs
+++ b/crates/ra_lsp_server/src/caps.rs
@@ -7,15 +7,13 @@ use lsp_types::{
7 7
8pub fn server_capabilities() -> ServerCapabilities { 8pub fn server_capabilities() -> ServerCapabilities {
9 ServerCapabilities { 9 ServerCapabilities {
10 text_document_sync: Some(TextDocumentSyncCapability::Options( 10 text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions {
11 TextDocumentSyncOptions { 11 open_close: Some(true),
12 open_close: Some(true), 12 change: Some(TextDocumentSyncKind::Full),
13 change: Some(TextDocumentSyncKind::Full), 13 will_save: None,
14 will_save: None, 14 will_save_wait_until: None,
15 will_save_wait_until: None, 15 save: None,
16 save: None, 16 })),
17 },
18 )),
19 hover_provider: Some(true), 17 hover_provider: Some(true),
20 completion_provider: Some(CompletionOptions { 18 completion_provider: Some(CompletionOptions {
21 resolve_provider: None, 19 resolve_provider: None,
@@ -32,9 +30,7 @@ pub fn server_capabilities() -> ServerCapabilities {
32 document_symbol_provider: Some(true), 30 document_symbol_provider: Some(true),
33 workspace_symbol_provider: Some(true), 31 workspace_symbol_provider: Some(true),
34 code_action_provider: Some(CodeActionProviderCapability::Simple(true)), 32 code_action_provider: Some(CodeActionProviderCapability::Simple(true)),
35 code_lens_provider: Some(CodeLensOptions { 33 code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(true) }),
36 resolve_provider: Some(true),
37 }),
38 document_formatting_provider: Some(true), 34 document_formatting_provider: Some(true),
39 document_range_formatting_provider: None, 35 document_range_formatting_provider: None,
40 document_on_type_formatting_provider: Some(DocumentOnTypeFormattingOptions { 36 document_on_type_formatting_provider: Some(DocumentOnTypeFormattingOptions {
diff --git a/crates/ra_lsp_server/src/cargo_target_spec.rs b/crates/ra_lsp_server/src/cargo_target_spec.rs
index db9496bbe..e011eab7c 100644
--- a/crates/ra_lsp_server/src/cargo_target_spec.rs
+++ b/crates/ra_lsp_server/src/cargo_target_spec.rs
@@ -64,10 +64,7 @@ impl CargoTargetSpec {
64 None => return Ok(None), 64 None => return Ok(None),
65 }; 65 };
66 let file_id = world.analysis().crate_root(crate_id)?; 66 let file_id = world.analysis().crate_root(crate_id)?;
67 let path = world 67 let path = world.vfs.read().file2path(ra_vfs::VfsFile(file_id.0.into()));
68 .vfs
69 .read()
70 .file2path(ra_vfs::VfsFile(file_id.0.into()));
71 let res = world.workspaces.iter().find_map(|ws| { 68 let res = world.workspaces.iter().find_map(|ws| {
72 let tgt = ws.cargo.target_by_root(&path)?; 69 let tgt = ws.cargo.target_by_root(&path)?;
73 let res = CargoTargetSpec { 70 let res = CargoTargetSpec {
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs
index 981385466..20077a48a 100644
--- a/crates/ra_lsp_server/src/conv.rs
+++ b/crates/ra_lsp_server/src/conv.rs
@@ -82,11 +82,8 @@ impl ConvWith for CompletionItem {
82 fn conv_with(mut self, ctx: &LineIndex) -> ::lsp_types::CompletionItem { 82 fn conv_with(mut self, ctx: &LineIndex) -> ::lsp_types::CompletionItem {
83 let atom_text_edit = AtomTextEdit::replace(self.source_range(), self.insert_text()); 83 let atom_text_edit = AtomTextEdit::replace(self.source_range(), self.insert_text());
84 let text_edit = (&atom_text_edit).conv_with(ctx); 84 let text_edit = (&atom_text_edit).conv_with(ctx);
85 let additional_text_edits = if let Some(edit) = self.take_text_edit() { 85 let additional_text_edits =
86 Some(edit.conv_with(ctx)) 86 if let Some(edit) = self.take_text_edit() { Some(edit.conv_with(ctx)) } else { None };
87 } else {
88 None
89 };
90 87
91 let mut res = lsp_types::CompletionItem { 88 let mut res = lsp_types::CompletionItem {
92 label: self.label().to_string(), 89 label: self.label().to_string(),
@@ -112,10 +109,7 @@ impl ConvWith for Position {
112 type Output = TextUnit; 109 type Output = TextUnit;
113 110
114 fn conv_with(self, line_index: &LineIndex) -> TextUnit { 111 fn conv_with(self, line_index: &LineIndex) -> TextUnit {
115 let line_col = LineCol { 112 let line_col = LineCol { line: self.line as u32, col_utf16: self.character as u32 };
116 line: self.line as u32,
117 col_utf16: self.character as u32,
118 };
119 line_index.offset(line_col) 113 line_index.offset(line_col)
120 } 114 }
121} 115}
@@ -135,10 +129,7 @@ impl ConvWith for TextRange {
135 type Output = Range; 129 type Output = Range;
136 130
137 fn conv_with(self, line_index: &LineIndex) -> Range { 131 fn conv_with(self, line_index: &LineIndex) -> Range {
138 Range::new( 132 Range::new(self.start().conv_with(line_index), self.end().conv_with(line_index))
139 self.start().conv_with(line_index),
140 self.end().conv_with(line_index),
141 )
142 } 133 }
143} 134}
144 135
@@ -147,10 +138,7 @@ impl ConvWith for Range {
147 type Output = TextRange; 138 type Output = TextRange;
148 139
149 fn conv_with(self, line_index: &LineIndex) -> TextRange { 140 fn conv_with(self, line_index: &LineIndex) -> TextRange {
150 TextRange::from_to( 141 TextRange::from_to(self.start.conv_with(line_index), self.end.conv_with(line_index))
151 self.start.conv_with(line_index),
152 self.end.conv_with(line_index),
153 )
154 } 142 }
155} 143}
156 144
@@ -303,11 +291,7 @@ impl TryConvWith for SourceChange {
303 changes: None, 291 changes: None,
304 document_changes: Some(DocumentChanges::Operations(document_changes)), 292 document_changes: Some(DocumentChanges::Operations(document_changes)),
305 }; 293 };
306 Ok(req::SourceChange { 294 Ok(req::SourceChange { label: self.label, workspace_edit, cursor_position })
307 label: self.label,
308 workspace_edit,
309 cursor_position,
310 })
311 } 295 }
312} 296}
313 297
@@ -320,16 +304,8 @@ impl TryConvWith for SourceFileEdit {
320 version: None, 304 version: None,
321 }; 305 };
322 let line_index = world.analysis().file_line_index(self.file_id); 306 let line_index = world.analysis().file_line_index(self.file_id);
323 let edits = self 307 let edits = self.edit.as_atoms().iter().map_conv_with(&line_index).collect();
324 .edit 308 Ok(TextDocumentEdit { text_document, edits })
325 .as_atoms()
326 .iter()
327 .map_conv_with(&line_index)
328 .collect();
329 Ok(TextDocumentEdit {
330 text_document,
331 edits,
332 })
333 } 309 }
334} 310}
335 311
@@ -342,18 +318,10 @@ impl TryConvWith for FileSystemEdit {
342 let uri = world.path_to_uri(source_root, &path)?; 318 let uri = world.path_to_uri(source_root, &path)?;
343 ResourceOp::Create(CreateFile { uri, options: None }) 319 ResourceOp::Create(CreateFile { uri, options: None })
344 } 320 }
345 FileSystemEdit::MoveFile { 321 FileSystemEdit::MoveFile { src, dst_source_root, dst_path } => {
346 src,
347 dst_source_root,
348 dst_path,
349 } => {
350 let old_uri = world.file_id_to_uri(src)?; 322 let old_uri = world.file_id_to_uri(src)?;
351 let new_uri = world.path_to_uri(dst_source_root, &dst_path)?; 323 let new_uri = world.path_to_uri(dst_source_root, &dst_path)?;
352 ResourceOp::Rename(RenameFile { 324 ResourceOp::Rename(RenameFile { old_uri, new_uri, options: None })
353 old_uri,
354 new_uri,
355 options: None,
356 })
357 } 325 }
358 }; 326 };
359 Ok(res) 327 Ok(res)
@@ -381,11 +349,8 @@ pub fn to_location_link(
381 349
382 let target_range = target.info.full_range().conv_with(&tgt_line_index); 350 let target_range = target.info.full_range().conv_with(&tgt_line_index);
383 351
384 let target_selection_range = target 352 let target_selection_range =
385 .info 353 target.info.focus_range().map(|it| it.conv_with(&tgt_line_index)).unwrap_or(target_range);
386 .focus_range()
387 .map(|it| it.conv_with(&tgt_line_index))
388 .unwrap_or(target_range);
389 354
390 let res = LocationLink { 355 let res = LocationLink {
391 origin_selection_range: Some(target.range.conv_with(line_index)), 356 origin_selection_range: Some(target.range.conv_with(line_index)),
diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs
index 33aa30d70..03f83c7be 100644
--- a/crates/ra_lsp_server/src/main.rs
+++ b/crates/ra_lsp_server/src/main.rs
@@ -36,23 +36,15 @@ struct InitializationOptions {
36fn main_inner() -> Result<()> { 36fn main_inner() -> Result<()> {
37 let (receiver, sender, threads) = stdio_transport(); 37 let (receiver, sender, threads) = stdio_transport();
38 let cwd = ::std::env::current_dir()?; 38 let cwd = ::std::env::current_dir()?;
39 run_server( 39 run_server(ra_lsp_server::server_capabilities(), receiver, sender, |params, r, s| {
40 ra_lsp_server::server_capabilities(), 40 let root = params.root_uri.and_then(|it| it.to_file_path().ok()).unwrap_or(cwd);
41 receiver, 41 let supports_decorations = params
42 sender, 42 .initialization_options
43 |params, r, s| { 43 .and_then(|v| InitializationOptions::deserialize(v).ok())
44 let root = params 44 .and_then(|it| it.publish_decorations)
45 .root_uri 45 == Some(true);
46 .and_then(|it| it.to_file_path().ok()) 46 ra_lsp_server::main_loop(false, root, supports_decorations, r, s)
47 .unwrap_or(cwd); 47 })?;
48 let supports_decorations = params
49 .initialization_options
50 .and_then(|v| InitializationOptions::deserialize(v).ok())
51 .and_then(|it| it.publish_decorations)
52 == Some(true);
53 ra_lsp_server::main_loop(false, root, supports_decorations, r, s)
54 },
55 )?;
56 log::info!("shutting down IO..."); 48 log::info!("shutting down IO...");
57 threads.join()?; 49 threads.join()?;
58 log::info!("... IO is down"); 50 log::info!("... IO is down");
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index 26b6fe54a..a51299851 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -25,10 +25,7 @@ use crate::{
25}; 25};
26 26
27#[derive(Debug, Fail)] 27#[derive(Debug, Fail)]
28#[fail( 28#[fail(display = "Language Server request failed with {}. ({})", code, message)]
29 display = "Language Server request failed with {}. ({})",
30 code, message
31)]
32pub struct LspError { 29pub struct LspError {
33 pub code: i32, 30 pub code: i32,
34 pub message: String, 31 pub message: String,
@@ -69,9 +66,7 @@ pub fn main_loop(
69 } 66 }
70 }; 67 };
71 ws_worker.shutdown(); 68 ws_worker.shutdown();
72 ws_watcher 69 ws_watcher.shutdown().map_err(|_| format_err!("ws watcher died"))?;
73 .shutdown()
74 .map_err(|_| format_err!("ws watcher died"))?;
75 let mut state = ServerWorldState::new(ws_root.clone(), workspaces); 70 let mut state = ServerWorldState::new(ws_root.clone(), workspaces);
76 71
77 log::info!("server initialized, serving requests"); 72 log::info!("server initialized, serving requests");
@@ -92,9 +87,7 @@ pub fn main_loop(
92 ); 87 );
93 88
94 log::info!("waiting for tasks to finish..."); 89 log::info!("waiting for tasks to finish...");
95 task_receiver 90 task_receiver.into_iter().for_each(|task| on_task(task, msg_sender, &mut pending_requests));
96 .into_iter()
97 .for_each(|task| on_task(task, msg_sender, &mut pending_requests));
98 log::info!("...tasks have finished"); 91 log::info!("...tasks have finished");
99 log::info!("joining threadpool..."); 92 log::info!("joining threadpool...");
100 drop(pool); 93 drop(pool);
@@ -119,9 +112,7 @@ enum Event {
119impl fmt::Debug for Event { 112impl fmt::Debug for Event {
120 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 113 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
121 let debug_verbose_not = |not: &RawNotification, f: &mut fmt::Formatter| { 114 let debug_verbose_not = |not: &RawNotification, f: &mut fmt::Formatter| {
122 f.debug_struct("RawNotification") 115 f.debug_struct("RawNotification").field("method", &not.method).finish()
123 .field("method", &not.method)
124 .finish()
125 }; 116 };
126 117
127 match self { 118 match self {
@@ -287,13 +278,7 @@ fn on_request(
287 sender: &Sender<Task>, 278 sender: &Sender<Task>,
288 req: RawRequest, 279 req: RawRequest,
289) -> Result<Option<RawRequest>> { 280) -> Result<Option<RawRequest>> {
290 let mut pool_dispatcher = PoolDispatcher { 281 let mut pool_dispatcher = PoolDispatcher { req: Some(req), res: None, pool, world, sender };
291 req: Some(req),
292 res: None,
293 pool,
294 world,
295 sender,
296 };
297 let req = pool_dispatcher 282 let req = pool_dispatcher
298 .on::<req::AnalyzerStatus>(handlers::handle_analyzer_status)? 283 .on::<req::AnalyzerStatus>(handlers::handle_analyzer_status)?
299 .on::<req::SyntaxTree>(handlers::handle_syntax_tree)? 284 .on::<req::SyntaxTree>(handlers::handle_syntax_tree)?
@@ -362,13 +347,9 @@ fn on_notification(
362 let not = match not.cast::<req::DidOpenTextDocument>() { 347 let not = match not.cast::<req::DidOpenTextDocument>() {
363 Ok(params) => { 348 Ok(params) => {
364 let uri = params.text_document.uri; 349 let uri = params.text_document.uri;
365 let path = uri 350 let path = uri.to_file_path().map_err(|()| format_err!("invalid uri: {}", uri))?;
366 .to_file_path() 351 if let Some(file_id) =
367 .map_err(|()| format_err!("invalid uri: {}", uri))?; 352 state.vfs.write().add_file_overlay(&path, params.text_document.text)
368 if let Some(file_id) = state
369 .vfs
370 .write()
371 .add_file_overlay(&path, params.text_document.text)
372 { 353 {
373 subs.add_sub(FileId(file_id.0.into())); 354 subs.add_sub(FileId(file_id.0.into()));
374 } 355 }
@@ -379,14 +360,9 @@ fn on_notification(
379 let not = match not.cast::<req::DidChangeTextDocument>() { 360 let not = match not.cast::<req::DidChangeTextDocument>() {
380 Ok(mut params) => { 361 Ok(mut params) => {
381 let uri = params.text_document.uri; 362 let uri = params.text_document.uri;
382 let path = uri 363 let path = uri.to_file_path().map_err(|()| format_err!("invalid uri: {}", uri))?;
383 .to_file_path() 364 let text =
384 .map_err(|()| format_err!("invalid uri: {}", uri))?; 365 params.content_changes.pop().ok_or_else(|| format_err!("empty changes"))?.text;
385 let text = params
386 .content_changes
387 .pop()
388 .ok_or_else(|| format_err!("empty changes"))?
389 .text;
390 state.vfs.write().change_file_overlay(path.as_path(), text); 366 state.vfs.write().change_file_overlay(path.as_path(), text);
391 return Ok(()); 367 return Ok(());
392 } 368 }
@@ -395,16 +371,11 @@ fn on_notification(
395 let not = match not.cast::<req::DidCloseTextDocument>() { 371 let not = match not.cast::<req::DidCloseTextDocument>() {
396 Ok(params) => { 372 Ok(params) => {
397 let uri = params.text_document.uri; 373 let uri = params.text_document.uri;
398 let path = uri 374 let path = uri.to_file_path().map_err(|()| format_err!("invalid uri: {}", uri))?;
399 .to_file_path()
400 .map_err(|()| format_err!("invalid uri: {}", uri))?;
401 if let Some(file_id) = state.vfs.write().remove_file_overlay(path.as_path()) { 375 if let Some(file_id) = state.vfs.write().remove_file_overlay(path.as_path()) {
402 subs.remove_sub(FileId(file_id.0.into())); 376 subs.remove_sub(FileId(file_id.0.into()));
403 } 377 }
404 let params = req::PublishDiagnosticsParams { 378 let params = req::PublishDiagnosticsParams { uri, diagnostics: Vec::new() };
405 uri,
406 diagnostics: Vec::new(),
407 };
408 let not = RawNotification::new::<req::PublishDiagnostics>(&params); 379 let not = RawNotification::new::<req::PublishDiagnostics>(&params);
409 msg_sender.send(RawMessage::Notification(not)).unwrap(); 380 msg_sender.send(RawMessage::Notification(not)).unwrap();
410 return Ok(()); 381 return Ok(());
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index aa55d1255..0cdb39c32 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -46,12 +46,7 @@ pub fn handle_extend_selection(
46 .into_iter() 46 .into_iter()
47 .map_conv_with(&line_index) 47 .map_conv_with(&line_index)
48 .map(|range| FileRange { file_id, range }) 48 .map(|range| FileRange { file_id, range })
49 .map(|frange| { 49 .map(|frange| world.analysis().extend_selection(frange).map(|it| it.conv_with(&line_index)))
50 world
51 .analysis()
52 .extend_selection(frange)
53 .map(|it| it.conv_with(&line_index))
54 })
55 .collect::<Cancelable<Vec<_>>>()?; 50 .collect::<Cancelable<Vec<_>>>()?;
56 Ok(req::ExtendSelectionResult { selections }) 51 Ok(req::ExtendSelectionResult { selections })
57} 52}
@@ -67,10 +62,7 @@ pub fn handle_find_matching_brace(
67 .into_iter() 62 .into_iter()
68 .map_conv_with(&line_index) 63 .map_conv_with(&line_index)
69 .map(|offset| { 64 .map(|offset| {
70 world 65 world.analysis().matching_brace(FilePosition { file_id, offset }).unwrap_or(offset)
71 .analysis()
72 .matching_brace(FilePosition { file_id, offset })
73 .unwrap_or(offset)
74 }) 66 })
75 .map_conv_with(&line_index) 67 .map_conv_with(&line_index)
76 .collect(); 68 .collect();
@@ -171,11 +163,7 @@ pub fn handle_workspace_symbol(
171 let all_symbols = params.query.contains('#'); 163 let all_symbols = params.query.contains('#');
172 let libs = params.query.contains('*'); 164 let libs = params.query.contains('*');
173 let query = { 165 let query = {
174 let query: String = params 166 let query: String = params.query.chars().filter(|&c| c != '#' && c != '*').collect();
175 .query
176 .chars()
177 .filter(|&c| c != '#' && c != '*')
178 .collect();
179 let mut q = Query::new(query); 167 let mut q = Query::new(query);
180 if !all_symbols { 168 if !all_symbols {
181 q.only_types(); 169 q.only_types();
@@ -367,10 +355,7 @@ pub fn handle_completion(
367 Some(items) => items, 355 Some(items) => items,
368 }; 356 };
369 let line_index = world.analysis().file_line_index(position.file_id); 357 let line_index = world.analysis().file_line_index(position.file_id);
370 let items = items 358 let items = items.into_iter().map(|item| item.conv_with(&line_index)).collect();
371 .into_iter()
372 .map(|item| item.conv_with(&line_index))
373 .collect();
374 359
375 Ok(Some(req::CompletionResponse::Array(items))) 360 Ok(Some(req::CompletionResponse::Array(items)))
376} 361}
@@ -496,9 +481,8 @@ pub fn handle_rename(world: ServerWorld, params: RenameParams) -> Result<Option<
496 .into()); 481 .into());
497 } 482 }
498 483
499 let optional_change = world 484 let optional_change =
500 .analysis() 485 world.analysis().rename(FilePosition { file_id, offset }, &*params.new_name)?;
501 .rename(FilePosition { file_id, offset }, &*params.new_name)?;
502 let change = match optional_change { 486 let change = match optional_change {
503 None => return Ok(None), 487 None => return Ok(None),
504 Some(it) => it, 488 Some(it) => it,
@@ -517,14 +501,10 @@ pub fn handle_references(
517 let line_index = world.analysis().file_line_index(file_id); 501 let line_index = world.analysis().file_line_index(file_id);
518 let offset = params.position.conv_with(&line_index); 502 let offset = params.position.conv_with(&line_index);
519 503
520 let refs = world 504 let refs = world.analysis().find_all_refs(FilePosition { file_id, offset })?;
521 .analysis()
522 .find_all_refs(FilePosition { file_id, offset })?;
523 505
524 Ok(Some( 506 Ok(Some(
525 refs.into_iter() 507 refs.into_iter().filter_map(|r| to_location(r.0, r.1, &world, &line_index).ok()).collect(),
526 .filter_map(|r| to_location(r.0, r.1, &world, &line_index).ok())
527 .collect(),
528 )) 508 ))
529} 509}
530 510
@@ -540,9 +520,7 @@ pub fn handle_formatting(
540 520
541 use std::process; 521 use std::process;
542 let mut rustfmt = process::Command::new("rustfmt"); 522 let mut rustfmt = process::Command::new("rustfmt");
543 rustfmt 523 rustfmt.stdin(process::Stdio::piped()).stdout(process::Stdio::piped());
544 .stdin(process::Stdio::piped())
545 .stdout(process::Stdio::piped());
546 524
547 if let Ok(path) = params.text_document.uri.to_file_path() { 525 if let Ok(path) = params.text_document.uri.to_file_path() {
548 if let Some(parent) = path.parent() { 526 if let Some(parent) = path.parent() {
@@ -582,10 +560,7 @@ pub fn handle_code_action(
582 let line_index = world.analysis().file_line_index(file_id); 560 let line_index = world.analysis().file_line_index(file_id);
583 let range = params.range.conv_with(&line_index); 561 let range = params.range.conv_with(&line_index);
584 562
585 let assists = world 563 let assists = world.analysis().assists(FileRange { file_id, range })?.into_iter();
586 .analysis()
587 .assists(FileRange { file_id, range })?
588 .into_iter();
589 let fixes = world 564 let fixes = world
590 .analysis() 565 .analysis()
591 .diagnostics(file_id)? 566 .diagnostics(file_id)?
@@ -720,18 +695,11 @@ pub fn handle_code_lens_resolve(world: ServerWorld, code_lens: CodeLens) -> Resu
720 to_value(locations).unwrap(), 695 to_value(locations).unwrap(),
721 ]), 696 ]),
722 }; 697 };
723 Ok(CodeLens { 698 Ok(CodeLens { range: code_lens.range, command: Some(cmd), data: None })
724 range: code_lens.range,
725 command: Some(cmd),
726 data: None,
727 })
728 } 699 }
729 None => Ok(CodeLens { 700 None => Ok(CodeLens {
730 range: code_lens.range, 701 range: code_lens.range,
731 command: Some(Command { 702 command: Some(Command { title: "Error".into(), ..Default::default() }),
732 title: "Error".into(),
733 ..Default::default()
734 }),
735 data: None, 703 data: None,
736 }), 704 }),
737 } 705 }
@@ -744,16 +712,11 @@ pub fn handle_document_highlight(
744 let file_id = params.text_document.try_conv_with(&world)?; 712 let file_id = params.text_document.try_conv_with(&world)?;
745 let line_index = world.analysis().file_line_index(file_id); 713 let line_index = world.analysis().file_line_index(file_id);
746 714
747 let refs = world 715 let refs = world.analysis().find_all_refs(params.try_conv_with(&world)?)?;
748 .analysis()
749 .find_all_refs(params.try_conv_with(&world)?)?;
750 716
751 Ok(Some( 717 Ok(Some(
752 refs.into_iter() 718 refs.into_iter()
753 .map(|r| DocumentHighlight { 719 .map(|r| DocumentHighlight { range: r.1.conv_with(&line_index), kind: None })
754 range: r.1.conv_with(&line_index),
755 kind: None,
756 })
757 .collect(), 720 .collect(),
758 )) 721 ))
759} 722}
@@ -785,10 +748,7 @@ pub fn publish_decorations(
785 file_id: FileId, 748 file_id: FileId,
786) -> Result<req::PublishDecorationsParams> { 749) -> Result<req::PublishDecorationsParams> {
787 let uri = world.file_id_to_uri(file_id)?; 750 let uri = world.file_id_to_uri(file_id)?;
788 Ok(req::PublishDecorationsParams { 751 Ok(req::PublishDecorationsParams { uri, decorations: highlight(&world, file_id)? })
789 uri,
790 decorations: highlight(&world, file_id)?,
791 })
792} 752}
793 753
794fn highlight(world: &ServerWorld, file_id: FileId) -> Result<Vec<Decoration>> { 754fn highlight(world: &ServerWorld, file_id: FileId) -> Result<Vec<Decoration>> {
@@ -797,10 +757,7 @@ fn highlight(world: &ServerWorld, file_id: FileId) -> Result<Vec<Decoration>> {
797 .analysis() 757 .analysis()
798 .highlight(file_id)? 758 .highlight(file_id)?
799 .into_iter() 759 .into_iter()
800 .map(|h| Decoration { 760 .map(|h| Decoration { range: h.range.conv_with(&line_index), tag: h.tag })
801 range: h.range.conv_with(&line_index),
802 tag: h.tag,
803 })
804 .collect(); 761 .collect();
805 Ok(res) 762 Ok(res)
806} 763}
diff --git a/crates/ra_lsp_server/src/main_loop/subscriptions.rs b/crates/ra_lsp_server/src/main_loop/subscriptions.rs
index a83e01557..11bd952d9 100644
--- a/crates/ra_lsp_server/src/main_loop/subscriptions.rs
+++ b/crates/ra_lsp_server/src/main_loop/subscriptions.rs
@@ -7,9 +7,7 @@ pub struct Subscriptions {
7 7
8impl Subscriptions { 8impl Subscriptions {
9 pub fn new() -> Subscriptions { 9 pub fn new() -> Subscriptions {
10 Subscriptions { 10 Subscriptions { subs: FxHashSet::default() }
11 subs: FxHashSet::default(),
12 }
13 } 11 }
14 pub fn add_sub(&mut self, file_id: FileId) { 12 pub fn add_sub(&mut self, file_id: FileId) {
15 self.subs.insert(file_id); 13 self.subs.insert(file_id);
diff --git a/crates/ra_lsp_server/src/project_model/cargo_workspace.rs b/crates/ra_lsp_server/src/project_model/cargo_workspace.rs
index 8cf99d586..3b76389d2 100644
--- a/crates/ra_lsp_server/src/project_model/cargo_workspace.rs
+++ b/crates/ra_lsp_server/src/project_model/cargo_workspace.rs
@@ -118,14 +118,11 @@ impl Target {
118impl CargoWorkspace { 118impl CargoWorkspace {
119 pub fn from_cargo_metadata(cargo_toml: &Path) -> Result<CargoWorkspace> { 119 pub fn from_cargo_metadata(cargo_toml: &Path) -> Result<CargoWorkspace> {
120 let mut meta = MetadataCommand::new(); 120 let mut meta = MetadataCommand::new();
121 meta.manifest_path(cargo_toml) 121 meta.manifest_path(cargo_toml).features(CargoOpt::AllFeatures);
122 .features(CargoOpt::AllFeatures);
123 if let Some(parent) = cargo_toml.parent() { 122 if let Some(parent) = cargo_toml.parent() {
124 meta.current_dir(parent); 123 meta.current_dir(parent);
125 } 124 }
126 let meta = meta 125 let meta = meta.exec().map_err(|e| format_err!("cargo metadata failed: {}", e))?;
127 .exec()
128 .map_err(|e| format_err!("cargo metadata failed: {}", e))?;
129 let mut pkg_by_id = FxHashMap::default(); 126 let mut pkg_by_id = FxHashMap::default();
130 let mut packages = Arena::default(); 127 let mut packages = Arena::default();
131 let mut targets = Arena::default(); 128 let mut targets = Arena::default();
@@ -157,10 +154,8 @@ impl CargoWorkspace {
157 for node in resolve.nodes { 154 for node in resolve.nodes {
158 let source = pkg_by_id[&node.id]; 155 let source = pkg_by_id[&node.id];
159 for dep_node in node.deps { 156 for dep_node in node.deps {
160 let dep = PackageDependency { 157 let dep =
161 name: dep_node.name.into(), 158 PackageDependency { name: dep_node.name.into(), pkg: pkg_by_id[&dep_node.pkg] };
162 pkg: pkg_by_id[&dep_node.pkg],
163 };
164 packages[source].dependencies.push(dep); 159 packages[source].dependencies.push(dep);
165 } 160 }
166 } 161 }
@@ -171,8 +166,6 @@ impl CargoWorkspace {
171 self.packages.iter().map(|(id, _pkg)| id) 166 self.packages.iter().map(|(id, _pkg)| id)
172 } 167 }
173 pub fn target_by_root(&self, root: &Path) -> Option<Target> { 168 pub fn target_by_root(&self, root: &Path) -> Option<Target> {
174 self.packages() 169 self.packages().filter_map(|pkg| pkg.targets(self).find(|it| it.root(self) == root)).next()
175 .filter_map(|pkg| pkg.targets(self).find(|it| it.root(self) == root))
176 .next()
177 } 170 }
178} 171}
diff --git a/crates/ra_lsp_server/src/project_model/sysroot.rs b/crates/ra_lsp_server/src/project_model/sysroot.rs
index fb4685671..49210ac7a 100644
--- a/crates/ra_lsp_server/src/project_model/sysroot.rs
+++ b/crates/ra_lsp_server/src/project_model/sysroot.rs
@@ -53,9 +53,7 @@ impl Sysroot {
53 ); 53 );
54 } 54 }
55 55
56 let mut sysroot = Sysroot { 56 let mut sysroot = Sysroot { crates: Arena::default() };
57 crates: Arena::default(),
58 };
59 for name in SYSROOT_CRATES.trim().lines() { 57 for name in SYSROOT_CRATES.trim().lines() {
60 let root = src.join(format!("lib{}", name)).join("lib.rs"); 58 let root = src.join(format!("lib{}", name)).join("lib.rs");
61 if root.exists() { 59 if root.exists() {
@@ -77,10 +75,7 @@ impl Sysroot {
77 } 75 }
78 76
79 fn by_name(&self, name: &str) -> Option<SysrootCrate> { 77 fn by_name(&self, name: &str) -> Option<SysrootCrate> {
80 self.crates 78 self.crates.iter().find(|(_id, data)| data.name == name).map(|(id, _data)| id)
81 .iter()
82 .find(|(_id, data)| data.name == name)
83 .map(|(id, _data)| id)
84 } 79 }
85} 80}
86 81
diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs
index c2167c5d8..02f2a37a8 100644
--- a/crates/ra_lsp_server/src/server_world.rs
+++ b/crates/ra_lsp_server/src/server_world.rs
@@ -80,10 +80,7 @@ impl ServerWorldState {
80 } 80 }
81 } 81 }
82 82
83 let libstd = ws 83 let libstd = ws.sysroot.std().and_then(|it| sysroot_crates.get(&it).map(|&it| it));
84 .sysroot
85 .std()
86 .and_then(|it| sysroot_crates.get(&it).map(|&it| it));
87 84
88 let mut pkg_to_lib_crate = FxHashMap::default(); 85 let mut pkg_to_lib_crate = FxHashMap::default();
89 let mut pkg_crates = FxHashMap::default(); 86 let mut pkg_crates = FxHashMap::default();
@@ -99,10 +96,7 @@ impl ServerWorldState {
99 lib_tgt = Some(crate_id); 96 lib_tgt = Some(crate_id);
100 pkg_to_lib_crate.insert(pkg, crate_id); 97 pkg_to_lib_crate.insert(pkg, crate_id);
101 } 98 }
102 pkg_crates 99 pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id);
103 .entry(pkg)
104 .or_insert_with(Vec::new)
105 .push(crate_id);
106 } 100 }
107 } 101 }
108 102
@@ -192,18 +186,8 @@ impl ServerWorldState {
192 libs.push((SourceRootId(root.0.into()), files)); 186 libs.push((SourceRootId(root.0.into()), files));
193 } 187 }
194 } 188 }
195 VfsChange::AddFile { 189 VfsChange::AddFile { root, file, path, text } => {
196 root, 190 change.add_file(SourceRootId(root.0.into()), FileId(file.0.into()), path, text);
197 file,
198 path,
199 text,
200 } => {
201 change.add_file(
202 SourceRootId(root.0.into()),
203 FileId(file.0.into()),
204 path,
205 text,
206 );
207 } 191 }
208 VfsChange::RemoveFile { root, file, path } => { 192 VfsChange::RemoveFile { root, file, path } => {
209 change.remove_file(SourceRootId(root.0.into()), FileId(file.0.into()), path) 193 change.remove_file(SourceRootId(root.0.into()), FileId(file.0.into()), path)
@@ -247,9 +231,7 @@ impl ServerWorld {
247 } 231 }
248 232
249 pub fn uri_to_file_id(&self, uri: &Url) -> Result<FileId> { 233 pub fn uri_to_file_id(&self, uri: &Url) -> Result<FileId> {
250 let path = uri 234 let path = uri.to_file_path().map_err(|()| format_err!("invalid uri: {}", uri))?;
251 .to_file_path()
252 .map_err(|()| format_err!("invalid uri: {}", uri))?;
253 let file = self 235 let file = self
254 .vfs 236 .vfs
255 .read() 237 .read()