Skip to content

Conversation

@ntBre
Copy link
Contributor

@ntBre ntBre commented May 13, 2025

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 #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

ntBre added 5 commits May 13, 2025 14:03
instead of storing the DiagnosticKind to construct a title later
avoid DiagnosticKind in blocking_process_invocation

avoid DiagnosticKind in suspicious_function_call

avoid DiagnosticKind in function_call_in_argument_default

avoid DiagnosticKind in typing_only_runtime_import

avoid DiagnosticKind in unused_arguments

avoid DiagnosticKind in replaceable_by_pathlib

avoid DiagnosticKind in pandas_vet rules

avoid DiagnosticKind in invalid_first_argument_name

avoid DiagnosticKind in indentation

avoid DiagnosticKind in missing_whitespace_around_operator

avoid DiagnosticKind in invalid_string_characters

avoid DiagnosticKind in no_method_decoroator

avoid DiagnosticKind in use_pep604_annotation

avoid DiagnosticKind in ambiguous_unicode_character

avoid DiagnosticKind in some tests
@ntBre ntBre added the diagnostics Related to reporting of diagnostics. label May 13, 2025
@github-actions
Copy link
Contributor

github-actions bot commented May 13, 2025

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

Formatter (stable)

✅ ecosystem check detected no format changes.

Formatter (preview)

✅ ecosystem check detected no format changes.

ntBre added a commit that referenced this pull request May 13, 2025
Summary
--

This PR is stacked on #18074 and uses the
separation between `CacheMessage` and the other diagnostic types added there to
store a `Rule` directly on `CacheMessage` and convert it back to a `&'static
str` for use by `Diagnostic` and `DiagnosticMessage`.

I think what we really want is to use only the kebab-case names everywhere, but
I don't think we can accomplish that with `Diagnostic::new` living in the
`ruff_diagnostics` crate, and the proc macros being called in `ruff_linter`.
`Diagnostic::new` relies on `ViolationMetadata::rule_name`, which just calls
`stringify!(#name)`.

Test Plan
--

Existing tests
@ntBre ntBre marked this pull request as ready for review May 13, 2025 21:26
@ntBre ntBre requested a review from MichaReiser May 13, 2025 21:26
Copy link
Member

@MichaReiser MichaReiser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good. I only skimmed through and I've one comment related to code size/compile time.

Comment on lines 469 to 476
impl AsRule for ruff_diagnostics::Diagnostic {
fn rule(&self) -> Rule {
match self.name.as_str() {
#from_impls_for_diagnostic_kind
_ => unreachable!("invalid rule name: {}", self.name),
}
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By how much does this increase the code size, considering that this is a pretty large match?

Should we instead implement TryFrom<&str> for Rule and the AsRule impl for Diagnostic and DiagnosticMessagte both call Rule::try_from(&self.name).or_else(|| panic!("invalid rule name: {}", self.name))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh good question. There's even a strum macro for generating a FromStr (and TryFrom<&str>) implementation that I used in one of my drafts, so we can definitely switch to that if you prefer. I guess there's no reason not to do that, unless we're worried about people calling Rule::from_str directly.

@MichaReiser MichaReiser added the internal An internal refactor or improvement label May 14, 2025
ntBre and others added 4 commits May 14, 2025 16:26
This PR is stacked on #18074 and
uses the
separation between `CacheMessage` and the other diagnostic types added
there to
store a `Rule` directly on `CacheMessage` and convert it back to a
`&'static
str` for use by `Diagnostic` and `DiagnosticMessage`.

In the first commit, I added a generated `Rule::pascal_name` method for
converting
back to the Pascal-case name currently used by `Diagnostic` and
`DiagnosticMessage`,
but in the second commit I used the `heck` crate to generalize our
existing `kebab_case`
macro to convert the `ViolationMetadata::rule_name` output to kebab-case
and use
kebab-case everywhere. `heck` was already in our dependency graph
because it's what
`strum` uses internally for case conversions.

I think that's probably preferable long-term, but it might be a breaking
change in
the LSP because the lint name is used as the title for a quick fix, if a
`suggestion` is
unavailable. Otherwise `Diagnostic::name` is only used for `debug!`
logging.

Test Plan
--

Existing tests
@ntBre ntBre merged commit e2c5b83 into main May 15, 2025
34 checks passed
@ntBre ntBre deleted the brent/inline-diagnostic-kind branch May 15, 2025 14:27
@ntBre ntBre mentioned this pull request May 15, 2025
Glyphack pushed a commit to Glyphack/ruff that referenced this pull request May 21, 2025
## 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 astral-sh#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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

diagnostics Related to reporting of diagnostics. internal An internal refactor or improvement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants