Unnamed repository; edit this file 'description' to name the repository.
| -rw-r--r-- | crates/rust-analyzer/src/command.rs | 32 | ||||
| -rw-r--r-- | crates/rust-analyzer/src/discover.rs | 4 | ||||
| -rw-r--r-- | crates/rust-analyzer/src/flycheck.rs | 4 | ||||
| -rw-r--r-- | crates/rust-analyzer/src/test_runner.rs | 4 |
4 files changed, 25 insertions, 19 deletions
diff --git a/crates/rust-analyzer/src/command.rs b/crates/rust-analyzer/src/command.rs index 674e8623b2..41055272b1 100644 --- a/crates/rust-analyzer/src/command.rs +++ b/crates/rust-analyzer/src/command.rs @@ -15,33 +15,36 @@ use paths::Utf8PathBuf; use process_wrap::std::{StdChildWrapper, StdCommandWrap}; use stdx::process::streaming_output; -/// Cargo output is structured as one JSON per line. This trait abstracts parsing one line of -/// cargo output into a Rust data type -pub(crate) trait CargoParser<T>: Send + 'static { +/// This trait abstracts parsing one line of JSON output into a Rust +/// data type. +/// +/// This is useful for `cargo check` output, `cargo test` output, as +/// well as custom discover commands. +pub(crate) trait JsonLinesParser<T>: Send + 'static { fn from_line(&self, line: &str, error: &mut String) -> Option<T>; fn from_eof(&self) -> Option<T>; } -struct CargoActor<T> { - parser: Box<dyn CargoParser<T>>, +struct CommandActor<T> { + parser: Box<dyn JsonLinesParser<T>>, sender: Sender<T>, stdout: ChildStdout, stderr: ChildStderr, } -impl<T: Sized + Send + 'static> CargoActor<T> { +impl<T: Sized + Send + 'static> CommandActor<T> { fn new( - parser: impl CargoParser<T>, + parser: impl JsonLinesParser<T>, sender: Sender<T>, stdout: ChildStdout, stderr: ChildStderr, ) -> Self { let parser = Box::new(parser); - CargoActor { parser, sender, stdout, stderr } + CommandActor { parser, sender, stdout, stderr } } } -impl<T: Sized + Send + 'static> CargoActor<T> { +impl<T: Sized + Send + 'static> CommandActor<T> { fn run(self, outfile: Option<Utf8PathBuf>) -> io::Result<(bool, String)> { // We manually read a line at a time, instead of using serde's // stream deserializers, because the deserializer cannot recover @@ -113,6 +116,9 @@ impl<T: Sized + Send + 'static> CargoActor<T> { } } +/// 'Join On Drop' wrapper for a child process. +/// +/// This wrapper kills the process when the wrapper is dropped. struct JodGroupChild(Box<dyn StdChildWrapper>); impl Drop for JodGroupChild { @@ -122,9 +128,9 @@ impl Drop for JodGroupChild { } } -/// A handle to a cargo process used for fly-checking. +/// A handle to a shell command, such as cargo for diagnostics (flycheck). pub(crate) struct CommandHandle<T> { - /// The handle to the actual cargo process. As we cannot cancel directly from with + /// The handle to the actual child process. As we cannot cancel directly from with /// a read syscall dropping and therefore terminating the process is our best option. child: JodGroupChild, thread: stdx::thread::JoinHandle<io::Result<(bool, String)>>, @@ -147,7 +153,7 @@ impl<T> fmt::Debug for CommandHandle<T> { impl<T: Sized + Send + 'static> CommandHandle<T> { pub(crate) fn spawn( mut command: Command, - parser: impl CargoParser<T>, + parser: impl JsonLinesParser<T>, sender: Sender<T>, out_file: Option<Utf8PathBuf>, ) -> std::io::Result<Self> { @@ -167,7 +173,7 @@ impl<T: Sized + Send + 'static> CommandHandle<T> { let stdout = child.0.stdout().take().unwrap(); let stderr = child.0.stderr().take().unwrap(); - let actor = CargoActor::<T>::new(parser, sender, stdout, stderr); + let actor = CommandActor::<T>::new(parser, sender, stdout, stderr); let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker, "CommandHandle") .spawn(move || actor.run(out_file)) diff --git a/crates/rust-analyzer/src/discover.rs b/crates/rust-analyzer/src/discover.rs index 4ec0c075dd..0e96eff278 100644 --- a/crates/rust-analyzer/src/discover.rs +++ b/crates/rust-analyzer/src/discover.rs @@ -9,7 +9,7 @@ use project_model::ProjectJsonData; use serde::{Deserialize, Serialize}; use tracing::{info_span, span::EnteredSpan}; -use crate::command::{CargoParser, CommandHandle}; +use crate::command::{CommandHandle, JsonLinesParser}; pub(crate) const ARG_PLACEHOLDER: &str = "{arg}"; @@ -118,7 +118,7 @@ impl DiscoverProjectMessage { struct DiscoverProjectParser; -impl CargoParser<DiscoverProjectMessage> for DiscoverProjectParser { +impl JsonLinesParser<DiscoverProjectMessage> for DiscoverProjectParser { fn from_line(&self, line: &str, _error: &mut String) -> Option<DiscoverProjectMessage> { match serde_json::from_str::<DiscoverProjectData>(line) { Ok(data) => { diff --git a/crates/rust-analyzer/src/flycheck.rs b/crates/rust-analyzer/src/flycheck.rs index 68337ddf1c..14a4a1752f 100644 --- a/crates/rust-analyzer/src/flycheck.rs +++ b/crates/rust-analyzer/src/flycheck.rs @@ -25,7 +25,7 @@ use toolchain::Tool; use triomphe::Arc; use crate::{ - command::{CargoParser, CommandHandle}, + command::{CommandHandle, JsonLinesParser}, diagnostics::DiagnosticsGeneration, }; @@ -753,7 +753,7 @@ enum CargoCheckMessage { struct CargoCheckParser; -impl CargoParser<CargoCheckMessage> for CargoCheckParser { +impl JsonLinesParser<CargoCheckMessage> for CargoCheckParser { fn from_line(&self, line: &str, error: &mut String) -> Option<CargoCheckMessage> { let mut deserializer = serde_json::Deserializer::from_str(line); deserializer.disable_recursion_limit(); diff --git a/crates/rust-analyzer/src/test_runner.rs b/crates/rust-analyzer/src/test_runner.rs index 9a65e708a0..7111a15d02 100644 --- a/crates/rust-analyzer/src/test_runner.rs +++ b/crates/rust-analyzer/src/test_runner.rs @@ -9,7 +9,7 @@ use serde_derive::Deserialize; use toolchain::Tool; use crate::{ - command::{CargoParser, CommandHandle}, + command::{CommandHandle, JsonLinesParser}, flycheck::CargoOptions, }; @@ -57,7 +57,7 @@ impl CargoTestOutputParser { } } -impl CargoParser<CargoTestMessage> for CargoTestOutputParser { +impl JsonLinesParser<CargoTestMessage> for CargoTestOutputParser { fn from_line(&self, line: &str, _error: &mut String) -> Option<CargoTestMessage> { let mut deserializer = serde_json::Deserializer::from_str(line); deserializer.disable_recursion_limit(); |