diff options
-rw-r--r-- | crates/ra_lsp_server/src/cargo_check.rs | 53 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop.rs | 8 | ||||
-rw-r--r-- | editors/code/src/commands/watch_status.ts | 43 | ||||
-rw-r--r-- | editors/code/src/extension.ts | 8 |
4 files changed, 103 insertions, 9 deletions
diff --git a/crates/ra_lsp_server/src/cargo_check.rs b/crates/ra_lsp_server/src/cargo_check.rs index 5a6a209eb..dd8c5d407 100644 --- a/crates/ra_lsp_server/src/cargo_check.rs +++ b/crates/ra_lsp_server/src/cargo_check.rs | |||
@@ -9,7 +9,8 @@ use cargo_metadata::{ | |||
9 | use crossbeam_channel::{select, unbounded, Receiver, RecvError, Sender, TryRecvError}; | 9 | use crossbeam_channel::{select, unbounded, Receiver, RecvError, Sender, TryRecvError}; |
10 | use lsp_types::{ | 10 | use lsp_types::{ |
11 | Diagnostic, DiagnosticRelatedInformation, DiagnosticSeverity, DiagnosticTag, Location, | 11 | Diagnostic, DiagnosticRelatedInformation, DiagnosticSeverity, DiagnosticTag, Location, |
12 | NumberOrString, Position, Range, Url, | 12 | NumberOrString, Position, Range, Url, WorkDoneProgress, WorkDoneProgressBegin, |
13 | WorkDoneProgressEnd, WorkDoneProgressReport, | ||
13 | }; | 14 | }; |
14 | use parking_lot::RwLock; | 15 | use parking_lot::RwLock; |
15 | use std::{ | 16 | use std::{ |
@@ -132,6 +133,7 @@ impl CheckWatcherSharedState { | |||
132 | #[derive(Debug)] | 133 | #[derive(Debug)] |
133 | pub enum CheckTask { | 134 | pub enum CheckTask { |
134 | Update(Url), | 135 | Update(Url), |
136 | Status(WorkDoneProgress), | ||
135 | } | 137 | } |
136 | 138 | ||
137 | pub enum CheckCommand { | 139 | pub enum CheckCommand { |
@@ -204,13 +206,38 @@ impl CheckWatcherState { | |||
204 | } | 206 | } |
205 | } | 207 | } |
206 | 208 | ||
207 | fn handle_message(&mut self, msg: cargo_metadata::Message, task_send: &Sender<CheckTask>) { | 209 | fn handle_message(&mut self, msg: CheckEvent, task_send: &Sender<CheckTask>) { |
208 | match msg { | 210 | match msg { |
209 | Message::CompilerArtifact(_msg) => { | 211 | CheckEvent::Begin => { |
210 | // TODO: Status display | 212 | task_send |
213 | .send(CheckTask::Status(WorkDoneProgress::Begin(WorkDoneProgressBegin { | ||
214 | title: "Running 'cargo check'".to_string(), | ||
215 | cancellable: Some(false), | ||
216 | message: None, | ||
217 | percentage: None, | ||
218 | }))) | ||
219 | .unwrap(); | ||
211 | } | 220 | } |
212 | 221 | ||
213 | Message::CompilerMessage(msg) => { | 222 | CheckEvent::End => { |
223 | task_send | ||
224 | .send(CheckTask::Status(WorkDoneProgress::End(WorkDoneProgressEnd { | ||
225 | message: None, | ||
226 | }))) | ||
227 | .unwrap(); | ||
228 | } | ||
229 | |||
230 | CheckEvent::Msg(Message::CompilerArtifact(msg)) => { | ||
231 | task_send | ||
232 | .send(CheckTask::Status(WorkDoneProgress::Report(WorkDoneProgressReport { | ||
233 | cancellable: Some(false), | ||
234 | message: Some(msg.target.name), | ||
235 | percentage: None, | ||
236 | }))) | ||
237 | .unwrap(); | ||
238 | } | ||
239 | |||
240 | CheckEvent::Msg(Message::CompilerMessage(msg)) => { | ||
214 | let map_result = | 241 | let map_result = |
215 | match map_rust_diagnostic_to_lsp(&msg.message, &self.workspace_root) { | 242 | match map_rust_diagnostic_to_lsp(&msg.message, &self.workspace_root) { |
216 | Some(map_result) => map_result, | 243 | Some(map_result) => map_result, |
@@ -232,8 +259,8 @@ impl CheckWatcherState { | |||
232 | task_send.send(CheckTask::Update(location.uri)).unwrap(); | 259 | task_send.send(CheckTask::Update(location.uri)).unwrap(); |
233 | } | 260 | } |
234 | 261 | ||
235 | Message::BuildScriptExecuted(_msg) => {} | 262 | CheckEvent::Msg(Message::BuildScriptExecuted(_msg)) => {} |
236 | Message::Unknown => {} | 263 | CheckEvent::Msg(Message::Unknown) => {} |
237 | } | 264 | } |
238 | } | 265 | } |
239 | } | 266 | } |
@@ -244,10 +271,16 @@ impl CheckWatcherState { | |||
244 | /// have to wrap sub-processes output handling in a thread and pass messages | 271 | /// have to wrap sub-processes output handling in a thread and pass messages |
245 | /// back over a channel. | 272 | /// back over a channel. |
246 | struct WatchThread { | 273 | struct WatchThread { |
247 | message_recv: Receiver<cargo_metadata::Message>, | 274 | message_recv: Receiver<CheckEvent>, |
248 | cancel_send: Sender<()>, | 275 | cancel_send: Sender<()>, |
249 | } | 276 | } |
250 | 277 | ||
278 | enum CheckEvent { | ||
279 | Begin, | ||
280 | Msg(cargo_metadata::Message), | ||
281 | End, | ||
282 | } | ||
283 | |||
251 | impl WatchThread { | 284 | impl WatchThread { |
252 | fn new( | 285 | fn new( |
253 | check_command: Option<&String>, | 286 | check_command: Option<&String>, |
@@ -273,6 +306,7 @@ impl WatchThread { | |||
273 | .spawn() | 306 | .spawn() |
274 | .expect("couldn't launch cargo"); | 307 | .expect("couldn't launch cargo"); |
275 | 308 | ||
309 | message_send.send(CheckEvent::Begin).unwrap(); | ||
276 | for message in cargo_metadata::parse_messages(command.stdout.take().unwrap()) { | 310 | for message in cargo_metadata::parse_messages(command.stdout.take().unwrap()) { |
277 | match cancel_recv.try_recv() { | 311 | match cancel_recv.try_recv() { |
278 | Ok(()) | Err(TryRecvError::Disconnected) => { | 312 | Ok(()) | Err(TryRecvError::Disconnected) => { |
@@ -281,8 +315,9 @@ impl WatchThread { | |||
281 | Err(TryRecvError::Empty) => (), | 315 | Err(TryRecvError::Empty) => (), |
282 | } | 316 | } |
283 | 317 | ||
284 | message_send.send(message.unwrap()).unwrap(); | 318 | message_send.send(CheckEvent::Msg(message.unwrap())).unwrap(); |
285 | } | 319 | } |
320 | message_send.send(CheckEvent::End).unwrap(); | ||
286 | }); | 321 | }); |
287 | WatchThread { message_recv, cancel_send } | 322 | WatchThread { message_recv, cancel_send } |
288 | } | 323 | } |
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 1f6175699..045e4660d 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs | |||
@@ -338,6 +338,14 @@ fn loop_turn( | |||
338 | task_sender.send(Task::Notify(not)).unwrap(); | 338 | task_sender.send(Task::Notify(not)).unwrap(); |
339 | } | 339 | } |
340 | } | 340 | } |
341 | CheckTask::Status(progress) => { | ||
342 | let params = req::ProgressParams { | ||
343 | token: req::ProgressToken::String("rustAnalyzer/cargoWatcher".to_string()), | ||
344 | value: req::ProgressParamsValue::WorkDone(progress), | ||
345 | }; | ||
346 | let not = notification_new::<req::Progress>(params); | ||
347 | task_sender.send(Task::Notify(not)).unwrap(); | ||
348 | } | ||
341 | }, | 349 | }, |
342 | Event::Msg(msg) => match msg { | 350 | Event::Msg(msg) => match msg { |
343 | Message::Request(req) => on_request( | 351 | Message::Request(req) => on_request( |
diff --git a/editors/code/src/commands/watch_status.ts b/editors/code/src/commands/watch_status.ts index 8d64394c7..2404c3f16 100644 --- a/editors/code/src/commands/watch_status.ts +++ b/editors/code/src/commands/watch_status.ts | |||
@@ -57,7 +57,50 @@ export class StatusDisplay implements vscode.Disposable { | |||
57 | this.statusBarItem.dispose(); | 57 | this.statusBarItem.dispose(); |
58 | } | 58 | } |
59 | 59 | ||
60 | public handleProgressNotification(params: ProgressParams) { | ||
61 | const { token, value } = params; | ||
62 | if (token !== "rustAnalyzer/cargoWatcher") { | ||
63 | return; | ||
64 | } | ||
65 | |||
66 | console.log("Got progress notification", token, value) | ||
67 | switch (value.kind) { | ||
68 | case "begin": | ||
69 | this.show(); | ||
70 | break; | ||
71 | |||
72 | case "report": | ||
73 | if (value.message) { | ||
74 | this.packageName = value.message; | ||
75 | } | ||
76 | break; | ||
77 | |||
78 | case "end": | ||
79 | this.hide(); | ||
80 | break; | ||
81 | } | ||
82 | } | ||
83 | |||
60 | private frame() { | 84 | private frame() { |
61 | return spinnerFrames[(this.i = ++this.i % spinnerFrames.length)]; | 85 | return spinnerFrames[(this.i = ++this.i % spinnerFrames.length)]; |
62 | } | 86 | } |
63 | } | 87 | } |
88 | |||
89 | // FIXME: Replace this once vscode-languageclient is updated to LSP 3.15 | ||
90 | interface ProgressParams { | ||
91 | token: string | ||
92 | value: WorkDoneProgress | ||
93 | } | ||
94 | |||
95 | enum WorkDoneProgressKind { | ||
96 | Begin = "begin", | ||
97 | Report = "report", | ||
98 | End = "end" | ||
99 | } | ||
100 | |||
101 | interface WorkDoneProgress { | ||
102 | kind: WorkDoneProgressKind, | ||
103 | message?: string | ||
104 | cancelable?: boolean | ||
105 | percentage?: string | ||
106 | } \ No newline at end of file | ||
diff --git a/editors/code/src/extension.ts b/editors/code/src/extension.ts index 72a4d4bf2..1507cb26e 100644 --- a/editors/code/src/extension.ts +++ b/editors/code/src/extension.ts | |||
@@ -8,6 +8,7 @@ import { SyntaxTreeContentProvider } from './commands/syntaxTree'; | |||
8 | import * as events from './events'; | 8 | import * as events from './events'; |
9 | import * as notifications from './notifications'; | 9 | import * as notifications from './notifications'; |
10 | import { Server } from './server'; | 10 | import { Server } from './server'; |
11 | import { StatusDisplay } from './commands/watch_status'; | ||
11 | 12 | ||
12 | export async function activate(context: vscode.ExtensionContext) { | 13 | export async function activate(context: vscode.ExtensionContext) { |
13 | function disposeOnDeactivation(disposable: vscode.Disposable) { | 14 | function disposeOnDeactivation(disposable: vscode.Disposable) { |
@@ -83,6 +84,9 @@ export async function activate(context: vscode.ExtensionContext) { | |||
83 | overrideCommand('type', commands.onEnter.handle); | 84 | overrideCommand('type', commands.onEnter.handle); |
84 | } | 85 | } |
85 | 86 | ||
87 | const watchStatus = new StatusDisplay(Server.config.cargoCheckOptions.command || 'check'); | ||
88 | disposeOnDeactivation(watchStatus); | ||
89 | |||
86 | // Notifications are events triggered by the language server | 90 | // Notifications are events triggered by the language server |
87 | const allNotifications: Iterable<[ | 91 | const allNotifications: Iterable<[ |
88 | string, | 92 | string, |
@@ -92,6 +96,10 @@ export async function activate(context: vscode.ExtensionContext) { | |||
92 | 'rust-analyzer/publishDecorations', | 96 | 'rust-analyzer/publishDecorations', |
93 | notifications.publishDecorations.handle, | 97 | notifications.publishDecorations.handle, |
94 | ], | 98 | ], |
99 | [ | ||
100 | '$/progress', | ||
101 | (params) => watchStatus.handleProgressNotification(params), | ||
102 | ] | ||
95 | ]; | 103 | ]; |
96 | const syntaxTreeContentProvider = new SyntaxTreeContentProvider(); | 104 | const syntaxTreeContentProvider = new SyntaxTreeContentProvider(); |
97 | const expandMacroContentProvider = new ExpandMacroContentProvider(); | 105 | const expandMacroContentProvider = new ExpandMacroContentProvider(); |