-
Notifications
You must be signed in to change notification settings - Fork 901
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
Backport: Do not touch module with #![rustfmt::skip] (4297) #5094
Conversation
Thanks! Code changes look fine, though I have two asks:
On the testing front, I'd advise utilizing the model I've started adding for module resolution related testing (see https://github.com/rust-lang/rustfmt/blob/master/src/test/mod_resolver.rs) for more targeted and explicit validation. One of the challenges we saw historically with trying to use the system/idempotence based checks is that it was far too easy for the absence of a failure to be specious and our tests weren't catching mod resolution/skipping issues, especially with imported/nested files. That happened typically because the out of line file(s) had to be explicitly added to the skip list used for the system/idempotence tests, and there was no way of differentiating between the testing skip list vs. the ignore behavior. |
whoops that definitely shouldn't have been included. will remove right away!
Sure! I can definitely add some additional test, and thanks for explaining all the nuance of properly testing skipping. I'll let you know if I have any questions. |
src/formatting.rs
Outdated
.into_iter() | ||
.filter(|(_, module)| !contains_skip(module.attrs())); |
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.
Actually I think I changed my mind sorry. Instead of having filtering scattered about in multiple places, I'd like to consolidate it in one place (there's several other checks on lines 114-119). It would probably be best to add filtering iterations after line 102/105 so that the reported duration of parsing is as closely confined to the parsing pass as possible, but I don't feel too strongly about it.
Given the ever expanding list of conditional checks, it would probably be best to pull things out into some sort of function though so it's easy to see/add more checks in the future
ad69578
to
f82070c
Compare
|
f82070c
to
66b8fe1
Compare
I suspect this is due to the attribute placed on the main input file which gets handled a bit differently. One of the things on my todo list is to enhance the resolution process to take more "ignore" type information into account up front, but there's still some pending discussion to be had around whether ignore means "parse and discover, but don't format" or "completely ignore me altogether and don't even attempt to parse me" |
@@ -5,6 +5,7 @@ use std::io::{self, Write}; | |||
use std::time::{Duration, Instant}; | |||
|
|||
use rustc_ast::ast; | |||
use rustc_ast::AstLike; |
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 gather this is indeed needed otherwise the deny warnings compiler lint would've caused build failures, though curious what we need this for?
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 need the trait rustc_ast::AstLike
to be in scope to write module.attrs()
. Here's the error message you get if you remove the use statement
and run cargo check
--> src\formatting.rs:70:29
|
70 | if contains_skip(module.attrs()) {
| ^^^^^ method not found in `&Module<'_>`
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
3 | use crate::rustc_ast::AstLike;
|
src/formatting.rs
Outdated
fn should_skip_module<T: FormatHandler>( | ||
config: &Config, | ||
context: &FormatContext<'_, T>, | ||
input_is_stdin: bool, | ||
main_file: &FileName, | ||
path: &FileName, | ||
module: &Module<'_>, | ||
) -> bool { | ||
if contains_skip(module.attrs()) { | ||
return true; | ||
} | ||
|
||
let source_file = context.parse_session.span_to_file_contents(module.span); | ||
let src = source_file.src.as_ref().expect("SourceFile without src"); | ||
|
||
let should_ignore = (!input_is_stdin && context.ignore_file(&path)) | ||
|| (!config.format_generated_files() && is_generated_file(src)); | ||
|
||
if (config.skip_children() && path != main_file) || should_ignore { | ||
return true; | ||
} | ||
|
||
false | ||
} |
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.
Thanks for pulling this out, think it makes things much more clear. I realize what you've done here is identical to what was there before, though as I'm looking at this I feel like we could maybe clean it up a bit more?
For example, we could use the same type of early return pattern utilized with contains_skip
in the function opening for a file based input that's ignored, and save the span_to_file_contents
and src.as_ref()
calls when those conditions are 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.
I reorganized the should_skip_module
function so now we only call span_to_file_contents
and src.as_ref()
when they are needed.
@@ -251,6 +255,7 @@ fn configuration_snippet_tests() { | |||
let blocks = get_code_blocks(); | |||
let failures = blocks | |||
.iter() | |||
.filter(|block| !block.fmt_skip()) |
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.
Was this change related/necessary for the fix? It seems reasonable enough but wasn't sure if it was just an add on
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 it was needed. The tests fail otherwise. The original PR (4297) ran into a similar issue, and here's how they chose to fix it. The test code has changed a bit since (4297) was opened, but the comment in the commit is insightful as to what's happening and why we need to skip checking these code blocks.
Let me know if you have another suggestions for fixing the test.
Although the implementation is slightly different than the original PR, the general idea is the same. After collecting all modules we want to exclude formatting those that contain the #![rustfmt::skip] attribute.
66b8fe1
to
246cfa9
Compare
Nicely done, thank you! |
Closes #5065
Fixes #5033
Although the implementation is slightly different than the original PR,
the general idea is the same. After collecting all modules we want to
exclude formatting those that contain the
#![rustfmt::skip]
attribute.