From 4a383a0b0f1e2861a4d0884f40ae2c1d83ad156a Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Tue, 21 Oct 2025 00:40:12 +0900 Subject: [PATCH] fix: strip ANSI escape codes from flycheck messages --- Cargo.lock | 19 +++++++++++++++ Cargo.toml | 1 + crates/rust-analyzer/Cargo.toml | 1 + crates/rust-analyzer/src/flycheck.rs | 35 +++++++++++++++++++++------- 4 files changed, 47 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ea8d1a781dcc..4cbfb705322e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2048,6 +2048,7 @@ dependencies = [ "serde_derive", "serde_json", "stdx", + "strip-ansi-escapes", "syntax", "syntax-bridge", "tenthash", @@ -2379,6 +2380,15 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "strip-ansi-escapes" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a8f8038e7e7969abb3f1b7c2a811225e9296da208539e0f79c5251d6cac0025" +dependencies = [ + "vte", +] + [[package]] name = "syn" version = "2.0.106" @@ -2840,6 +2850,15 @@ dependencies = [ "walkdir", ] +[[package]] +name = "vte" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "231fdcd7ef3037e8330d8e17e61011a2c244126acc0a982f4040ac3f9f0bc077" +dependencies = [ + "memchr", +] + [[package]] name = "walkdir" version = "2.5.0" diff --git a/Cargo.toml b/Cargo.toml index 8a108974681a..336ae6a77501 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -144,6 +144,7 @@ semver = "1.0.26" serde = { version = "1.0.219" } serde_derive = { version = "1.0.219" } serde_json = "1.0.140" +strip-ansi-escapes = "0.2.1" rustc-hash = "2.1.1" rustc-literal-escaper = "0.0.4" smallvec = { version = "1.15.1", features = [ diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml index c746f848b6a0..408f9d3a129e 100644 --- a/crates/rust-analyzer/Cargo.toml +++ b/crates/rust-analyzer/Cargo.toml @@ -53,6 +53,7 @@ semver.workspace = true memchr = "2.7.5" cargo_metadata.workspace = true process-wrap.workspace = true +strip-ansi-escapes.workspace = true cfg.workspace = true hir-def.workspace = true diff --git a/crates/rust-analyzer/src/flycheck.rs b/crates/rust-analyzer/src/flycheck.rs index 73a51bba3d9a..5962beff1f29 100644 --- a/crates/rust-analyzer/src/flycheck.rs +++ b/crates/rust-analyzer/src/flycheck.rs @@ -421,11 +421,16 @@ impl FlycheckActor { let formatted_command = format!("{command:?}"); + let strip_ansi_color_codes = !matches!( + self.config, + FlycheckConfig::CargoCommand { ansi_color_output: false, .. } + ); + tracing::debug!(?command, "will restart flycheck"); let (sender, receiver) = unbounded(); match CommandHandle::spawn( command, - CargoCheckParser, + CargoCheckParser { strip_ansi_color_codes }, sender, match &self.config { FlycheckConfig::CargoCommand { options, .. } => Some( @@ -655,11 +660,12 @@ impl FlycheckActor { }; } - cmd.arg(if *ansi_color_output { - "--message-format=json-diagnostic-rendered-ansi" + if *ansi_color_output { + cmd.arg("--message-format=json-diagnostic-rendered-ansi"); } else { - "--message-format=json" - }); + cmd.arg("--message-format=json"); + cmd.arg("--color=never"); + } if let Some(manifest_path) = &self.manifest_path { cmd.arg("--manifest-path"); @@ -725,7 +731,9 @@ enum CargoCheckMessage { Diagnostic { diagnostic: Diagnostic, package_id: Option> }, } -struct CargoCheckParser; +struct CargoCheckParser { + strip_ansi_color_codes: bool, +} impl CargoParser for CargoCheckParser { fn from_line(&self, line: &str, error: &mut String) -> Option { @@ -739,15 +747,24 @@ impl CargoParser for CargoCheckParser { Some(CargoCheckMessage::CompilerArtifact(artifact)) } cargo_metadata::Message::CompilerMessage(msg) => { + let mut diagnostic = msg.message; + if self.strip_ansi_color_codes { + diagnostic.rendered = + diagnostic.rendered.map(strip_ansi_escapes::strip_str); + } Some(CargoCheckMessage::Diagnostic { - diagnostic: msg.message, + diagnostic, package_id: Some(Arc::new(msg.package_id)), }) } _ => None, }, - JsonMessage::Rustc(message) => { - Some(CargoCheckMessage::Diagnostic { diagnostic: message, package_id: None }) + JsonMessage::Rustc(mut diagnostic) => { + if self.strip_ansi_color_codes { + diagnostic.rendered = + diagnostic.rendered.map(strip_ansi_escapes::strip_str); + } + Some(CargoCheckMessage::Diagnostic { diagnostic, package_id: None }) } }; }