Inline DiagnosticKind into other diagnostic types (#18074)

## Summary

This PR deletes the `DiagnosticKind` type by inlining its three fields
(`name`, `body`, and `suggestion`) into three other diagnostic types:
`Diagnostic`, `DiagnosticMessage`, and `CacheMessage`.

Instead of deferring to an internal `DiagnosticKind`, both `Diagnostic`
and `DiagnosticMessage` now have their own macro-generated `AsRule`
implementations.

This should make both https://github.com/astral-sh/ruff/pull/18051 and
another follow-up PR changing the type of `name` on `CacheMessage`
easier since its type will be able to change separately from
`Diagnostic` and `DiagnosticMessage`.

## Test Plan

Existing tests
This commit is contained in:
Brent Westbrook 2025-05-15 10:27:21 -04:00 committed by GitHub
parent b35bf8ae07
commit e2c5b83fe1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
41 changed files with 604 additions and 621 deletions

View file

@ -1,35 +1,29 @@
use anyhow::Result;
use log::debug;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use ruff_text_size::{Ranged, TextRange, TextSize};
use crate::Fix;
use crate::{Fix, Violation};
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct DiagnosticKind {
pub struct Diagnostic {
/// The identifier of the diagnostic, used to align the diagnostic with a rule.
pub name: String,
pub name: &'static str,
/// The message body to display to the user, to explain the diagnostic.
pub body: String,
/// The message to display to the user, to explain the suggested fix.
pub suggestion: Option<String>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Diagnostic {
pub kind: DiagnosticKind,
pub range: TextRange,
pub fix: Option<Fix>,
pub parent: Option<TextSize>,
}
impl Diagnostic {
pub fn new<T: Into<DiagnosticKind>>(kind: T, range: TextRange) -> Self {
pub fn new<T: Violation>(kind: T, range: TextRange) -> Self {
Self {
kind: kind.into(),
name: T::rule_name(),
body: Violation::message(&kind),
suggestion: Violation::fix_title(&kind),
range,
fix: None,
parent: None,
@ -56,7 +50,7 @@ impl Diagnostic {
pub fn try_set_fix(&mut self, func: impl FnOnce() -> Result<Fix>) {
match func() {
Ok(fix) => self.fix = Some(fix),
Err(err) => debug!("Failed to create fix for {}: {}", self.kind.name, err),
Err(err) => debug!("Failed to create fix for {}: {}", self.name, err),
}
}
@ -67,7 +61,7 @@ impl Diagnostic {
match func() {
Ok(None) => {}
Ok(Some(fix)) => self.fix = Some(fix),
Err(err) => debug!("Failed to create fix for {}: {}", self.kind.name, err),
Err(err) => debug!("Failed to create fix for {}: {}", self.name, err),
}
}

View file

@ -1,4 +1,4 @@
pub use diagnostic::{Diagnostic, DiagnosticKind};
pub use diagnostic::Diagnostic;
pub use edit::Edit;
pub use fix::{Applicability, Fix, IsolationLevel};
pub use source_map::{SourceMap, SourceMarker};

View file

@ -1,4 +1,3 @@
use crate::DiagnosticKind;
use std::fmt::{Debug, Display};
#[derive(Debug, Copy, Clone)]
@ -79,16 +78,3 @@ impl<V: AlwaysFixableViolation> Violation for V {
<Self as AlwaysFixableViolation>::message_formats()
}
}
impl<T> From<T> for DiagnosticKind
where
T: Violation,
{
fn from(value: T) -> Self {
Self {
body: Violation::message(&value),
suggestion: Violation::fix_title(&value),
name: T::rule_name().to_string(),
}
}
}