-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Hide empty snippets for full-file diagnostics #19653
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
CodSpeed Instrumentation Performance ReportMerging #19653 will not alter performanceComparing Summary
|
|
1e1bd62 to
1cdb26c
Compare
8a027bb to
f4e93b6
Compare
MichaReiser
left a comment
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.
Thank you. The approach looks good to me but I'm unsure about the ruff integration
|
|
||
| let is_file_level = snippet.annotations.iter().any(|ann| ann.is_file_level); | ||
| if is_file_level { | ||
| let header = format_header(origin, main_range, &[], is_first); |
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.
Nit: Would it make sense to add an assertion that the snippet has no body (e.g no associated message?)
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.
Sure, some kind of assertion makes sense to me. I think we can assert that the snippet source is empty, I'll just have to rework the test to avoid using the builder, which expects a non-empty snippet. It looks like Ruff's real diagnostics that will go through this path should already have empty snippets. We could also check that the annotation labels are empty (the text after ^^^), but I think those are always empty for us right now.
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 RenderableSnippet::new might try to expand the snippet to the usual number of context lines, unless we also check is_file_level there. We might have to remove or update the assertion when running this in #19415, but I'll add it for now. It'll be a good reminder to revisit it.
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.
Oh, maybe that's in line with your suggestion about applying this per-rule. I guess we shouldn't render one of these except in cases where the snippet isn't available, like an io-error!
crates/ruff_db/src/diagnostic/mod.rs
Outdated
| /// When set, rendering will not include a file snippet but will still have the file's name and | ||
| /// (optional) range. |
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.
We should mention that this also omits the annotation's message. Or we could phrase it differently and say that everything other than the file name and range are omitted.
| self.tags.push(tag); | ||
| } | ||
|
|
||
| pub fn set_file_level(&mut self, yes: bool) { |
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.
Can we document the meaning of a file level annotation here too
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.
Good idea, I added a note here about Span too, referring to this section of the Span docs:
ruff/crates/ruff_db/src/diagnostic/mod.rs
Lines 1080 to 1084 in e7e7b7b
| /// It consists of a `File` and an optional range into that file. When the | |
| /// range isn't present, it semantically implies that the diagnostic refers to | |
| /// the entire file. For example, when the file should be executable but isn't. | |
| #[derive(Debug, Clone, PartialEq, Eq, Hash, get_size2::GetSize)] | |
| pub struct Span { |
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 get a TODO that it ought to be removed in favor of Ruff diagnostics being updated to use a None span?
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 that's a good point. I added an explicit TODO in the code here and also wrote some notes from looking into the options today: #19688 (comment). In short, I thought we would handle this with a None range on the span, but I think you're right that we should omit the span entirely instead.
It might be a bit tangential to the main issue in #19688, but at least it's recorded somewhere, and I can spin it off later if needed.
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 this at least gives us a possible path toward eventually merging back with upstream.
| let mut annotation = Annotation::primary(span); | ||
| // The `0..0` range is used to highlight file-level diagnostics. | ||
| if range == TextRange::default() { | ||
| annotation.set_file_level(true); | ||
| } |
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.
Would it be much more work to instead change the rules that add file level diagnostics rather than doing this "global" override?
(the rule would have to mutate the Diagnostic after reporting it with report_diagnostic).
The reason I'd prefer this is that it makes it more apparent where we rely on this behavior and it doesn't prevent other rules to use an empty range (e.g. what if we had a rule that enforces module level docstrings. That rule would probably ask you to insert the docstring at 0:0.
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 that's a great idea! We actually do have rules like you're describing. I think at least one import rule suggests adding an import at the top of the file (probably a __future__ import rule). It might be easier to handle that in #19415 as I'm going through the snapshots, but I can revert this for now.
You're right about the syntax errors too, I don't think we have any file-level ones. That was just for consistency with the current version.
On second thought, we might want to hold off on this until we can cache the Annotations. I don't think set_file_level will be cached currently.
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.
On second thought, we might want to hold off on this until we can cache the Annotations. I don't think set_file_level will be cached currently.
I'm not sure I understand what you mean by caching.
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.
(also discussed on Discord, just recording here for future reference)
For caching, I just mean in ruff's diagnostic cache. I think we would lose the is_file_level field on the annotation when converting to a CacheMessage
I'll drop the syntax error check because that shouldn't affect any real diagnostics and open an issue to follow up on this after a caching 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.
Let's maybe add a TODO here too
| let mut annotation = Annotation::primary(span); | ||
| // The `0..0` range is used to highlight file-level diagnostics. | ||
| if range == TextRange::default() { | ||
| annotation.set_file_level(true); | ||
| } |
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 maybe add a TODO here too
| self.tags.push(tag); | ||
| } | ||
|
|
||
| pub fn set_file_level(&mut self, yes: bool) { |
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 get a TODO that it ought to be removed in favor of Ruff diagnostics being updated to use a None span?
01c8ac8 to
4603fc8
Compare
Summary -- Fixes a snapshot test failure I saw in #19653 locally and in Windows CI by padding the hex ID to 16 digits to match the regex in `filter_result_id`. https://github.com/astral-sh/ruff/blob/78e5fe0a51fcbb1456d54c65b4632f60c268e389/crates/ty_server/tests/e2e/pull_diagnostics.rs#L380-L384 Test Plan -- I applied this to the branch from #19653 locally and saw that the tests now pass. I couldn't reproduce this failure directly on `main` or this branch, though.
Summary -- Fixes a snapshot test failure I saw in #19653 locally and in Windows CI by padding the hex ID to 16 digits to match the regex in `filter_result_id`. https://github.com/astral-sh/ruff/blob/78e5fe0a51fcbb1456d54c65b4632f60c268e389/crates/ty_server/tests/e2e/pull_diagnostics.rs#L380-L384 Test Plan -- I applied this to the branch from #19653 locally and saw that the tests now pass. I couldn't reproduce this failure directly on `main` or this branch, though.
Summary -- This isn't really polished for review yet, but this is the other commit I wanted to spin off from #19415. This suppresses empty snippets for empty ranges at the very beginning of a file, and for empty ranges in non-existent files. Ruff includes empty ranges for IO errors, for example. Test Plan -- TODO add a `ruff_db` test with an example
We do need a single character because the diagnostic builder does some subtraction on the range, but conceptually this can be a completely empty or non-existent file, as can be the case in Ruff.
also construct the test span manually to avoid some non-empty snippet assumptions in `TestEnvironment::span`
we don't currently have any file-level syntax errors, so this wasn't having any effect
4603fc8 to
2cfad84
Compare
Summary
This is the other commit I wanted to spin off from #19415, currently stacked on #19644.
This PR suppresses blank snippets for empty ranges at the very beginning of a file, and for empty ranges in non-existent files. Ruff includes empty ranges for IO errors, for example.
ruff/crates/ruff_linter/src/message/text.rs
Lines 100 to 110 in f4e93b6
The diagnostics now look like this (new snapshot test):
Instead of 1
Test Plan
A new
ruff_dbtest showing the expected output formatFootnotes
This doesn't correspond precisely to the example in the PR because of some details of the diagnostic builder helper methods in
ruff_db, but you can see another example in the current version of the summary in Move full diagnostic rendering toruff_db#19415. ↩