-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New diagnostics for unused range suppressions #21783
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
Conversation
|
| /// - [Ruff error suppression](https://docs.astral.sh/ruff/linter/#error-suppression) | ||
| #[derive(ViolationMetadata)] | ||
| #[violation_metadata(preview_since = "0.14.9")] | ||
| pub(crate) struct UnusedSuppression; |
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.
Did you create a new rule because that was easier or do you forsee use cases where users want to disable unused block level suppression warnings but not warnings about unused noqa comments?
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.
Both 😅
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.
Having two rules might be confusing to users. I can see how the old rule name isn't great, but the name of this rule is generic enough that a user could think that it also handles noqa comments.
Given that our long-term plan is to merge all suppression comments, I'd lean towards reusing the old rule and renaming it later.
crates/ruff_linter/src/linter.rs
Outdated
| parsed.has_valid_syntax(), | ||
| settings, | ||
| &suppressions, | ||
| &mut suppressions, |
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 we just pass suppressions here (the owned value), given that they aren't used afterwards?
Another alternative would be to store them on LintContext (I don't remember if that would be hard. It's okay to only look at this at the very end. Just floating this as an idea). Ultimately, I think, where we store it probably depends on where we want to use it, e.g. e might need to pass them to a new lint rule that checks for unclosed suppressions)
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 went back and forth a couple times on what pieces should own the creation of the Suppressions object. The biggest problem is that the existing APIs are very inconsistent on what's available where, like how far context/locator/tokens get passed through. I like the idea of adding them to LintContext but that context isn't passed to generate_noqa_edits for example.
14b1a4d to
bc990f1
Compare
|
Not particularly happy with |
One option you have is to use interior mutability by making I don't mind the |
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.
The implementation looks great.
We should add some tests for the new rule that show that the fixes are working as expected. This is the reason why I'm requesting changes.
We should also add some tests demonstrating how you can use ruff:disable to suppress unused-suppression errors within a block.
I'm also leaning towards reusing the existing rules but I'm curious to learn about your motivation for having different rules (and how that expands to the other checks we want to add)
| let code_index = comment | ||
| .codes | ||
| .iter() | ||
| .position(|range| locator.slice(range) == suppression.code) | ||
| .unwrap(); |
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 think we want to store the suppression range on Suppression to correctly handle:
# ruff:disable[RUF100, RUF100]
| /// - [Ruff error suppression](https://docs.astral.sh/ruff/linter/#error-suppression) | ||
| #[derive(ViolationMetadata)] | ||
| #[violation_metadata(preview_since = "0.14.9")] | ||
| pub(crate) struct UnusedSuppression; |
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.
Having two rules might be confusing to users. I can see how the old rule name isn't great, but the name of this rule is generic enough that a user could think that it also handles noqa comments.
Given that our long-term plan is to merge all suppression comments, I'd lean towards reusing the old rule and renaming it later.
bc990f1 to
646ad15
Compare
|
Updated to use Currently reports a separate diagnostic for each code due to the way the Not sure if it's worth reworking the data model before going further on this, or if I should worry about that later, or if you have a better idea of which direction to go. |
That shouldn't be necessary (other than storing the range of the codes?). We use a similar data structure in ty, and we group consecutive unused codes together, which is perfectly fine (it can result in multiple diagnostics if most codes are unused but only creates one diagnostic if all codes are unused) See ruff/crates/ty_python_semantic/src/suppression.rs Lines 260 to 289 in adf468b
We can address this in a follow-up PR (which is also what I did in ty, the initial version didn't support grouping) |
| help: Remove unused suppression | ||
| 45 | # logged to user | ||
| 46 | # ruff: disable[E501] | ||
| 47 | I = 1 | ||
| - # ruff: enable[E501] | ||
| 48 | | ||
| 49 | | ||
| 50 | def f(): | ||
|
|
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.
Let's add some more tests demonstrating some edge cases:
- Duplicate rule codes (it's okay to add a todo)
- Disabling
RUF100 - Overlapping ranges (
ruff: disable[E501followed by anotherruff: disable[E501]) - Multiple codes where only one code is unused
- Multiple codes where only some codes are unused
- Multiple codes were all codes are unused
646ad15 to
2f8d4a4
Compare
|
|
||
|
|
||
| def f(): | ||
| # TODO: Duplicate codes should be counted as duplicate, not unused |
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's fine if one of them counts as unused, for as long as we remove the right one.
…return * dcreager/die-die-intersections: (29 commits) simpler bounds [`pylint`] Detect subclasses of builtin exceptions (`PLW0133`) (#21382) Fix stack overflow with recursive generic protocols (depth limit) (#21858) New diagnostics for unused range suppressions (#21783) [ty] Use default settings in completion tests [ty] Infer type variables within generic unions (#21862) [ty] Fix overload filtering to prefer more "precise" match (#21859) [ty] Stabilize auto-import [ty] Fix reveal-type E2E test (#21865) [ty] Use concise message for LSP clients not supporting related diagnostic information (#21850) Include more details in Tokens 'offset is inside token' panic message (#21860) apply range suppressions to filter diagnostics (#21623) [ty] followup: add-import action for `reveal_type` too (#21668) [ty] Enrich function argument auto-complete suggestions with annotated types [ty] Add autocomplete suggestions for function arguments [`flake8-bugbear`] Accept immutable slice default arguments (`B008`) (#21823) [`pydocstyle`] Suppress `D417` for parameters with `Unpack` annotations (#21816) [ty] Remove legacy `concise_message` fallback behavior (#21847) [ty] Make Python-version subdiagnostics less verbose (#21849) [ty] Supress inlay hints when assigning a trivial initializer call (#21848) ...
…return * dcreager/die-die-intersections: (31 commits) clippy reword comment simpler bounds [`pylint`] Detect subclasses of builtin exceptions (`PLW0133`) (#21382) Fix stack overflow with recursive generic protocols (depth limit) (#21858) New diagnostics for unused range suppressions (#21783) [ty] Use default settings in completion tests [ty] Infer type variables within generic unions (#21862) [ty] Fix overload filtering to prefer more "precise" match (#21859) [ty] Stabilize auto-import [ty] Fix reveal-type E2E test (#21865) [ty] Use concise message for LSP clients not supporting related diagnostic information (#21850) Include more details in Tokens 'offset is inside token' panic message (#21860) apply range suppressions to filter diagnostics (#21623) [ty] followup: add-import action for `reveal_type` too (#21668) [ty] Enrich function argument auto-complete suggestions with annotated types [ty] Add autocomplete suggestions for function arguments [`flake8-bugbear`] Accept immutable slice default arguments (`B008`) (#21823) [`pydocstyle`] Suppress `D417` for parameters with `Unpack` annotations (#21816) [ty] Remove legacy `concise_message` fallback behavior (#21847) ...
…return * dcreager/die-die-intersections: (31 commits) clippy reword comment simpler bounds [`pylint`] Detect subclasses of builtin exceptions (`PLW0133`) (#21382) Fix stack overflow with recursive generic protocols (depth limit) (#21858) New diagnostics for unused range suppressions (#21783) [ty] Use default settings in completion tests [ty] Infer type variables within generic unions (#21862) [ty] Fix overload filtering to prefer more "precise" match (#21859) [ty] Stabilize auto-import [ty] Fix reveal-type E2E test (#21865) [ty] Use concise message for LSP clients not supporting related diagnostic information (#21850) Include more details in Tokens 'offset is inside token' panic message (#21860) apply range suppressions to filter diagnostics (#21623) [ty] followup: add-import action for `reveal_type` too (#21668) [ty] Enrich function argument auto-complete suggestions with annotated types [ty] Add autocomplete suggestions for function arguments [`flake8-bugbear`] Accept immutable slice default arguments (`B008`) (#21823) [`pydocstyle`] Suppress `D417` for parameters with `Unpack` annotations (#21816) [ty] Remove legacy `concise_message` fallback behavior (#21847) ...
* origin/main: (33 commits) [ty] Simplify union lower bounds and intersection upper bounds in constraint sets (#21871) [ty] Collapse `never` paths in constraint set BDDs (#21880) Fix leading comment formatting for lambdas with multiple parameters (#21879) [ty] Type inference for `@asynccontextmanager` (#21876) Fix comment placement in lambda parameters (#21868) [`pylint`] Detect subclasses of builtin exceptions (`PLW0133`) (#21382) Fix stack overflow with recursive generic protocols (depth limit) (#21858) New diagnostics for unused range suppressions (#21783) [ty] Use default settings in completion tests [ty] Infer type variables within generic unions (#21862) [ty] Fix overload filtering to prefer more "precise" match (#21859) [ty] Stabilize auto-import [ty] Fix reveal-type E2E test (#21865) [ty] Use concise message for LSP clients not supporting related diagnostic information (#21850) Include more details in Tokens 'offset is inside token' panic message (#21860) apply range suppressions to filter diagnostics (#21623) [ty] followup: add-import action for `reveal_type` too (#21668) [ty] Enrich function argument auto-complete suggestions with annotated types [ty] Add autocomplete suggestions for function arguments [`flake8-bugbear`] Accept immutable slice default arguments (`B008`) (#21823) ...
Adds new diagnostics for reporting unused range suppressions.
noqaor "suppression" in the description and fix title.Suppressionssystem to track whether individual suppressions/codes have been "used", and then report appropriat RUF100 diagnostics for unused suppressions/codes.Issue #3711