From eb6871d2090ae441d3b3dd0aed69b0fbcf396cba Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Fri, 14 Mar 2025 09:56:06 -0400 Subject: [PATCH] ruff_db: add concise diagnostic mode This adds a new configuration knob to diagnostic rendering that, when enabled, will make diagnostic rendering much more terse. Specifically, it will guarantee that each diagnostic will only use one line. This doesn't actually hook the concise output option up to anything. We'll do that plumbing in the next commit. --- crates/ruff_db/src/diagnostic/mod.rs | 36 +++++++++++++++++++++++++++- crates/ruff_db/src/diagnostic/old.rs | 24 ++++++++++++++++++- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/crates/ruff_db/src/diagnostic/mod.rs b/crates/ruff_db/src/diagnostic/mod.rs index 73bc080caa..b0f88df90a 100644 --- a/crates/ruff_db/src/diagnostic/mod.rs +++ b/crates/ruff_db/src/diagnostic/mod.rs @@ -518,6 +518,10 @@ impl Severity { /// Configuration for rendering diagnostics. #[derive(Clone, Debug, Default)] pub struct DisplayDiagnosticConfig { + /// The format to use for diagnostic rendering. + /// + /// This uses the "full" format by default. + format: DiagnosticFormat, /// Whether to enable colors or not. /// /// Disabled by default. @@ -525,8 +529,38 @@ pub struct DisplayDiagnosticConfig { } impl DisplayDiagnosticConfig { + /// Whether to enable concise diagnostic output or not. + pub fn format(self, format: DiagnosticFormat) -> DisplayDiagnosticConfig { + DisplayDiagnosticConfig { format, ..self } + } + /// Whether to enable colors or not. pub fn color(self, yes: bool) -> DisplayDiagnosticConfig { - DisplayDiagnosticConfig { color: yes } + DisplayDiagnosticConfig { color: yes, ..self } } } + +/// The diagnostic output format. +#[derive(Copy, Clone, Debug, Default, Eq, Hash, PartialEq, PartialOrd, Ord)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))] +#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] +pub enum DiagnosticFormat { + /// The default full mode will print "pretty" diagnostics. + /// + /// That is, color will be used when printing to a `tty`. + /// Moreover, diagnostic messages may include additional + /// context and annotations on the input to help understand + /// the message. + #[default] + Full, + /// Print diagnostics in a concise mode. + /// + /// This will guarantee that each diagnostic is printed on + /// a single line. Only the most important or primary aspects + /// of the diagnostic are included. Contextual information is + /// dropped. + /// + /// This may use color when printing to a `tty`. + Concise, +} diff --git a/crates/ruff_db/src/diagnostic/old.rs b/crates/ruff_db/src/diagnostic/old.rs index 1486269617..f27dc4cac3 100644 --- a/crates/ruff_db/src/diagnostic/old.rs +++ b/crates/ruff_db/src/diagnostic/old.rs @@ -9,7 +9,7 @@ use ruff_source_file::{OneIndexed, SourceCode}; use ruff_text_size::TextRange; use crate::{ - diagnostic::{DiagnosticId, DisplayDiagnosticConfig, Severity, Span}, + diagnostic::{DiagnosticFormat, DiagnosticId, DisplayDiagnosticConfig, Severity, Span}, files::File, source::{line_index, source_text}, Db, @@ -74,6 +74,28 @@ pub struct OldDisplayDiagnostic<'db, 'diag, 'config> { impl std::fmt::Display for OldDisplayDiagnostic<'_, '_, '_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if matches!(self.config.format, DiagnosticFormat::Concise) { + match self.diagnostic.severity() { + Severity::Info => f.write_str("info")?, + Severity::Warning => f.write_str("warning")?, + Severity::Error => f.write_str("error")?, + Severity::Fatal => f.write_str("fatal")?, + } + + write!(f, "[{rule}]", rule = self.diagnostic.id())?; + if let Some(span) = self.diagnostic.span() { + write!(f, " {path}", path = span.file().path(self.db))?; + if let Some(range) = span.range() { + let index = line_index(self.db, span.file()); + let source = source_text(self.db, span.file()); + let start = index.source_location(range.start(), &source); + write!(f, ":{line}:{col}", line = start.row, col = start.column)?; + } + write!(f, ":")?; + } + return write!(f, " {message}", message = self.diagnostic.message()); + } + let render = |f: &mut std::fmt::Formatter, message| { let renderer = if self.config.color { AnnotateRenderer::styled()