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.
This commit is contained in:
Andrew Gallant 2025-03-14 09:56:06 -04:00 committed by Andrew Gallant
parent 6311412373
commit eb6871d209
2 changed files with 58 additions and 2 deletions

View file

@ -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,
}

View file

@ -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()