mirror of
https://github.com/astral-sh/ruff.git
synced 2025-11-02 21:03:11 +00:00
ruff_db: switch diagnostic rendering over to std::fmt::Display
It was already using this approach internally, so this is "just" a matter of rejiggering the public API of `Diagnostic`. We were previously writing directly to a `std::io::Write` since it was thought that this worked better with the linear typing fakery. Namely, it increased confidence that the diagnostic rendering was actually written somewhere useful, instead of just being converted to a string that could potentially get lost. For reasons discussed in #17130, the linear type fakery was removed. And so there is less of a reason to require a `std::io::Write` implementation for diagnostic rendering. Indeed, this would sometimes result in `unwrap()` calls when one wants to convert to a `String`.
This commit is contained in:
parent
24498e383d
commit
718b0cadf4
6 changed files with 53 additions and 53 deletions
|
|
@ -5,11 +5,12 @@ use thiserror::Error;
|
|||
use ruff_annotate_snippets::Level as AnnotateLevel;
|
||||
use ruff_text_size::TextRange;
|
||||
|
||||
pub use self::render::DisplayDiagnostic;
|
||||
pub use crate::diagnostic::old::OldSecondaryDiagnosticMessage;
|
||||
use crate::files::File;
|
||||
use crate::Db;
|
||||
|
||||
use self::render::{DisplayDiagnostic, FileResolver};
|
||||
use self::render::FileResolver;
|
||||
|
||||
// This module should not be exported. We are planning to migrate off
|
||||
// the APIs in this module.
|
||||
|
|
@ -100,22 +101,18 @@ impl Diagnostic {
|
|||
Arc::make_mut(&mut self.inner).subs.push(sub);
|
||||
}
|
||||
|
||||
/// Print this diagnostic to the given writer.
|
||||
/// Return a `std::fmt::Display` implementation that renders this
|
||||
/// diagnostic into a human readable format.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This is guaranteed to only return an error if the underlying
|
||||
/// writer given returns an error. Otherwise, the formatting of
|
||||
/// diagnostics themselves is infallible.
|
||||
pub fn print(
|
||||
&self,
|
||||
db: &dyn Db,
|
||||
config: &DisplayDiagnosticConfig,
|
||||
mut wtr: impl std::io::Write,
|
||||
) -> std::io::Result<()> {
|
||||
/// Note that this `Display` impl includes a trailing line terminator, so
|
||||
/// callers should prefer using this with `write!` instead of `writeln!`.
|
||||
pub fn display<'c, 'db, 'd>(
|
||||
&'d self,
|
||||
db: &'db dyn Db,
|
||||
config: &'c DisplayDiagnosticConfig,
|
||||
) -> DisplayDiagnostic<'c, 'db, 'd> {
|
||||
let resolver = FileResolver::new(db);
|
||||
let display = DisplayDiagnostic::new(&resolver, config, self);
|
||||
writeln!(wtr, "{display}")
|
||||
DisplayDiagnostic::new(resolver, config, self)
|
||||
}
|
||||
|
||||
/// Returns the identifier for this diagnostic.
|
||||
|
|
|
|||
|
|
@ -17,20 +17,31 @@ use super::{
|
|||
Annotation, Diagnostic, DiagnosticFormat, DisplayDiagnosticConfig, Severity, SubDiagnostic,
|
||||
};
|
||||
|
||||
/// A type that implements `std::fmt::Display` for diagnostic rendering.
|
||||
///
|
||||
/// It is created via [`Diagnostic::display`].
|
||||
///
|
||||
/// The lifetime parameters are:
|
||||
///
|
||||
/// * `'c` is the lifetime of the rendering configuration.
|
||||
/// * `'r` is the lifetime of the resolver used to load the contents of `Span`
|
||||
/// values. When using Salsa, this most commonly corresponds to the lifetime
|
||||
/// of a Salsa `Db`.
|
||||
/// * `'d` is the lifetime of the diagnostic being rendered.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct DisplayDiagnostic<'a> {
|
||||
config: &'a DisplayDiagnosticConfig,
|
||||
resolver: &'a FileResolver<'a>,
|
||||
pub struct DisplayDiagnostic<'c, 'r, 'd> {
|
||||
config: &'c DisplayDiagnosticConfig,
|
||||
resolver: FileResolver<'r>,
|
||||
annotate_renderer: AnnotateRenderer,
|
||||
diag: &'a Diagnostic,
|
||||
diag: &'d Diagnostic,
|
||||
}
|
||||
|
||||
impl<'a> DisplayDiagnostic<'a> {
|
||||
impl<'c, 'r, 'd> DisplayDiagnostic<'c, 'r, 'd> {
|
||||
pub(crate) fn new(
|
||||
resolver: &'a FileResolver<'a>,
|
||||
config: &'a DisplayDiagnosticConfig,
|
||||
diag: &'a Diagnostic,
|
||||
) -> DisplayDiagnostic<'a> {
|
||||
resolver: FileResolver<'r>,
|
||||
config: &'c DisplayDiagnosticConfig,
|
||||
diag: &'d Diagnostic,
|
||||
) -> DisplayDiagnostic<'c, 'r, 'd> {
|
||||
let annotate_renderer = if config.color {
|
||||
AnnotateRenderer::styled()
|
||||
} else {
|
||||
|
|
@ -45,7 +56,7 @@ impl<'a> DisplayDiagnostic<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for DisplayDiagnostic<'_> {
|
||||
impl std::fmt::Display for DisplayDiagnostic<'_, '_, '_> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
if matches!(self.config.format, DiagnosticFormat::Concise) {
|
||||
match self.diag.severity() {
|
||||
|
|
@ -65,15 +76,15 @@ impl std::fmt::Display for DisplayDiagnostic<'_> {
|
|||
}
|
||||
write!(f, ":")?;
|
||||
}
|
||||
return write!(f, " {message}", message = self.diag.primary_message());
|
||||
return writeln!(f, " {message}", message = self.diag.primary_message());
|
||||
}
|
||||
|
||||
let resolved = Resolved::new(self.resolver, self.diag);
|
||||
let resolved = Resolved::new(&self.resolver, self.diag);
|
||||
let renderable = resolved.to_renderable(self.config.context);
|
||||
for diag in renderable.diagnostics.iter() {
|
||||
writeln!(f, "{}", self.annotate_renderer.render(diag.to_annotate()))?;
|
||||
}
|
||||
Ok(())
|
||||
writeln!(f)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2130,9 +2141,7 @@ watermelon
|
|||
///
|
||||
/// (This will set the "printed" flag on `Diagnostic`.)
|
||||
fn render(&self, diag: &Diagnostic) -> String {
|
||||
let mut buf = vec![];
|
||||
diag.print(&self.db, &self.config, &mut buf).unwrap();
|
||||
String::from_utf8(buf).unwrap()
|
||||
diag.display(&self.db, &self.config).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue