Repository: rust-lang/rustfmt (rust)

Issue:
rustfmt binary path in usage string
`rustfmt` help command returns usage information in which `rustfmt` binary path is appended to the usage message. The usage message will be cleaner without the binary's path. I am happy to raise a pr for this if we are okay to remove the path from the usage string.
<img width="772" alt="Screenshot 2022-02-03 at 9 22 29 PM" src="https://user-images.githubusercontent.com/14926492/152378300-797f93f3-58f1-4c21-bd85-fccbbde5a572.png">


<!-- TRIAGEBOT_START -->

<!-- TRIAGEBOT_ASSIGN_START -->

<!-- TRIAGEBOT_ASSIGN_DATA_START$${"user":"tharun208"}$$TRIAGEBOT_ASSIGN_DATA_END -->

<!-- TRIAGEBOT_ASSIGN_END -->
<!-- TRIAGEBOT_END -->

Pull request:
chore(rustfmt): remove executable path from usage string
This PR removes the `rustfmt` executable path from usage string.

Fixes #5214 

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b59438dc..5b233608 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,10 @@
 
 ## [Unreleased]
 
+### Fixed
+
+- Fixes issue where wrapped strings would be incorrectly indented in macro defs when `format_strings` was enabled [#4036](https://github.com/rust-lang/rustfmt/issues/4036)
+
 ## [1.4.38] 2021-10-20
 
 ### Changed
@@ -57,6 +61,7 @@ Note this hit the rustup distributions prior to the v1.4.38 release as part of a
 
 - New `One` variant added to `imports_granularity` configuration option which can be used to reformat all imports into a single use statement [#4669](https://github.com/rust-lang/rustfmt/issues/4669)
 - rustfmt will now skip files that are annotated with `@generated` at the top of the file [#3958](https://github.com/rust-lang/rustfmt/issues/3958)
+  if `format_generated_files` option is set to `false` (by default `@generated` files are formatted)
 - New configuration option `hex_literal_case` that allows user to control the casing utilized for hex literals [PR #4903](https://github.com/rust-lang/rustfmt/pull/4903)
 
 See the section on the configuration site for more information
diff --git a/Configurations.md b/Configurations.md
index 4476f2a4..2e2b0f7c 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -930,6 +930,8 @@ fn add_one(x: i32) -> i32 {
 
 Format generated files. A file is considered generated
 if any of the first five lines contain a `@generated` comment marker.
+By default, generated files are reformatted, i. e. `@generated` marker is ignored.
+This option is currently ignored for stdin (`@generated` in stdin is ignored.)
 
 - **Default value**: `true`
 - **Possible values**: `true`, `false`
diff --git a/src/bin/main.rs b/src/bin/main.rs
index 6f5b09fc..196de605 100644
--- a/src/bin/main.rs
+++ b/src/bin/main.rs
@@ -394,9 +394,8 @@ fn print_usage_to_stdout(opts: &Options, reason: &str) {
         format!("{}\n\n", reason)
     };
     let msg = format!(
-        "{}Format Rust code\n\nusage: {} [options] <file>...",
-        sep,
-        env::args_os().next().unwrap().to_string_lossy()
+        "{}Format Rust code\n\nusage: rustfmt [options] <file>...",
+        sep
     );
     println!("{}", opts.usage(&msg));
 }
diff --git a/src/spanned.rs b/src/spanned.rs
index 8e6c75a3..2136cfea 100644
--- a/src/spanned.rs
+++ b/src/spanned.rs
@@ -113,17 +113,10 @@ impl Spanned for ast::Param {
 
 impl Spanned for ast::GenericParam {
     fn span(&self) -> Span {
-        let lo = if let ast::GenericParamKind::Const {
-            ty: _,
-            kw_span,
-            default: _,
-        } = self.kind
-        {
-            kw_span.lo()
-        } else if self.attrs.is_empty() {
-            self.ident.span.lo()
-        } else {
-            self.attrs[0].span.lo()
+        let lo = match self.kind {
+            _ if !self.attrs.is_empty() => self.attrs[0].span.lo(),
+            ast::GenericParamKind::Const { kw_span, .. } => kw_span.lo(),
+            _ => self.ident.span.lo(),
         };
         let hi = if self.bounds.is_empty() {
             self.ident.span.hi()
diff --git a/src/types.rs b/src/types.rs
index 5de30129..b13e75a9 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -575,7 +575,16 @@ impl Rewrite for ast::GenericParam {
         let mut result = String::with_capacity(128);
         // FIXME: If there are more than one attributes, this will force multiline.
         match self.attrs.rewrite(context, shape) {
-            Some(ref rw) if !rw.is_empty() => result.push_str(&format!("{} ", rw)),
+            Some(ref rw) if !rw.is_empty() => {
+                result.push_str(rw);
+                // When rewriting generic params, an extra newline should be put
+                // if the attributes end with a doc comment
+                if let Some(true) = self.attrs.last().map(|a| a.is_doc_comment()) {
+                    result.push_str(&shape.indent.to_string_with_newline(context.config));
+                } else {
+                    result.push(' ');
+                }
+            }
             _ => (),
         }
 
diff --git a/src/utils.rs b/src/utils.rs
index 2428d8cb..35512e78 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -646,9 +646,22 @@ pub(crate) fn trim_left_preserve_layout(
 }
 
 /// Based on the given line, determine if the next line can be indented or not.
-/// This allows to preserve the indentation of multi-line literals.
-pub(crate) fn indent_next_line(kind: FullCodeCharKind, _line: &str, config: &Config) -> bool {
-    !(kind.is_string() || (config.version() == Version::Two && kind.is_commented_string()))
+/// This allows to preserve the indentation of multi-line literals when
+/// re-inserted a code block that has been formatted separately from the rest
+/// of the code, such as code in macro defs or code blocks doc comments.
+pub(crate) fn indent_next_line(kind: FullCodeCharKind, line: &str, config: &Config) -> bool {
+    if kind.is_string() {
+        // If the string ends with '\', the string has been wrapped over
+        // multiple lines. If `format_strings = true`, then the indentation of
+        // strings wrapped over multiple lines will have been adjusted while
+        // formatting the code block, therefore the string's indentation needs
+        // to be adjusted for the code surrounding the code block.
+        config.format_strings() && line.ends_with('\\')
+    } else if config.version() == Version::Two {
+        !kind.is_commented_string()
+    } else {
+        true
+    }
 }
 
 pub(crate) fn is_empty_line(s: &str) -> bool {


Test patch:
diff --git a/tests/rustfmt/main.rs b/tests/rustfmt/main.rs
index 8effb1c6..6976cc4d 100644
--- a/tests/rustfmt/main.rs
+++ b/tests/rustfmt/main.rs
@@ -106,3 +106,12 @@ fn inline_config() {
             && contains("format_strings = true")
     );
 }
+
+#[test]
+fn rustfmt_usage_text() {
+    let args = [
+        "--help",
+    ];
+    let (stdout, _) = rustfmt(&args);
+    assert!(stdout.contains(&format!("Format Rust code\n\nusage: rustfmt [options] <file>...")));
+}
diff --git a/tests/source/issue-4036/one.rs b/tests/source/issue-4036/one.rs
new file mode 100644
index 00000000..9f9675f5
--- /dev/null
+++ b/tests/source/issue-4036/one.rs
@@ -0,0 +1,11 @@
+// rustfmt-format_strings: true
+
+macro_rules! test {
+    () => {
+        fn from() {
+            None.expect(
+                "We asserted that `buffer.len()` is exactly `$n` so we can expect `ApInt::from_iter` to be successful.",
+            )
+        }
+    };
+}
diff --git a/tests/source/issue-4036/three.rs b/tests/source/issue-4036/three.rs
new file mode 100644
index 00000000..e1865dd0
--- /dev/null
+++ b/tests/source/issue-4036/three.rs
@@ -0,0 +1,12 @@
+// rustfmt-format_strings: true
+// rustfmt-hard_tabs: true
+
+macro_rules! test {
+    () => {
+        fn from() {
+            None.expect(
+                "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
+            )
+        }
+    };
+}
diff --git a/tests/source/issue-4036/two.rs b/tests/source/issue-4036/two.rs
new file mode 100644
index 00000000..fa54d2e3
--- /dev/null
+++ b/tests/source/issue-4036/two.rs
@@ -0,0 +1,11 @@
+// rustfmt-format_strings: true
+
+macro_rules! test {
+    () => {
+        fn from() {
+            None.expect(
+                "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
+            )
+        }
+    };
+}
diff --git a/tests/target/doc-of-generic-item.rs b/tests/target/doc-of-generic-item.rs
new file mode 100644
index 00000000..2efc5e09
--- /dev/null
+++ b/tests/target/doc-of-generic-item.rs
@@ -0,0 +1,14 @@
+// Non-doc pre-comment of Foo
+/// doc of Foo
+// Non-doc post-comment of Foo
+struct Foo<
+    // Non-doc pre-comment of 'a
+    /// doc of 'a
+    'a,
+    // Non-doc pre-comment of T
+    /// doc of T
+    T,
+    // Non-doc pre-comment of N
+    /// doc of N
+    const N: item,
+>;
diff --git a/tests/target/issue-4036/one.rs b/tests/target/issue-4036/one.rs
new file mode 100644
index 00000000..54e490b7
--- /dev/null
+++ b/tests/target/issue-4036/one.rs
@@ -0,0 +1,12 @@
+// rustfmt-format_strings: true
+
+macro_rules! test {
+    () => {
+        fn from() {
+            None.expect(
+                "We asserted that `buffer.len()` is exactly `$n` so we can expect \
+                 `ApInt::from_iter` to be successful.",
+            )
+        }
+    };
+}
diff --git a/tests/target/issue-4036/three.rs b/tests/target/issue-4036/three.rs
new file mode 100644
index 00000000..394dc863
--- /dev/null
+++ b/tests/target/issue-4036/three.rs
@@ -0,0 +1,17 @@
+// rustfmt-format_strings: true
+// rustfmt-hard_tabs: true
+
+macro_rules! test {
+	() => {
+		fn from() {
+			None.expect(
+				"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor \
+				 incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis \
+				 nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \
+				 Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu \
+				 fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in \
+				 culpa qui officia deserunt mollit anim id est laborum.",
+			)
+		}
+	};
+}
diff --git a/tests/target/issue-4036/two.rs b/tests/target/issue-4036/two.rs
new file mode 100644
index 00000000..01cafa76
--- /dev/null
+++ b/tests/target/issue-4036/two.rs
@@ -0,0 +1,16 @@
+// rustfmt-format_strings: true
+
+macro_rules! test {
+    () => {
+        fn from() {
+            None.expect(
+                "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor \
+                 incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis \
+                 nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \
+                 Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu \
+                 fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in \
+                 culpa qui officia deserunt mollit anim id est laborum.",
+            )
+        }
+    };
+}