aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_lsp_server/src/cargo_check.rs53
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs8
-rw-r--r--editors/code/src/commands/watch_status.ts43
-rw-r--r--editors/code/src/extension.ts8
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::{
9use crossbeam_channel::{select, unbounded, Receiver, RecvError, Sender, TryRecvError}; 9use crossbeam_channel::{select, unbounded, Receiver, RecvError, Sender, TryRecvError};
10use lsp_types::{ 10use 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};
14use parking_lot::RwLock; 15use parking_lot::RwLock;
15use std::{ 16use std::{
@@ -132,6 +133,7 @@ impl CheckWatcherSharedState {
132#[derive(Debug)] 133#[derive(Debug)]
133pub enum CheckTask { 134pub enum CheckTask {
134 Update(Url), 135 Update(Url),
136 Status(WorkDoneProgress),
135} 137}
136 138
137pub enum CheckCommand { 139pub 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.
246struct WatchThread { 273struct 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
278enum CheckEvent {
279 Begin,
280 Msg(cargo_metadata::Message),
281 End,
282}
283
251impl WatchThread { 284impl 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
90interface ProgressParams {
91 token: string
92 value: WorkDoneProgress
93}
94
95enum WorkDoneProgressKind {
96 Begin = "begin",
97 Report = "report",
98 End = "end"
99}
100
101interface 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';
8import * as events from './events'; 8import * as events from './events';
9import * as notifications from './notifications'; 9import * as notifications from './notifications';
10import { Server } from './server'; 10import { Server } from './server';
11import { StatusDisplay } from './commands/watch_status';
11 12
12export async function activate(context: vscode.ExtensionContext) { 13export 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();