diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-12-29 12:57:24 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2019-12-29 12:57:24 +0000 |
commit | dc48f89581843248660ceb755bb20469ab6ac0c9 (patch) | |
tree | 05a7e47d1c68c250025be1ce6492f56c15353749 /crates/ra_lsp_server/src/main_loop.rs | |
parent | cdcb3d3833d3d5b37b2cd4dac91a6e9366f20aea (diff) | |
parent | 899dbebd02b41b12d89c9f485e85208b39b81932 (diff) |
Merge #2668
2668: In-server cargo check watching r=matklad a=kiljacken
Opening a draft now so people can follow the progress, and comment if they spot something stupid.
Things that need doing:
- [x] Running cargo check on save
- [x] Pipe through configuration options from client
- [x] Tests for parsing behavior
- [x] Remove existing cargo watch support from VSCode extension
- [x] Progress notification in VSCode extension using LSP 3.15 `$/progress` notification
- [ ] ~~Rework ra-ide diagnostics to support secondary messages~~
- [ ] ~~Make cargo-check watcher use ra-ide diagnostics~~
~~I'd love some input on whether to try to keep the status bar progress thingy for VSCode? It will require some plumbing, and maintaining yet another rust-analyzer specific LSP notification, which I'm not sure we want to.~~
Fixes #1894
Co-authored-by: Emil Lauridsen <[email protected]>
Diffstat (limited to 'crates/ra_lsp_server/src/main_loop.rs')
-rw-r--r-- | crates/ra_lsp_server/src/main_loop.rs | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index dda318e43..af1a487de 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs | |||
@@ -10,6 +10,7 @@ use std::{error::Error, fmt, panic, path::PathBuf, sync::Arc, time::Instant}; | |||
10 | use crossbeam_channel::{select, unbounded, RecvError, Sender}; | 10 | use crossbeam_channel::{select, unbounded, RecvError, Sender}; |
11 | use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestId, Response}; | 11 | use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestId, Response}; |
12 | use lsp_types::{ClientCapabilities, NumberOrString}; | 12 | use lsp_types::{ClientCapabilities, NumberOrString}; |
13 | use ra_cargo_watch::{CheckOptions, CheckTask}; | ||
13 | use ra_ide::{Canceled, FeatureFlags, FileId, LibraryData, SourceRootId}; | 14 | use ra_ide::{Canceled, FeatureFlags, FileId, LibraryData, SourceRootId}; |
14 | use ra_prof::profile; | 15 | use ra_prof::profile; |
15 | use ra_vfs::{VfsTask, Watch}; | 16 | use ra_vfs::{VfsTask, Watch}; |
@@ -126,6 +127,12 @@ pub fn main_loop( | |||
126 | .and_then(|it| it.line_folding_only) | 127 | .and_then(|it| it.line_folding_only) |
127 | .unwrap_or(false), | 128 | .unwrap_or(false), |
128 | max_inlay_hint_length: config.max_inlay_hint_length, | 129 | max_inlay_hint_length: config.max_inlay_hint_length, |
130 | cargo_watch: CheckOptions { | ||
131 | enable: config.cargo_watch_enable, | ||
132 | args: config.cargo_watch_args, | ||
133 | command: config.cargo_watch_command, | ||
134 | all_targets: config.cargo_watch_all_targets, | ||
135 | }, | ||
129 | } | 136 | } |
130 | }; | 137 | }; |
131 | 138 | ||
@@ -176,7 +183,11 @@ pub fn main_loop( | |||
176 | Ok(task) => Event::Vfs(task), | 183 | Ok(task) => Event::Vfs(task), |
177 | Err(RecvError) => Err("vfs died")?, | 184 | Err(RecvError) => Err("vfs died")?, |
178 | }, | 185 | }, |
179 | recv(libdata_receiver) -> data => Event::Lib(data.unwrap()) | 186 | recv(libdata_receiver) -> data => Event::Lib(data.unwrap()), |
187 | recv(world_state.check_watcher.task_recv) -> task => match task { | ||
188 | Ok(task) => Event::CheckWatcher(task), | ||
189 | Err(RecvError) => Err("check watcher died")?, | ||
190 | } | ||
180 | }; | 191 | }; |
181 | if let Event::Msg(Message::Request(req)) = &event { | 192 | if let Event::Msg(Message::Request(req)) = &event { |
182 | if connection.handle_shutdown(&req)? { | 193 | if connection.handle_shutdown(&req)? { |
@@ -222,6 +233,7 @@ enum Event { | |||
222 | Task(Task), | 233 | Task(Task), |
223 | Vfs(VfsTask), | 234 | Vfs(VfsTask), |
224 | Lib(LibraryData), | 235 | Lib(LibraryData), |
236 | CheckWatcher(CheckTask), | ||
225 | } | 237 | } |
226 | 238 | ||
227 | impl fmt::Debug for Event { | 239 | impl fmt::Debug for Event { |
@@ -259,6 +271,7 @@ impl fmt::Debug for Event { | |||
259 | Event::Task(it) => fmt::Debug::fmt(it, f), | 271 | Event::Task(it) => fmt::Debug::fmt(it, f), |
260 | Event::Vfs(it) => fmt::Debug::fmt(it, f), | 272 | Event::Vfs(it) => fmt::Debug::fmt(it, f), |
261 | Event::Lib(it) => fmt::Debug::fmt(it, f), | 273 | Event::Lib(it) => fmt::Debug::fmt(it, f), |
274 | Event::CheckWatcher(it) => fmt::Debug::fmt(it, f), | ||
262 | } | 275 | } |
263 | } | 276 | } |
264 | } | 277 | } |
@@ -318,6 +331,28 @@ fn loop_turn( | |||
318 | world_state.maybe_collect_garbage(); | 331 | world_state.maybe_collect_garbage(); |
319 | loop_state.in_flight_libraries -= 1; | 332 | loop_state.in_flight_libraries -= 1; |
320 | } | 333 | } |
334 | Event::CheckWatcher(task) => match task { | ||
335 | CheckTask::Update(uri) => { | ||
336 | // We manually send a diagnostic update when the watcher asks | ||
337 | // us to, to avoid the issue of having to change the file to | ||
338 | // receive updated diagnostics. | ||
339 | let path = uri.to_file_path().map_err(|()| format!("invalid uri: {}", uri))?; | ||
340 | if let Some(file_id) = world_state.vfs.read().path2file(&path) { | ||
341 | let params = | ||
342 | handlers::publish_diagnostics(&world_state.snapshot(), FileId(file_id.0))?; | ||
343 | let not = notification_new::<req::PublishDiagnostics>(params); | ||
344 | task_sender.send(Task::Notify(not)).unwrap(); | ||
345 | } | ||
346 | } | ||
347 | CheckTask::Status(progress) => { | ||
348 | let params = req::ProgressParams { | ||
349 | token: req::ProgressToken::String("rustAnalyzer/cargoWatcher".to_string()), | ||
350 | value: req::ProgressParamsValue::WorkDone(progress), | ||
351 | }; | ||
352 | let not = notification_new::<req::Progress>(params); | ||
353 | task_sender.send(Task::Notify(not)).unwrap(); | ||
354 | } | ||
355 | }, | ||
321 | Event::Msg(msg) => match msg { | 356 | Event::Msg(msg) => match msg { |
322 | Message::Request(req) => on_request( | 357 | Message::Request(req) => on_request( |
323 | world_state, | 358 | world_state, |
@@ -517,6 +552,13 @@ fn on_notification( | |||
517 | } | 552 | } |
518 | Err(not) => not, | 553 | Err(not) => not, |
519 | }; | 554 | }; |
555 | let not = match notification_cast::<req::DidSaveTextDocument>(not) { | ||
556 | Ok(_params) => { | ||
557 | state.check_watcher.update(); | ||
558 | return Ok(()); | ||
559 | } | ||
560 | Err(not) => not, | ||
561 | }; | ||
520 | let not = match notification_cast::<req::DidCloseTextDocument>(not) { | 562 | let not = match notification_cast::<req::DidCloseTextDocument>(not) { |
521 | Ok(params) => { | 563 | Ok(params) => { |
522 | let uri = params.text_document.uri; | 564 | let uri = params.text_document.uri; |