From 0ec5d4f55c6a5ac3fadcd48ae17b70379aba17fa Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 25 Jun 2020 09:13:46 +0200 Subject: Rename ra_flycheck -> flycheck --- Cargo.lock | 26 +- crates/flycheck/Cargo.toml | 16 ++ crates/flycheck/src/lib.rs | 342 +++++++++++++++++++++++ crates/ra_flycheck/Cargo.toml | 16 -- crates/ra_flycheck/src/lib.rs | 342 ----------------------- crates/rust-analyzer/Cargo.toml | 2 +- crates/rust-analyzer/src/config.rs | 2 +- crates/rust-analyzer/src/diagnostics/to_proto.rs | 19 +- crates/rust-analyzer/src/global_state.rs | 2 +- crates/rust-analyzer/src/main_loop.rs | 8 +- 10 files changed, 388 insertions(+), 387 deletions(-) create mode 100644 crates/flycheck/Cargo.toml create mode 100644 crates/flycheck/src/lib.rs delete mode 100644 crates/ra_flycheck/Cargo.toml delete mode 100644 crates/ra_flycheck/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index c2d00adeb..b2b624212 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -340,6 +340,18 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" +[[package]] +name = "flycheck" +version = "0.1.0" +dependencies = [ + "cargo_metadata", + "crossbeam-channel", + "jod-thread", + "log", + "ra_toolchain", + "serde_json", +] + [[package]] name = "fnv" version = "1.0.7" @@ -959,18 +971,6 @@ dependencies = [ "vfs", ] -[[package]] -name = "ra_flycheck" -version = "0.1.0" -dependencies = [ - "cargo_metadata", - "crossbeam-channel", - "jod-thread", - "log", - "ra_toolchain", - "serde_json", -] - [[package]] name = "ra_fmt" version = "0.1.0" @@ -1373,6 +1373,7 @@ dependencies = [ "anyhow", "crossbeam-channel", "env_logger", + "flycheck", "globset", "insta", "itertools", @@ -1384,7 +1385,6 @@ dependencies = [ "pico-args", "ra_cfg", "ra_db", - "ra_flycheck", "ra_hir", "ra_hir_def", "ra_hir_ty", diff --git a/crates/flycheck/Cargo.toml b/crates/flycheck/Cargo.toml new file mode 100644 index 000000000..dc26b8ce7 --- /dev/null +++ b/crates/flycheck/Cargo.toml @@ -0,0 +1,16 @@ +[package] +edition = "2018" +name = "flycheck" +version = "0.1.0" +authors = ["rust-analyzer developers"] + +[lib] +doctest = false + +[dependencies] +crossbeam-channel = "0.4.0" +log = "0.4.8" +cargo_metadata = "0.10.0" +serde_json = "1.0.48" +jod-thread = "0.1.1" +ra_toolchain = { path = "../ra_toolchain" } diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs new file mode 100644 index 000000000..af75adbe2 --- /dev/null +++ b/crates/flycheck/src/lib.rs @@ -0,0 +1,342 @@ +//! cargo_check provides the functionality needed to run `cargo check` or +//! another compatible command (f.x. clippy) in a background thread and provide +//! LSP diagnostics based on the output of the command. + +use std::{ + fmt, + io::{self, BufReader}, + path::PathBuf, + process::{Command, Stdio}, + time::Instant, +}; + +use cargo_metadata::Message; +use crossbeam_channel::{never, select, unbounded, Receiver, RecvError, Sender}; + +pub use cargo_metadata::diagnostic::{ + Applicability, Diagnostic, DiagnosticLevel, DiagnosticSpan, DiagnosticSpanMacroExpansion, +}; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum FlycheckConfig { + CargoCommand { + command: String, + all_targets: bool, + all_features: bool, + features: Vec, + extra_args: Vec, + }, + CustomCommand { + command: String, + args: Vec, + }, +} + +impl fmt::Display for FlycheckConfig { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + FlycheckConfig::CargoCommand { command, .. } => write!(f, "cargo {}", command), + FlycheckConfig::CustomCommand { command, args } => { + write!(f, "{} {}", command, args.join(" ")) + } + } + } +} + +/// Flycheck wraps the shared state and communication machinery used for +/// running `cargo check` (or other compatible command) and providing +/// diagnostics based on the output. +/// The spawned thread is shut down when this struct is dropped. +#[derive(Debug)] +pub struct FlycheckHandle { + // XXX: drop order is significant + cmd_send: Sender, + handle: jod_thread::JoinHandle<()>, +} + +impl FlycheckHandle { + pub fn spawn( + sender: Box, + config: FlycheckConfig, + workspace_root: PathBuf, + ) -> FlycheckHandle { + let (cmd_send, cmd_recv) = unbounded::(); + let handle = jod_thread::spawn(move || { + FlycheckActor::new(sender, config, workspace_root).run(&cmd_recv); + }); + FlycheckHandle { cmd_send, handle } + } + + /// Schedule a re-start of the cargo check worker. + pub fn update(&self) { + self.cmd_send.send(CheckCommand::Update).unwrap(); + } +} + +#[derive(Debug)] +pub enum CheckTask { + /// Request a clearing of all cached diagnostics from the check watcher + ClearDiagnostics, + + /// Request adding a diagnostic with fixes included to a file + AddDiagnostic { workspace_root: PathBuf, diagnostic: Diagnostic }, + + /// Request check progress notification to client + Status(Status), +} + +#[derive(Debug)] +pub enum Status { + Being, + Progress(String), + End, +} + +pub enum CheckCommand { + /// Request re-start of check thread + Update, +} + +struct FlycheckActor { + sender: Box, + config: FlycheckConfig, + workspace_root: PathBuf, + last_update_req: Option, + // XXX: drop order is significant + message_recv: Receiver, + /// WatchThread exists to wrap around the communication needed to be able to + /// run `cargo check` without blocking. Currently the Rust standard library + /// doesn't provide a way to read sub-process output without blocking, so we + /// have to wrap sub-processes output handling in a thread and pass messages + /// back over a channel. + check_process: Option>, +} + +impl FlycheckActor { + fn new( + sender: Box, + config: FlycheckConfig, + workspace_root: PathBuf, + ) -> FlycheckActor { + FlycheckActor { + sender, + config, + workspace_root, + last_update_req: None, + message_recv: never(), + check_process: None, + } + } + + fn run(&mut self, cmd_recv: &Receiver) { + // If we rerun the thread, we need to discard the previous check results first + self.clean_previous_results(); + + loop { + select! { + recv(&cmd_recv) -> cmd => match cmd { + Ok(cmd) => self.handle_command(cmd), + Err(RecvError) => { + // Command channel has closed, so shut down + break; + }, + }, + recv(self.message_recv) -> msg => match msg { + Ok(msg) => self.handle_message(msg), + Err(RecvError) => { + // Watcher finished, replace it with a never channel to + // avoid busy-waiting. + self.message_recv = never(); + self.check_process = None; + }, + } + }; + + if self.should_recheck() { + self.last_update_req = None; + self.send(CheckTask::ClearDiagnostics); + self.restart_check_process(); + } + } + } + + fn clean_previous_results(&self) { + self.send(CheckTask::ClearDiagnostics); + self.send(CheckTask::Status(Status::End)); + } + + fn should_recheck(&mut self) -> bool { + if let Some(_last_update_req) = &self.last_update_req { + // We currently only request an update on save, as we need up to + // date source on disk for cargo check to do it's magic, so we + // don't really need to debounce the requests at this point. + return true; + } + false + } + + fn handle_command(&mut self, cmd: CheckCommand) { + match cmd { + CheckCommand::Update => self.last_update_req = Some(Instant::now()), + } + } + + fn handle_message(&self, msg: CheckEvent) { + match msg { + CheckEvent::Begin => { + self.send(CheckTask::Status(Status::Being)); + } + + CheckEvent::End => { + self.send(CheckTask::Status(Status::End)); + } + + CheckEvent::Msg(Message::CompilerArtifact(msg)) => { + self.send(CheckTask::Status(Status::Progress(msg.target.name))); + } + + CheckEvent::Msg(Message::CompilerMessage(msg)) => { + self.send(CheckTask::AddDiagnostic { + workspace_root: self.workspace_root.clone(), + diagnostic: msg.message, + }); + } + + CheckEvent::Msg(Message::BuildScriptExecuted(_msg)) => {} + CheckEvent::Msg(Message::BuildFinished(_)) => {} + CheckEvent::Msg(Message::TextLine(_)) => {} + CheckEvent::Msg(Message::Unknown) => {} + } + } + + fn restart_check_process(&mut self) { + // First, clear and cancel the old thread + self.message_recv = never(); + self.check_process = None; + + let mut cmd = match &self.config { + FlycheckConfig::CargoCommand { + command, + all_targets, + all_features, + extra_args, + features, + } => { + let mut cmd = Command::new(ra_toolchain::cargo()); + cmd.arg(command); + cmd.args(&["--workspace", "--message-format=json", "--manifest-path"]) + .arg(self.workspace_root.join("Cargo.toml")); + if *all_targets { + cmd.arg("--all-targets"); + } + if *all_features { + cmd.arg("--all-features"); + } else if !features.is_empty() { + cmd.arg("--features"); + cmd.arg(features.join(" ")); + } + cmd.args(extra_args); + cmd + } + FlycheckConfig::CustomCommand { command, args } => { + let mut cmd = Command::new(command); + cmd.args(args); + cmd + } + }; + cmd.current_dir(&self.workspace_root); + + let (message_send, message_recv) = unbounded(); + self.message_recv = message_recv; + self.check_process = Some(jod_thread::spawn(move || { + // If we trigger an error here, we will do so in the loop instead, + // which will break out of the loop, and continue the shutdown + let _ = message_send.send(CheckEvent::Begin); + + let res = run_cargo(cmd, &mut |message| { + // Skip certain kinds of messages to only spend time on what's useful + match &message { + Message::CompilerArtifact(artifact) if artifact.fresh => return true, + Message::BuildScriptExecuted(_) => return true, + Message::Unknown => return true, + _ => {} + } + + // if the send channel was closed, we want to shutdown + message_send.send(CheckEvent::Msg(message)).is_ok() + }); + + if let Err(err) = res { + // FIXME: make the `message_send` to be `Sender>` + // to display user-caused misconfiguration errors instead of just logging them here + log::error!("Cargo watcher failed {:?}", err); + } + + // We can ignore any error here, as we are already in the progress + // of shutting down. + let _ = message_send.send(CheckEvent::End); + })) + } + + fn send(&self, check_task: CheckTask) { + (self.sender)(check_task) + } +} + +enum CheckEvent { + Begin, + Msg(cargo_metadata::Message), + End, +} + +fn run_cargo( + mut command: Command, + on_message: &mut dyn FnMut(cargo_metadata::Message) -> bool, +) -> io::Result<()> { + let mut child = + command.stdout(Stdio::piped()).stderr(Stdio::null()).stdin(Stdio::null()).spawn()?; + + // We manually read a line at a time, instead of using serde's + // stream deserializers, because the deserializer cannot recover + // from an error, resulting in it getting stuck, because we try to + // be resillient against failures. + // + // Because cargo only outputs one JSON object per line, we can + // simply skip a line if it doesn't parse, which just ignores any + // erroneus output. + let stdout = BufReader::new(child.stdout.take().unwrap()); + let mut read_at_least_one_message = false; + for message in cargo_metadata::Message::parse_stream(stdout) { + let message = match message { + Ok(message) => message, + Err(err) => { + log::error!("Invalid json from cargo check, ignoring ({})", err); + continue; + } + }; + + read_at_least_one_message = true; + + if !on_message(message) { + break; + } + } + + // It is okay to ignore the result, as it only errors if the process is already dead + let _ = child.kill(); + + let exit_status = child.wait()?; + if !exit_status.success() && !read_at_least_one_message { + // FIXME: Read the stderr to display the reason, see `read2()` reference in PR comment: + // https://github.com/rust-analyzer/rust-analyzer/pull/3632#discussion_r395605298 + return Err(io::Error::new( + io::ErrorKind::Other, + format!( + "the command produced no valid metadata (exit code: {:?}): {:?}", + exit_status, command + ), + )); + } + + Ok(()) +} diff --git a/crates/ra_flycheck/Cargo.toml b/crates/ra_flycheck/Cargo.toml deleted file mode 100644 index 1aa39bade..000000000 --- a/crates/ra_flycheck/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -edition = "2018" -name = "ra_flycheck" -version = "0.1.0" -authors = ["rust-analyzer developers"] - -[lib] -doctest = false - -[dependencies] -crossbeam-channel = "0.4.0" -log = "0.4.8" -cargo_metadata = "0.10.0" -serde_json = "1.0.48" -jod-thread = "0.1.1" -ra_toolchain = { path = "../ra_toolchain" } diff --git a/crates/ra_flycheck/src/lib.rs b/crates/ra_flycheck/src/lib.rs deleted file mode 100644 index af75adbe2..000000000 --- a/crates/ra_flycheck/src/lib.rs +++ /dev/null @@ -1,342 +0,0 @@ -//! cargo_check provides the functionality needed to run `cargo check` or -//! another compatible command (f.x. clippy) in a background thread and provide -//! LSP diagnostics based on the output of the command. - -use std::{ - fmt, - io::{self, BufReader}, - path::PathBuf, - process::{Command, Stdio}, - time::Instant, -}; - -use cargo_metadata::Message; -use crossbeam_channel::{never, select, unbounded, Receiver, RecvError, Sender}; - -pub use cargo_metadata::diagnostic::{ - Applicability, Diagnostic, DiagnosticLevel, DiagnosticSpan, DiagnosticSpanMacroExpansion, -}; - -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum FlycheckConfig { - CargoCommand { - command: String, - all_targets: bool, - all_features: bool, - features: Vec, - extra_args: Vec, - }, - CustomCommand { - command: String, - args: Vec, - }, -} - -impl fmt::Display for FlycheckConfig { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - FlycheckConfig::CargoCommand { command, .. } => write!(f, "cargo {}", command), - FlycheckConfig::CustomCommand { command, args } => { - write!(f, "{} {}", command, args.join(" ")) - } - } - } -} - -/// Flycheck wraps the shared state and communication machinery used for -/// running `cargo check` (or other compatible command) and providing -/// diagnostics based on the output. -/// The spawned thread is shut down when this struct is dropped. -#[derive(Debug)] -pub struct FlycheckHandle { - // XXX: drop order is significant - cmd_send: Sender, - handle: jod_thread::JoinHandle<()>, -} - -impl FlycheckHandle { - pub fn spawn( - sender: Box, - config: FlycheckConfig, - workspace_root: PathBuf, - ) -> FlycheckHandle { - let (cmd_send, cmd_recv) = unbounded::(); - let handle = jod_thread::spawn(move || { - FlycheckActor::new(sender, config, workspace_root).run(&cmd_recv); - }); - FlycheckHandle { cmd_send, handle } - } - - /// Schedule a re-start of the cargo check worker. - pub fn update(&self) { - self.cmd_send.send(CheckCommand::Update).unwrap(); - } -} - -#[derive(Debug)] -pub enum CheckTask { - /// Request a clearing of all cached diagnostics from the check watcher - ClearDiagnostics, - - /// Request adding a diagnostic with fixes included to a file - AddDiagnostic { workspace_root: PathBuf, diagnostic: Diagnostic }, - - /// Request check progress notification to client - Status(Status), -} - -#[derive(Debug)] -pub enum Status { - Being, - Progress(String), - End, -} - -pub enum CheckCommand { - /// Request re-start of check thread - Update, -} - -struct FlycheckActor { - sender: Box, - config: FlycheckConfig, - workspace_root: PathBuf, - last_update_req: Option, - // XXX: drop order is significant - message_recv: Receiver, - /// WatchThread exists to wrap around the communication needed to be able to - /// run `cargo check` without blocking. Currently the Rust standard library - /// doesn't provide a way to read sub-process output without blocking, so we - /// have to wrap sub-processes output handling in a thread and pass messages - /// back over a channel. - check_process: Option>, -} - -impl FlycheckActor { - fn new( - sender: Box, - config: FlycheckConfig, - workspace_root: PathBuf, - ) -> FlycheckActor { - FlycheckActor { - sender, - config, - workspace_root, - last_update_req: None, - message_recv: never(), - check_process: None, - } - } - - fn run(&mut self, cmd_recv: &Receiver) { - // If we rerun the thread, we need to discard the previous check results first - self.clean_previous_results(); - - loop { - select! { - recv(&cmd_recv) -> cmd => match cmd { - Ok(cmd) => self.handle_command(cmd), - Err(RecvError) => { - // Command channel has closed, so shut down - break; - }, - }, - recv(self.message_recv) -> msg => match msg { - Ok(msg) => self.handle_message(msg), - Err(RecvError) => { - // Watcher finished, replace it with a never channel to - // avoid busy-waiting. - self.message_recv = never(); - self.check_process = None; - }, - } - }; - - if self.should_recheck() { - self.last_update_req = None; - self.send(CheckTask::ClearDiagnostics); - self.restart_check_process(); - } - } - } - - fn clean_previous_results(&self) { - self.send(CheckTask::ClearDiagnostics); - self.send(CheckTask::Status(Status::End)); - } - - fn should_recheck(&mut self) -> bool { - if let Some(_last_update_req) = &self.last_update_req { - // We currently only request an update on save, as we need up to - // date source on disk for cargo check to do it's magic, so we - // don't really need to debounce the requests at this point. - return true; - } - false - } - - fn handle_command(&mut self, cmd: CheckCommand) { - match cmd { - CheckCommand::Update => self.last_update_req = Some(Instant::now()), - } - } - - fn handle_message(&self, msg: CheckEvent) { - match msg { - CheckEvent::Begin => { - self.send(CheckTask::Status(Status::Being)); - } - - CheckEvent::End => { - self.send(CheckTask::Status(Status::End)); - } - - CheckEvent::Msg(Message::CompilerArtifact(msg)) => { - self.send(CheckTask::Status(Status::Progress(msg.target.name))); - } - - CheckEvent::Msg(Message::CompilerMessage(msg)) => { - self.send(CheckTask::AddDiagnostic { - workspace_root: self.workspace_root.clone(), - diagnostic: msg.message, - }); - } - - CheckEvent::Msg(Message::BuildScriptExecuted(_msg)) => {} - CheckEvent::Msg(Message::BuildFinished(_)) => {} - CheckEvent::Msg(Message::TextLine(_)) => {} - CheckEvent::Msg(Message::Unknown) => {} - } - } - - fn restart_check_process(&mut self) { - // First, clear and cancel the old thread - self.message_recv = never(); - self.check_process = None; - - let mut cmd = match &self.config { - FlycheckConfig::CargoCommand { - command, - all_targets, - all_features, - extra_args, - features, - } => { - let mut cmd = Command::new(ra_toolchain::cargo()); - cmd.arg(command); - cmd.args(&["--workspace", "--message-format=json", "--manifest-path"]) - .arg(self.workspace_root.join("Cargo.toml")); - if *all_targets { - cmd.arg("--all-targets"); - } - if *all_features { - cmd.arg("--all-features"); - } else if !features.is_empty() { - cmd.arg("--features"); - cmd.arg(features.join(" ")); - } - cmd.args(extra_args); - cmd - } - FlycheckConfig::CustomCommand { command, args } => { - let mut cmd = Command::new(command); - cmd.args(args); - cmd - } - }; - cmd.current_dir(&self.workspace_root); - - let (message_send, message_recv) = unbounded(); - self.message_recv = message_recv; - self.check_process = Some(jod_thread::spawn(move || { - // If we trigger an error here, we will do so in the loop instead, - // which will break out of the loop, and continue the shutdown - let _ = message_send.send(CheckEvent::Begin); - - let res = run_cargo(cmd, &mut |message| { - // Skip certain kinds of messages to only spend time on what's useful - match &message { - Message::CompilerArtifact(artifact) if artifact.fresh => return true, - Message::BuildScriptExecuted(_) => return true, - Message::Unknown => return true, - _ => {} - } - - // if the send channel was closed, we want to shutdown - message_send.send(CheckEvent::Msg(message)).is_ok() - }); - - if let Err(err) = res { - // FIXME: make the `message_send` to be `Sender>` - // to display user-caused misconfiguration errors instead of just logging them here - log::error!("Cargo watcher failed {:?}", err); - } - - // We can ignore any error here, as we are already in the progress - // of shutting down. - let _ = message_send.send(CheckEvent::End); - })) - } - - fn send(&self, check_task: CheckTask) { - (self.sender)(check_task) - } -} - -enum CheckEvent { - Begin, - Msg(cargo_metadata::Message), - End, -} - -fn run_cargo( - mut command: Command, - on_message: &mut dyn FnMut(cargo_metadata::Message) -> bool, -) -> io::Result<()> { - let mut child = - command.stdout(Stdio::piped()).stderr(Stdio::null()).stdin(Stdio::null()).spawn()?; - - // We manually read a line at a time, instead of using serde's - // stream deserializers, because the deserializer cannot recover - // from an error, resulting in it getting stuck, because we try to - // be resillient against failures. - // - // Because cargo only outputs one JSON object per line, we can - // simply skip a line if it doesn't parse, which just ignores any - // erroneus output. - let stdout = BufReader::new(child.stdout.take().unwrap()); - let mut read_at_least_one_message = false; - for message in cargo_metadata::Message::parse_stream(stdout) { - let message = match message { - Ok(message) => message, - Err(err) => { - log::error!("Invalid json from cargo check, ignoring ({})", err); - continue; - } - }; - - read_at_least_one_message = true; - - if !on_message(message) { - break; - } - } - - // It is okay to ignore the result, as it only errors if the process is already dead - let _ = child.kill(); - - let exit_status = child.wait()?; - if !exit_status.success() && !read_at_least_one_message { - // FIXME: Read the stderr to display the reason, see `read2()` reference in PR comment: - // https://github.com/rust-analyzer/rust-analyzer/pull/3632#discussion_r395605298 - return Err(io::Error::new( - io::ErrorKind::Other, - format!( - "the command produced no valid metadata (exit code: {:?}): {:?}", - exit_status, command - ), - )); - } - - Ok(()) -} diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml index 68d04f3e3..08c67ddd0 100644 --- a/crates/rust-analyzer/Cargo.toml +++ b/crates/rust-analyzer/Cargo.toml @@ -32,7 +32,7 @@ threadpool = "1.7.1" stdx = { path = "../stdx" } lsp-server = "0.3.3" -ra_flycheck = { path = "../ra_flycheck" } +flycheck = { path = "../flycheck" } ra_ide = { path = "../ra_ide" } ra_prof = { path = "../ra_prof" } ra_project_model = { path = "../ra_project_model" } diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 8f69de968..435bbbb6b 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -10,9 +10,9 @@ use std::{ffi::OsString, path::PathBuf}; use crate::diagnostics::DiagnosticsConfig; +use flycheck::FlycheckConfig; use lsp_types::ClientCapabilities; use ra_db::AbsPathBuf; -use ra_flycheck::FlycheckConfig; use ra_ide::{AssistConfig, CompletionConfig, HoverConfig, InlayHintsConfig}; use ra_project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest}; use serde::Deserialize; diff --git a/crates/rust-analyzer/src/diagnostics/to_proto.rs b/crates/rust-analyzer/src/diagnostics/to_proto.rs index ba74f15f3..f379f5ed0 100644 --- a/crates/rust-analyzer/src/diagnostics/to_proto.rs +++ b/crates/rust-analyzer/src/diagnostics/to_proto.rs @@ -2,20 +2,21 @@ //! `cargo check` json format to the LSP diagnostic format. use std::{collections::HashMap, path::Path}; +use flycheck::{Applicability, DiagnosticLevel, DiagnosticSpan, DiagnosticSpanMacroExpansion}; use lsp_types::{ Diagnostic, DiagnosticRelatedInformation, DiagnosticSeverity, DiagnosticTag, Location, NumberOrString, Position, Range, TextEdit, Url, }; -use ra_flycheck::{Applicability, DiagnosticLevel, DiagnosticSpan, DiagnosticSpanMacroExpansion}; use stdx::format_to; -use super::DiagnosticsConfig; use crate::{lsp_ext, to_proto::url_from_abs_path}; +use super::DiagnosticsConfig; + /// Determines the LSP severity from a diagnostic fn map_diagnostic_to_severity( config: &DiagnosticsConfig, - val: &ra_flycheck::Diagnostic, + val: &flycheck::Diagnostic, ) -> Option { let res = match val.level { DiagnosticLevel::Ice => DiagnosticSeverity::Error, @@ -95,7 +96,7 @@ fn map_secondary_span_to_related( } /// Determines if diagnostic is related to unused code -fn is_unused_or_unnecessary(rd: &ra_flycheck::Diagnostic) -> bool { +fn is_unused_or_unnecessary(rd: &flycheck::Diagnostic) -> bool { match &rd.code { Some(code) => match code.code.as_str() { "dead_code" | "unknown_lints" | "unreachable_code" | "unused_attributes" @@ -107,7 +108,7 @@ fn is_unused_or_unnecessary(rd: &ra_flycheck::Diagnostic) -> bool { } /// Determines if diagnostic is related to deprecated code -fn is_deprecated(rd: &ra_flycheck::Diagnostic) -> bool { +fn is_deprecated(rd: &flycheck::Diagnostic) -> bool { match &rd.code { Some(code) => code.code.as_str() == "deprecated", None => false, @@ -121,7 +122,7 @@ enum MappedRustChildDiagnostic { } fn map_rust_child_diagnostic( - rd: &ra_flycheck::Diagnostic, + rd: &flycheck::Diagnostic, workspace_root: &Path, ) -> MappedRustChildDiagnostic { let spans: Vec<&DiagnosticSpan> = rd.spans.iter().filter(|s| s.is_primary).collect(); @@ -183,7 +184,7 @@ pub(crate) struct MappedRustDiagnostic { /// If the diagnostic has no primary span this will return `None` pub(crate) fn map_rust_diagnostic_to_lsp( config: &DiagnosticsConfig, - rd: &ra_flycheck::Diagnostic, + rd: &flycheck::Diagnostic, workspace_root: &Path, ) -> Vec { let primary_spans: Vec<&DiagnosticSpan> = rd.spans.iter().filter(|s| s.is_primary).collect(); @@ -286,8 +287,8 @@ pub(crate) fn map_rust_diagnostic_to_lsp( mod tests { use super::*; - fn parse_diagnostic(val: &str) -> ra_flycheck::Diagnostic { - serde_json::from_str::(val).unwrap() + fn parse_diagnostic(val: &str) -> flycheck::Diagnostic { + serde_json::from_str::(val).unwrap() } #[test] diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index c022ff705..6038bf664 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs @@ -6,10 +6,10 @@ use std::{convert::TryFrom, sync::Arc}; use crossbeam_channel::{unbounded, Receiver}; +use flycheck::{CheckTask, FlycheckConfig, FlycheckHandle}; use lsp_types::Url; use parking_lot::RwLock; use ra_db::{CrateId, SourceRoot, VfsPath}; -use ra_flycheck::{CheckTask, FlycheckConfig, FlycheckHandle}; use ra_ide::{Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId}; use ra_project_model::{CargoWorkspace, ProcMacroClient, ProjectWorkspace, Target}; use stdx::format_to; diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index e5f82de5e..0664e4a5a 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -9,10 +9,10 @@ use std::{ }; use crossbeam_channel::{never, select, unbounded, RecvError, Sender}; +use flycheck::CheckTask; use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestId, Response}; use lsp_types::{request::Request as _, NumberOrString, TextDocumentContentChangeEvent}; use ra_db::VfsPath; -use ra_flycheck::CheckTask; use ra_ide::{Canceled, FileId, LineIndex}; use ra_prof::profile; use ra_project_model::{PackageRoot, ProjectWorkspace}; @@ -629,9 +629,9 @@ fn on_check_task( CheckTask::Status(status) => { let (state, message) = match status { - ra_flycheck::Status::Being => (ProgressState::Start, None), - ra_flycheck::Status::Progress(target) => (ProgressState::Report, Some(target)), - ra_flycheck::Status::End => (ProgressState::End, None), + flycheck::Status::Being => (ProgressState::Start, None), + flycheck::Status::Progress(target) => (ProgressState::Report, Some(target)), + flycheck::Status::End => (ProgressState::End, None), }; report_progress(global_state, msg_sender, "cargo check", state, message, None); -- cgit v1.2.3