-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Display fixes by default (#7352) #12595
Conversation
|
Use the existing `printer::Flags::SHOW_FIX_DIFF` to enable printing fixable diffs in `check` mode automatically. Enable it whenever the output format is `Full`, but keep a distinct flag for it (a) because output format and whether to print diffs are really separate concerns, (b) because it makes it easy to make changes to what sets the flag to true if/as that is needful, and (c) because it minimally perturbs the rest of the code. This does not introduce *new* tests, but does update the existing tests to account for the new default output.
@@ -1523,7 +1581,17 @@ fn check_hints_hidden_unsafe_fixes() { | |||
exit_code: 1 | |||
----- stdout ----- | |||
-:1:1: RUF901 [*] Hey this is a stable test rule with a safe fix. | |||
Suggested fix: |
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.
It looks like we need to do something special for violations without help messages? We want a dedicated test case for that and a test case for violations without source context.
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.
Ah, I missed that one. I’ll see about adding a test for those. What’s a scenario where you would end up without source context?
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.
Well, for example, there's no source context for this test rule right? I think if the violation is attached to an empty range we elide the source context. This behavior was recently modified in #12304
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'm going to open a new issue tracking what to do in each of those cases, with the existing baseline implementation here as a useful starting point.
- For missing help: Require rules with fixes to include help message #12599
- For missing source: Design display of fixes in
check
when there is no source #12600
Suggested fix: | ||
1 |+# fix from stable-test-rule-safe-fix | ||
|
||
Run `ruff check --fix` to apply this fix. |
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.
Looking at this more holistically, I wonder if this message is necessary since we have a call to action at the end:
[*] 1 fixable with the
--fix
option (1 hidden fix can be enabled with the--unsafe-fixes
option).
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 saw that as well, but my intuition was that it is helpful to have both the details and the summary.
Suggested fix: | ||
1 |+# fix from stable-test-rule-unsafe-fix | ||
|
||
Run `ruff check --fix --unsafe-fixes` to apply this unsafe fix. |
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.
Given the message below this ("1 hidden fix..."), I wonder if we should be hiding unsafe fixes unless the opt-in is provided. I think this would solve the "how do we display applicability" problem, to an extent?
If so, I think we could figure out what to do with "display-only" fixes later and just never show them to start (to limit the scope of this pull request)
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.
This would require a bit of futzing to retain the existing coverage in our test suite, maybe just using --unsafe-fixes
by default in some places?
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.
Hmm, yeah—I can definitely back out those parts of the change if that’s preferable!
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.
It feels like the current design (prior to this pull request) hides unsafe fixes and allowing opt-in to their display, at which point we don't need to indicate that they're unsafe? It seems easiest to follow that pattern for now and consider if and how we want to display unsafe fixes by default separately, i.e., I think more discussion in an issue would be prudent.
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.
In terms of handling applicability, we could do that in a couple of ways:
- The
Diff
itself could take a configuration level and itsDisplay
implementation could use that to decide what to print. - The caller could decide whether to print based on message applicability at a higher level, keeping it out of the
Diff
.
The latter is a slightly smaller scope and IMO better isolation of concerns; it keeps it properly in the TextEmitter
, whereas the Diff
can be concerned entirely with the presentation of a given diff.
If we go that way, we still have the choice whether to keep the applicability message in the diff. I think I am still mildly inclined toward showing that CTA, because of the differences when you do include --unsafe-fixes
; it seems like it would still be nice to know which changes are which.
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.
It seems reasonable to decide whether or not the Diff
should be displayed outside its display implementation (the latter option).
Regarding the CTA, I have a preference for splitting it out of this pull request so we can merge this sooner and have focused discussion on each objective, like:
- Display available fixes by default
- Disambiguate safe and unsafe fixes when displayed (i.e., via a CTA or other label)
- Display unsafe fixes by default (needs discussion)
- Determine how to make display-only fixes user-facing
What do you think?
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.
That makes good sense to me. I will split out issues (Edit: #12598) for further discussion on those points and update this to simply display fixes only for the Applicability::Safe
level, in a slightly clunky way that is amenable to cleaning up by way of broader refactors once some of those other design questions are fleshed out.
There are some open design questions about how the calls to action should work for unsafe and display-only fixes, so leave them aside for now. This hard-codes that behavior into the `Display` implementation, but with a tracking issue for moving that up to the `TextEmitter`, and also includes a TODO with a tracking issue for the design of the CTAs.
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'm concerned about the fact that this change removes all test coverage for unsafe fixes. I don't think we should land this before recovering the test coverage.
@@ -287,6 +287,9 @@ pub fn check(args: CheckCommand, global_options: GlobalConfigArgs) -> Result<Exi | |||
if show_fixes { | |||
printer_flags |= PrinterFlags::SHOW_FIX_SUMMARY; | |||
} | |||
if output_format == OutputFormat::Full { |
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 this be gated behind preview mode to get some user feedback before enabling it for everyone?
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 it's strictly necessary, but we may want to do so if it's going to change significantly (i.e. by being split into follow-ups)
// TODO: Instead of hard-coding this in, the `TextEmitter` should be | ||
// handling it. See https://github.com/astral-sh/ruff/issues/12597 for | ||
// further discussion. | ||
if matches!( | ||
self.fix.applicability(), | ||
Applicability::Unsafe | Applicability::DisplayOnly | ||
) { | ||
return Ok(()); | ||
} |
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.
Does this mean that we won't see unsafe fixes in snapshot tests anymore?
I would find this concerning because it means we loose all test coverage for unsafe fixes (of which there are plenty)
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.
Yes, we need to address this before merging.
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.
Yeah, we realized this late in our time working on it yesterday. It may warrant going ahead and doing the bit I highlighted in #12597, etc. I think this was a case where trying to keep the change minimal actually makes it harder to land—this particularly bit of coupling wasn’t obvious to me until the very end when we changed from including all the CTAs to including none of them, and turning off.
I think it probably needs the aforementioned refactor (where the TextEmitter
handles what to print or not) plus setting the relevant flags based on both --unsafe-fixes
and whether it is testing.
Summary
Use the existing
printer::Flags::SHOW_FIX_DIFF
to enable printing fixable diffs incheck
mode automatically. Enable it whenever the output format isFull
, but keep a distinct flag for it (a) because output format and whether to print diffs are really separate concerns, (b) because it makes it easy to make changes to what sets the flag to true if/as that is needful, and (c) because it minimally perturbs the rest of the code.Fixes #7352.
Details
This changes the result of running
ruff check
by adding the diff for possible fixes, and adds calls to action for those messages.Note that this currently displays only safe fixes to users. There are a number of design questions around when and how to display them; see #12598.
a file with three unused imports
Input:
Output:
The test file
crates/ruff_linter/resources/test/fixtures/flake8_pyi/PYI025_1.pyi
New output:
Test Plan
This does not introduce new tests, but does update the existing tests to account for the new default output. Of particular interest among the many snapshots, see the updated snapshot for
PYI025_1.pyi
]snap, which does some truncation of diffs.