aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_flycheck/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_flycheck/src/lib.rs')
-rw-r--r--crates/ra_flycheck/src/lib.rs88
1 files changed, 25 insertions, 63 deletions
diff --git a/crates/ra_flycheck/src/lib.rs b/crates/ra_flycheck/src/lib.rs
index d5efb6ab3..041e38a9f 100644
--- a/crates/ra_flycheck/src/lib.rs
+++ b/crates/ra_flycheck/src/lib.rs
@@ -1,10 +1,9 @@
1//! cargo_check provides the functionality needed to run `cargo check` or 1//! cargo_check provides the functionality needed to run `cargo check` or
2//! another compatible command (f.x. clippy) in a background thread and provide 2//! another compatible command (f.x. clippy) in a background thread and provide
3//! LSP diagnostics based on the output of the command. 3//! LSP diagnostics based on the output of the command.
4mod conv;
5 4
6use std::{ 5use std::{
7 io::{self, BufRead, BufReader}, 6 io::{self, BufReader},
8 path::PathBuf, 7 path::PathBuf,
9 process::{Command, Stdio}, 8 process::{Command, Stdio},
10 time::Instant, 9 time::Instant,
@@ -12,14 +11,10 @@ use std::{
12 11
13use cargo_metadata::Message; 12use cargo_metadata::Message;
14use crossbeam_channel::{never, select, unbounded, Receiver, RecvError, Sender}; 13use crossbeam_channel::{never, select, unbounded, Receiver, RecvError, Sender};
15use lsp_types::{
16 CodeAction, CodeActionOrCommand, Diagnostic, Url, WorkDoneProgress, WorkDoneProgressBegin,
17 WorkDoneProgressEnd, WorkDoneProgressReport,
18};
19
20use crate::conv::{map_rust_diagnostic_to_lsp, MappedRustDiagnostic};
21 14
22pub use crate::conv::url_from_path_with_drive_lowercasing; 15pub use cargo_metadata::diagnostic::{
16 Applicability, Diagnostic, DiagnosticLevel, DiagnosticSpan, DiagnosticSpanMacroExpansion,
17};
23 18
24#[derive(Clone, Debug, PartialEq, Eq)] 19#[derive(Clone, Debug, PartialEq, Eq)]
25pub enum FlycheckConfig { 20pub enum FlycheckConfig {
@@ -61,10 +56,17 @@ pub enum CheckTask {
61 ClearDiagnostics, 56 ClearDiagnostics,
62 57
63 /// Request adding a diagnostic with fixes included to a file 58 /// Request adding a diagnostic with fixes included to a file
64 AddDiagnostic { url: Url, diagnostic: Diagnostic, fixes: Vec<CodeActionOrCommand> }, 59 AddDiagnostic { workspace_root: PathBuf, diagnostic: Diagnostic },
65 60
66 /// Request check progress notification to client 61 /// Request check progress notification to client
67 Status(WorkDoneProgress), 62 Status(Status),
63}
64
65#[derive(Debug)]
66pub enum Status {
67 Being,
68 Progress(String),
69 End,
68} 70}
69 71
70pub enum CheckCommand { 72pub enum CheckCommand {
@@ -131,9 +133,7 @@ impl FlycheckThread {
131 133
132 fn clean_previous_results(&self, task_send: &Sender<CheckTask>) { 134 fn clean_previous_results(&self, task_send: &Sender<CheckTask>) {
133 task_send.send(CheckTask::ClearDiagnostics).unwrap(); 135 task_send.send(CheckTask::ClearDiagnostics).unwrap();
134 task_send 136 task_send.send(CheckTask::Status(Status::End)).unwrap();
135 .send(CheckTask::Status(WorkDoneProgress::End(WorkDoneProgressEnd { message: None })))
136 .unwrap();
137 } 137 }
138 138
139 fn should_recheck(&mut self) -> bool { 139 fn should_recheck(&mut self) -> bool {
@@ -155,52 +155,24 @@ impl FlycheckThread {
155 fn handle_message(&self, msg: CheckEvent, task_send: &Sender<CheckTask>) { 155 fn handle_message(&self, msg: CheckEvent, task_send: &Sender<CheckTask>) {
156 match msg { 156 match msg {
157 CheckEvent::Begin => { 157 CheckEvent::Begin => {
158 task_send 158 task_send.send(CheckTask::Status(Status::Being)).unwrap();
159 .send(CheckTask::Status(WorkDoneProgress::Begin(WorkDoneProgressBegin {
160 title: "Running `cargo check`".to_string(),
161 cancellable: Some(false),
162 message: None,
163 percentage: None,
164 })))
165 .unwrap();
166 } 159 }
167 160
168 CheckEvent::End => { 161 CheckEvent::End => {
169 task_send 162 task_send.send(CheckTask::Status(Status::End)).unwrap();
170 .send(CheckTask::Status(WorkDoneProgress::End(WorkDoneProgressEnd {
171 message: None,
172 })))
173 .unwrap();
174 } 163 }
175 164
176 CheckEvent::Msg(Message::CompilerArtifact(msg)) => { 165 CheckEvent::Msg(Message::CompilerArtifact(msg)) => {
177 task_send 166 task_send.send(CheckTask::Status(Status::Progress(msg.target.name))).unwrap();
178 .send(CheckTask::Status(WorkDoneProgress::Report(WorkDoneProgressReport {
179 cancellable: Some(false),
180 message: Some(msg.target.name),
181 percentage: None,
182 })))
183 .unwrap();
184 } 167 }
185 168
186 CheckEvent::Msg(Message::CompilerMessage(msg)) => { 169 CheckEvent::Msg(Message::CompilerMessage(msg)) => {
187 let map_result = map_rust_diagnostic_to_lsp(&msg.message, &self.workspace_root); 170 task_send
188 if map_result.is_empty() { 171 .send(CheckTask::AddDiagnostic {
189 return; 172 workspace_root: self.workspace_root.clone(),
190 } 173 diagnostic: msg.message,
191 174 })
192 for MappedRustDiagnostic { location, diagnostic, fixes } in map_result { 175 .unwrap();
193 let fixes = fixes
194 .into_iter()
195 .map(|fix| {
196 CodeAction { diagnostics: Some(vec![diagnostic.clone()]), ..fix }.into()
197 })
198 .collect();
199
200 task_send
201 .send(CheckTask::AddDiagnostic { url: location.uri, diagnostic, fixes })
202 .unwrap();
203 }
204 } 176 }
205 177
206 CheckEvent::Msg(Message::BuildScriptExecuted(_msg)) => {} 178 CheckEvent::Msg(Message::BuildScriptExecuted(_msg)) => {}
@@ -271,12 +243,6 @@ impl FlycheckThread {
271 } 243 }
272} 244}
273 245
274#[derive(Debug)]
275pub struct DiagnosticWithFixes {
276 diagnostic: Diagnostic,
277 fixes: Vec<CodeAction>,
278}
279
280enum CheckEvent { 246enum CheckEvent {
281 Begin, 247 Begin,
282 Msg(cargo_metadata::Message), 248 Msg(cargo_metadata::Message),
@@ -300,15 +266,11 @@ fn run_cargo(
300 // erroneus output. 266 // erroneus output.
301 let stdout = BufReader::new(child.stdout.take().unwrap()); 267 let stdout = BufReader::new(child.stdout.take().unwrap());
302 let mut read_at_least_one_message = false; 268 let mut read_at_least_one_message = false;
303 269 for message in cargo_metadata::Message::parse_stream(stdout) {
304 for line in stdout.lines() {
305 let line = line?;
306
307 let message = serde_json::from_str::<cargo_metadata::Message>(&line);
308 let message = match message { 270 let message = match message {
309 Ok(message) => message, 271 Ok(message) => message,
310 Err(err) => { 272 Err(err) => {
311 log::error!("Invalid json from cargo check, ignoring ({}): {:?} ", err, line); 273 log::error!("Invalid json from cargo check, ignoring ({})", err);
312 continue; 274 continue;
313 } 275 }
314 }; 276 };