From 649f69ce48e82b32047f6d0fcb0fe2af5d73a2dd Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Thu, 22 Dec 2022 08:19:42 -0500 Subject: [PATCH] prevent unnecessary indent when formatting doc comment code snippets Fixes 5623 When formatting code snippets in doc comments, we start by wrapping the content of the code block in an `fn main(){}` and add indentation. We do this because we're about to create an internal rustfmt `Session` that will try to parse the input snippet as a crate. In order for that operation to succeed the snippet can only contain top level items like function definitions. To illustrate the transformation, assume we're starting with the following doc comment: ```rust //! ```rust //! let x = "hello world!"; //! ``` ``` After the transformation rustfmt will actually try to format this: ```rust fn main() { let x = "hello world!"; } ``` It turns out that during the transformation described above, we sometimes add indentation to empty lines. This normally isn't an issue because rustfmt removes the redundant indentation while reformatting, but in the event a user adds an inner `#![rustfmt::skip]` attribute to their doc comment snippet the inner attribute will be applied to the `fn main(){}` and we'll leave the erroneous indentation in place. So this is what rustfmt will try to reformat: ```rust fn main() { #![rustfmt::skip] // ... the rest of the doc comment snippet } ``` To prevent this issue entirely we won't add indentation to any line that is empty or only contains whitespace. --- src/lib.rs | 8 ++++++-- tests/target/issue_5623.rs | 9 +++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 tests/target/issue_5623.rs diff --git a/src/lib.rs b/src/lib.rs index a67adb1478f..1b201e2301d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -352,10 +352,14 @@ fn format_code_block( result.push_str(FN_MAIN_PREFIX); let mut need_indent = true; for (kind, line) in LineClasses::new(s) { - if need_indent { + let not_empty = !line.trim().is_empty(); + // Only add indentation if the current line isn't empty + if need_indent && not_empty { result.push_str(&indent.to_string(config)); } - result.push_str(&line); + if not_empty { + result.push_str(&line); + } result.push('\n'); need_indent = indent_next_line(kind, &line, config); } diff --git a/tests/target/issue_5623.rs b/tests/target/issue_5623.rs new file mode 100644 index 00000000000..a165fdd92bf --- /dev/null +++ b/tests/target/issue_5623.rs @@ -0,0 +1,9 @@ +// rustfmt-format_code_in_doc_comments: true + +/// ``` +/// #![rustfmt::skip] +/// use core::primitive; +/// +/// let y = 0; +/// ``` +fn main() {}