-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Drop Violation::placeholder
#1996
Drop Violation::placeholder
#1996
Conversation
774e3e2
to
ba68ce8
Compare
ruff_dev/src/generate_rules_table.rs
Outdated
let fix_token = match rule.autofixable() { | ||
Autofixability::Never => "", | ||
Autofixability::Sometimes => "🛠 (sometimes)", | ||
Autofixability::Always => "🛠", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Unrelatedly: the use of the actual format strings is not only simpler for maintenance but so much clearer for users. Nice job.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough I have removed the display of "(sometimes)".
@@ -1,3 +1,23 @@ | |||
//! Checks for unused loop variables. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should these include the rule code at the end, like you did in the DTZ examples?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so. I think my goal is to centrally define all rule codes within a single file (including many to many mappings) and have our documentation generator combine these doc comments with the codes from that file.
I just included the codes in the datetimez comments since they were there previously ... but I don't think it really matters there since I think the datetimez rule implementations should ultimately be replaced by #1507.
(I still have to think about how to best implement the documentation generation from such doc comments ... but that's out of the scope of this PR.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mostly find those comments useful for grep. E.g., if someone reports a bug in SIM109
, it's useful to be able to search /// SIM109
and jump to the definition. I think there's some value in making that easy, since even if we move away from those codes internally, they'll still pop up in issue reports and such. (It doesn't matter to me that they're in the rustdoc or not.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right I think we could end up having a cargo dev jump SIM109
command that would print where the respective rule is defined (if we end up no longer defining them next to the functions).
It doesn't matter to me that they're in the rustdoc or not.
The plan is that such doc comments will become the user documentation.
quote! { | ||
#func | ||
fn message_formats() -> &'static [&'static str] { | ||
&[#strings] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the failure mode in the event that a violation doesn't contain a format string?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Compilation fails with a nice error message:
error: expected last expression to be a format! macro or a match block
--> src/violations.rs:539:9
|
539 | "foo".to_string()
| ^^^^^
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perfect.
This commit series removes the following associated function from the Violation trait: fn placeholder() -> Self; ruff previously used this placeholder approach for the messages it listed in the README and displayed when invoked with --explain <code>. This approach is suboptimal for three reasons: 1. The placeholder implementations are completely boring code since they just initialize the struct with some dummy values. 2. Displaying concrete error messages with arbitrary interpolated values can be confusing for the user since they might not recognize that the values are interpolated. 3. Some violations have varying format strings depending on the violation which could not be documented with the previous approach (while we could have changed the signature to return Vec<Self> this would still very much suffer from the previous two points). We therefore drop Violation::placeholder in favor of a new macro-based approach, explained in commit 4/5. Violation::placeholder is only invoked via Rule::kind, so we firstly have to get rid of all Rule::kind invocations ... this commit starts removing the trivial cases.
While ruff displays the string returned by Violation::message in its output for detected violations the messages displayed in the README and in the `--explain <code>` output previously used the DiagnosticKind::summary() function which for some verbose messages provided shorter descriptions. This commit removes DiagnosticKind::summary, and moves the more extensive documentation into doc comments ... these are not displayed yet to the user but doing that is very much planned.
ruff_dev::generate_rules_table previously documented which rules are autofixable via DiagnosticKind::fixable ... since the DiagnosticKind was obtained via Rule::kind (and Violation::placeholder) which we both want to get rid of we have to obtain the autofixability via another way. This commit implements such another way by adding an AUTOFIX associated constant to the Violation trait. The constant is of the type Option<AutoFixkind>, AutofixKind is a new struct containing an Availability enum { Sometimes, Always}, letting us additionally document that some autofixes are only available sometimes (which previously wasn't documented). We intentionally introduce this information in a struct so that we can easily introduce further autofix metadata in the future such as autofix applicability[1]. [1]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_errors/enum.Applicability.html
The idea is nice and simple we replace: fn placeholder() -> Self; with fn message_formats() -> &'static [&'static str]; So e.g. if a Violation implementation defines: fn message(&self) -> String { format!("Local variable `{name}` is assigned to but never used") } it would also have to define: fn message_formats() -> &'static [&'static str] { &["Local variable `{name}` is assigned to but never used"] } Since we however obviously do not want to duplicate all of our format strings we simply introduce a new procedural macro attribute #[derive_message_formats] that can be added to the message method declaration in order to automatically derive the message_formats implementation. This commit implements the macro. The following and final commit updates violations.rs to use the macro. (The changes have been separated because the next commit is autogenerated via a Python script.)
# This commit has been generated via the following Python script: # (followed by `cargo +nightly fmt` and `cargo dev generate-all`) # For the reasoning see the previous commit(s). import re import sys for path in ( 'src/violations.rs', 'src/rules/flake8_tidy_imports/banned_api.rs', 'src/rules/flake8_tidy_imports/relative_imports.rs', ): with open(path) as f: text = '' while line := next(f, None): if line.strip() != 'fn message(&self) -> String {': text += line continue text += ' #[derive_message_formats]\n' + line body = next(f) while (line := next(f)) != ' }\n': body += line # body = re.sub(r'(?<!code\| |\.push\()format!', 'format!', body) body = re.sub( r'("[^"]+")\s*\.to_string\(\)', r'format!(\1)', body, re.DOTALL ) body = re.sub( r'(r#".+?"#)\s*\.to_string\(\)', r'format!(\1)', body, re.DOTALL ) text += body + ' }\n' while (line := next(f)).strip() != 'fn placeholder() -> Self {': text += line while (line := next(f)) != ' }\n': pass with open(path, 'w') as f: f.write(text)
ba68ce8
to
cb7463b
Compare
I have just changed the associated constant introduced in the 3rd commit from: const AUTOFIXABLE: Autofixability = Autofixability::Never; to const AUTOFIX: Option<AutofixKind> = None; so that we can easily introduce another field for applicability (#1997) in the future :) |
You're doing so much good work on pushing these abstractions forward. These are highly complex changes and you're handling them expertly. It's much appreciated. |
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [ruff](https://togithub.com/charliermarsh/ruff) | `^0.0.226` -> `^0.0.227` | [![age](https://badges.renovateapi.com/packages/pypi/ruff/0.0.227/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/pypi/ruff/0.0.227/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/pypi/ruff/0.0.227/compatibility-slim/0.0.226)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/pypi/ruff/0.0.227/confidence-slim/0.0.226)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes <details> <summary>charliermarsh/ruff</summary> ### [`v0.0.227`](https://togithub.com/charliermarsh/ruff/releases/tag/v0.0.227) [Compare Source](https://togithub.com/charliermarsh/ruff/compare/v0.0.226...v0.0.227) #### What's Changed - Drop `RuleCode` in favor of `Rule` enum with human-friendly names by [@​not-my-profile](https://togithub.com/not-my-profile) in [https://github.com/charliermarsh/ruff/pull/1941](https://togithub.com/charliermarsh/ruff/pull/1941) - Make define_rule_mapping! set rule code as doc comment of variants by [@​not-my-profile](https://togithub.com/not-my-profile) in [https://github.com/charliermarsh/ruff/pull/1991](https://togithub.com/charliermarsh/ruff/pull/1991) - Added pylint formatter by [@​damienallen](https://togithub.com/damienallen) in [https://github.com/charliermarsh/ruff/pull/1995](https://togithub.com/charliermarsh/ruff/pull/1995) - Preserve unmatched comparators in `SIM109` by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/1998](https://togithub.com/charliermarsh/ruff/pull/1998) - Drop `Violation::placeholder` by [@​not-my-profile](https://togithub.com/not-my-profile) in [https://github.com/charliermarsh/ruff/pull/1996](https://togithub.com/charliermarsh/ruff/pull/1996) - Apply #\[derive(Default)] fixes suggested by Clippy by [@​akx](https://togithub.com/akx) in [https://github.com/charliermarsh/ruff/pull/2000](https://togithub.com/charliermarsh/ruff/pull/2000) - Avoid `SIM201` and `SIM202` errors in `__ne__` et al by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/2001](https://togithub.com/charliermarsh/ruff/pull/2001) - Fix that --explain panics by [@​not-my-profile](https://togithub.com/not-my-profile) in [https://github.com/charliermarsh/ruff/pull/2002](https://togithub.com/charliermarsh/ruff/pull/2002) - Split up pydocstyle rules by [@​akx](https://togithub.com/akx) in [https://github.com/charliermarsh/ruff/pull/2003](https://togithub.com/charliermarsh/ruff/pull/2003) - Add RUF005 "unpack instead of concatenating" check by [@​akx](https://togithub.com/akx) in [https://github.com/charliermarsh/ruff/pull/1957](https://togithub.com/charliermarsh/ruff/pull/1957) - Enable autofix for `FitsOnOneLine` (`D200`) by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/2006](https://togithub.com/charliermarsh/ruff/pull/2006) - Change AsRef<str> impl for Rule to kebab-case by [@​not-my-profile](https://togithub.com/not-my-profile) in [https://github.com/charliermarsh/ruff/pull/2009](https://togithub.com/charliermarsh/ruff/pull/2009) - Upgrade RustPython by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/2011](https://togithub.com/charliermarsh/ruff/pull/2011) - Avoid SIM401 in `elif` blocks by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/2012](https://togithub.com/charliermarsh/ruff/pull/2012) - Improve --explain output by [@​not-my-profile](https://togithub.com/not-my-profile) in [https://github.com/charliermarsh/ruff/pull/2010](https://togithub.com/charliermarsh/ruff/pull/2010) - Avoid checking row types for single-name [@​parametrize](https://togithub.com/parametrize) decorators by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/2013](https://togithub.com/charliermarsh/ruff/pull/2013) #### New Contributors - [@​damienallen](https://togithub.com/damienallen) made their first contribution in [https://github.com/charliermarsh/ruff/pull/1995](https://togithub.com/charliermarsh/ruff/pull/1995) **Full Changelog**: astral-sh/ruff@v0.0.226...v0.0.227 </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://app.renovatebot.com/dashboard#github/ixm-one/pytest-cmake-presets). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNC4xMDUuNCIsInVwZGF0ZWRJblZlciI6IjM0LjEwNS40In0=--> Signed-off-by: Renovate Bot <bot@renovateapp.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR removes the following associated function from the Violation trait:
ruff previously used this placeholder approach for the messages it
listed in the README and displayed when invoked with
--explain <code>
.This approach is suboptimal for three reasons:
The placeholder implementations are completely boring code since they
just initialize the struct with some dummy values.
Displaying concrete error messages with arbitrary interpolated values
can be confusing for the user since they might not recognize that the
values are interpolated.
Some violations have varying format strings depending on the
violation which could not be documented with the previous approach
(while we could have changed the signature to return Vec this
would still very much suffer from the previous two points).
We therefore drop Violation::placeholder in favor of a new macro-based
approach, explained in commit 4/5.
For the details please refer to the individual commit messages.