Auto merge of #126842 - calebcartwright:sync-from-rustfmt-24-06, r=calebcartwright

rustfmt subtree update

r? ghost
This commit is contained in:
bors 2024-06-23 00:42:26 +00:00
commit acb62737ac
99 changed files with 1582 additions and 327 deletions

View File

@ -638,7 +638,7 @@ dependencies = [
"filetime",
"futures",
"if_chain",
"itertools 0.12.1",
"itertools",
"parking_lot",
"quote",
"regex",
@ -670,7 +670,7 @@ dependencies = [
"aho-corasick",
"clap",
"indoc",
"itertools 0.12.1",
"itertools",
"opener 0.6.1",
"shell-escape",
"walkdir",
@ -685,7 +685,7 @@ dependencies = [
"clippy_config",
"clippy_utils",
"declare_clippy_lint",
"itertools 0.12.1",
"itertools",
"quine-mc_cluskey",
"regex",
"regex-syntax 0.8.4",
@ -707,7 +707,7 @@ version = "0.1.81"
dependencies = [
"arrayvec",
"clippy_config",
"itertools 0.12.1",
"itertools",
"rustc-semver",
"rustc_apfloat",
]
@ -1026,7 +1026,7 @@ dependencies = [
name = "declare_clippy_lint"
version = "0.1.81"
dependencies = [
"itertools 0.12.1",
"itertools",
"quote",
"syn 2.0.66",
]
@ -1133,16 +1133,16 @@ version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35"
dependencies = [
"dirs-sys 0.4.1",
"dirs-sys",
]
[[package]]
name = "dirs"
version = "4.0.0"
version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
dependencies = [
"dirs-sys 0.3.7",
"dirs-sys",
]
[[package]]
@ -1155,17 +1155,6 @@ dependencies = [
"dirs-sys-next",
]
[[package]]
name = "dirs-sys"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
dependencies = [
"libc",
"redox_users",
"winapi",
]
[[package]]
name = "dirs-sys"
version = "0.4.1"
@ -2076,15 +2065,6 @@ version = "1.70.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
[[package]]
name = "itertools"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.12.1"
@ -2227,7 +2207,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
dependencies = [
"cfg-if",
"windows-targets 0.48.5",
"windows-targets 0.52.5",
]
[[package]]
@ -3665,7 +3645,7 @@ dependencies = [
name = "rustc_ast_passes"
version = "0.0.0"
dependencies = [
"itertools 0.12.1",
"itertools",
"rustc_ast",
"rustc_ast_pretty",
"rustc_attr",
@ -3685,7 +3665,7 @@ dependencies = [
name = "rustc_ast_pretty"
version = "0.0.0"
dependencies = [
"itertools 0.12.1",
"itertools",
"rustc_ast",
"rustc_lexer",
"rustc_span",
@ -3726,7 +3706,7 @@ name = "rustc_borrowck"
version = "0.0.0"
dependencies = [
"either",
"itertools 0.12.1",
"itertools",
"polonius-engine",
"rustc_data_structures",
"rustc_errors",
@ -3779,7 +3759,7 @@ name = "rustc_codegen_llvm"
version = "0.0.0"
dependencies = [
"bitflags 2.5.0",
"itertools 0.12.1",
"itertools",
"libc",
"measureme",
"object 0.32.2",
@ -3818,7 +3798,7 @@ dependencies = [
"bitflags 2.5.0",
"cc",
"either",
"itertools 0.12.1",
"itertools",
"jobserver",
"libc",
"object 0.32.2",
@ -4098,7 +4078,7 @@ dependencies = [
name = "rustc_hir_analysis"
version = "0.0.0"
dependencies = [
"itertools 0.12.1",
"itertools",
"rustc_arena",
"rustc_ast",
"rustc_attr",
@ -4137,7 +4117,7 @@ dependencies = [
name = "rustc_hir_typeck"
version = "0.0.0"
dependencies = [
"itertools 0.12.1",
"itertools",
"rustc_ast",
"rustc_ast_ir",
"rustc_attr",
@ -4421,7 +4401,7 @@ dependencies = [
name = "rustc_mir_build"
version = "0.0.0"
dependencies = [
"itertools 0.12.1",
"itertools",
"rustc_apfloat",
"rustc_arena",
"rustc_ast",
@ -4468,7 +4448,7 @@ name = "rustc_mir_transform"
version = "0.0.0"
dependencies = [
"either",
"itertools 0.12.1",
"itertools",
"rustc_arena",
"rustc_ast",
"rustc_attr",
@ -4824,7 +4804,7 @@ version = "0.0.0"
dependencies = [
"bitflags 2.5.0",
"derivative",
"itertools 0.12.1",
"itertools",
"rustc_ast",
"rustc_ast_ir",
"rustc_attr",
@ -4867,7 +4847,7 @@ dependencies = [
name = "rustc_transmute"
version = "0.0.0"
dependencies = [
"itertools 0.12.1",
"itertools",
"rustc_ast_ir",
"rustc_data_structures",
"rustc_hir",
@ -4883,7 +4863,7 @@ dependencies = [
name = "rustc_ty_utils"
version = "0.0.0"
dependencies = [
"itertools 0.12.1",
"itertools",
"rustc_ast_ir",
"rustc_data_structures",
"rustc_errors",
@ -4947,7 +4927,7 @@ dependencies = [
"base64",
"expect-test",
"indexmap",
"itertools 0.12.1",
"itertools",
"minifier",
"regex",
"rustdoc-json-types",
@ -5028,20 +5008,19 @@ dependencies = [
[[package]]
name = "rustfmt-nightly"
version = "1.7.0"
version = "1.7.1"
dependencies = [
"annotate-snippets 0.9.2",
"anyhow",
"bytecount",
"cargo_metadata 0.15.4",
"cargo_metadata 0.18.1",
"clap",
"clap-cargo",
"diff",
"dirs",
"getopts",
"ignore",
"itertools 0.11.0",
"lazy_static",
"itertools",
"regex",
"rustfmt-config_proc_macro",
"serde",

View File

@ -19,7 +19,6 @@ jobs:
matrix:
integration: [
bitflags,
error-chain,
log,
mdbook,
packed_simd,

View File

@ -2,6 +2,99 @@
## [Unreleased]
### Fixed
- Fix an idempotency issue when rewriting where clauses in which rustfmt would continuously add a trailing comma `,` to the end of trailing line comments [#5941](https://github.com/rust-lang/rustfmt/issues/5941).
- Prevent enum variant attributes from wrapping one character early when using `version=Two` [#5801](https://github.com/rust-lang/rustfmt/issues/5801)
- Properly wrap macro matchers at the `max_width` when using `version=Two` and `format_macro_matchers=true` [#3805](https://github.com/rust-lang/rustfmt/issues/3805)
- Prevent panic when formatting trait declaration with non [Unicode Normalization Form] C (NFC) identifiers [#6069](https://github.com/rust-lang/rustfmt/issues/6069)
```rust
// The ó below is two codepoints, ASCII o followed by U+0301 COMBINING ACUTE ACCENT.
// It NFC-normalizes to ó, U+00F3 LATIN SMALL LETTER O WITH ACUTE.
trait Foó: Bar {}
```
[unicode normalization form]: https://unicode.org/reports/tr15/
- Ensure a space is added to a range expression, when the right hand side of the range expression is a binary expression that ends with a trailing period [#6059](https://github.com/rust-lang/rustfmt/issues/6059)
```rust
let range = 3. / 2. ..4.;
```
- When using `version=Two`, comments in match arms that contain `=>` no longer prevent formatting [#5998](https://github.com/rust-lang/rustfmt/issues/5998)
```rust
match a {
_ =>
// comment with =>
{
println!("A")
}
}
```
- Prevent panics when formatting input that contains the expanded form of `offset_of!` [#5885](https://github.com/rust-lang/rustfmt/issues/5885) [#6105](https://github.com/rust-lang/rustfmt/issues/6105)
```rust
const _: () = builtin # offset_of(x, x);
```
- When using `version=Two` inner attributes in `match` expressions are correctly indented [#6147](https://github.com/rust-lang/rustfmt/issues/6147)
```rust
pub fn main() {
match x {
#![attr1]
#![attr2]
_ => (),
}
}
```
- Output correct syntax for type ascription builtin [#6159](https://github.com/rust-lang/rustfmt/issues/6159)
```rust
fn main() {
builtin # type_ascribe(10, usize)
}
```
- rustfmt no longer removes inner attributes from inline const blocks [#6158](https://github.com/rust-lang/rustfmt/issues/6158)
```rust
fn main() {
const {
#![allow(clippy::assertions_on_constants)]
assert!(1 < 2);
}
}
```
- rustfmt no longer removes `safe` and `unsafe` keywords from static items in extern blocks.
This helps support [`#![feature(unsafe_extern_blocks)]`](https://github.com/rust-lang/rust/issues/123743) [#6204](https://github.com/rust-lang/rustfmt/pull/6204)
```rust
#![feature(unsafe_extern_blocks)]
unsafe extern "C" {
safe static TEST1: i32;
unsafe static TEST2: i32;
}
```
### Changed
- `hide_parse_errors` has been soft deprecated and it's been renamed to `show_parse_errors` [#5961](https://github.com/rust-lang/rustfmt/pull/5961).
- The diff output produced by `rustfmt --check` is more compatable with editors that support navigating directly to line numbers [#5971](https://github.com/rust-lang/rustfmt/pull/5971)
- When using `version=Two`, the `trace!` macro from the [log crate] is now formatted similarly to `debug!`, `info!`, `warn!`, and `error!` [#5987](https://github.com/rust-lang/rustfmt/issues/5987).
[log crate]: https://crates.io/crates/log
### Added
- `generated_marker_line_search_limit` is a new unstable configuration option that allows users to configure how many lines to search for an `@generated` marker when `format_generated_files=false` [#5658](https://github.com/rust-lang/rustfmt/issues/5658)
### Misc
- Updating `dirs 4.0.0 -> 5.0.1` and `cargo_metadata 0.15.4 -> 0.18.0` [#6033] (https://github.com/rust-lang/rustfmt/issues/6033)
- For reference, here's the [dirs v5 changelog](https://github.com/dirs-dev/dirs-rs/blob/main/README.md#5)
- Updated [itertools v0.11 -> v0.12](https://github.com/rust-itertools/itertools/blob/v0.12.1/CHANGELOG.md#0120) [#6093](https://github.com/rust-lang/rustfmt/pull/6093)
- Addressed clap deprecations output when running `cargo check --features clap/deprecated` [#6101](https://github.com/rust-lang/rustfmt/pull/6101)
- Bumped bytecount `0.6.4` -> `0.6.8` to fix compilation issues with the `generic-simd` feature. See [bytecount#92] and [bytecount#93]
[bytecount#92]: https://github.com/llogiq/bytecount/pull/92
[bytecount#93]: https://github.com/llogiq/bytecount/pull/93
- Replace the `lazy_static` dependency with `std::sync::OnceLock` [#6154](https://github.com/rust-lang/rustfmt/pull/6154)
## [1.7.0] 2023-10-22
@ -27,7 +120,7 @@
}
```
- Prevent ICE when formatting `vec!{}` [#5735](https://github.com/rust-lang/rustfmt/issues/5735)
- Prevent internal trailing whitespace error when formatting an empty `macro_rules!` defintion e.g. `macro_rules! foo {}` [#5882](https://github.com/rust-lang/rustfmt/issues/5882)
- Prevent internal trailing whitespace error when formatting an empty `macro_rules!` definition e.g. `macro_rules! foo {}` [#5882](https://github.com/rust-lang/rustfmt/issues/5882)
- Formatting doc comment lines that start with `.` or `)` won't be treated as ordered markdown lists because `.` or `)` must be preceded by a number to start an ordered markdown list [#5835](https://github.com/rust-lang/rustfmt/pull/5835)
- Add parenthesis around closures when they're used as method receives, don't have a block body, and end with `.` [#4808](https://github.com/rust-lang/rustfmt/issues/4808)
```rust
@ -184,7 +277,7 @@
- Simplify the rustfmt help text by eliding the full path to the rustfmt binary path from the usage string when running `rustfmt --help` [#5214](https://github.com/rust-lang/rustfmt/issues/5214)
- Bumped the version for serveral dependencies. Most notably `dirs` `v2.0.1` -> `v4.0.0`. This changed the global user config directory on macOS from `$HOME/Library/Preferences` to `$HOME/Library/Application Support` [#5237](https://github.com/rust-lang/rustfmt/pull/5237)
- Bumped the version for several dependencies. Most notably `dirs` `v2.0.1` -> `v4.0.0`. This changed the global user config directory on macOS from `$HOME/Library/Preferences` to `$HOME/Library/Application Support` [#5237](https://github.com/rust-lang/rustfmt/pull/5237)
### Fixed
@ -942,7 +1035,7 @@ from formatting an attribute #3665
### Fixed
- Do not remove path disambiugator inside macro #3142
- Do not remove path disambiguator inside macro #3142
- Improve handling of Windows newlines #3141
- Fix alignment of a struct's fields (`struct_field_align_threshold` option) with the Visual `indent_style` #3165
- Fix a bug in formatting markdown lists within comments #3172
@ -1031,7 +1124,7 @@ from formatting an attribute #3665
### Changed
- Replace '--conifig-help' with '--config=help' cb10e06
- Replace '--config-help' with '--config=help' cb10e06
- Improve formatting of slice patterns #2912
### Fixed
@ -1075,7 +1168,7 @@ from formatting an attribute #3665
- Add max_width option for all heuristics c2ae39e
- Add config option `format_macro_matchers` to format the metavariable matching patterns in macros 79c5ee8
- Add config option `format_macro_bodies` to format the bodies of macros 79c5ee8
- Format exitential type fc307ff
- Format existential type fc307ff
- Support raw identifiers in struct expressions f121b1a
- Format Async block and async function 0b25f60
@ -1131,7 +1224,7 @@ from formatting an attribute #3665
### Changed
- Update rustc-ap-syntax to 128.0.0 and ustc-ap-rustc_target to 128.0.0 195395f
- Update rustc-ap-syntax to 128.0.0 and rustc-ap-rustc_target to 128.0.0 195395f
- Put operands on its own line when each fits in a single line f8439ce
- Improve CLI options 55ac062 1869888 798bffb 4d9de48 eca7796 8396da1 5d9f5aa
@ -1195,7 +1288,7 @@ from formatting an attribute #3665
- Do not collapse block around expr with condition on match arm 5b9b7d5
- Use vertical layout for complex attributes c77708f
- Format array using heuristics for function calls 98c6f7b
- Implement stable ordering for impl items with the the following item priority: type, const, macro, then method fa80ddf
- Implement stable ordering for impl items with the following item priority: type, const, macro, then method fa80ddf
- Reorder imports by default 164cf7d
- Group `extern crate` by default 3a138a2
- Make `error_on_line_overflow` false by default f146711

View File

@ -98,12 +98,9 @@ dependencies = [
[[package]]
name = "bytecount"
version = "0.6.4"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad152d03a2c813c80bb94fedbf3a3f02b28f793e39e7c214c8a0bcc196343de7"
dependencies = [
"packed_simd",
]
checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce"
[[package]]
name = "camino"
@ -125,9 +122,9 @@ dependencies = [
[[package]]
name = "cargo_metadata"
version = "0.15.4"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a"
checksum = "fb9ac64500cc83ce4b9f8dafa78186aa008c8dea77a09b94cd307fd0cd5022a8"
dependencies = [
"camino",
"cargo-platform",
@ -217,9 +214,9 @@ checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499"
[[package]]
name = "dirs"
version = "4.0.0"
version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
dependencies = [
"dirs-sys",
]
@ -236,13 +233,14 @@ dependencies = [
[[package]]
name = "dirs-sys"
version = "0.3.7"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
dependencies = [
"libc",
"option-ext",
"redox_users",
"winapi",
"windows-sys",
]
[[package]]
@ -343,9 +341,9 @@ dependencies = [
[[package]]
name = "itertools"
version = "0.10.3"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
dependencies = [
"either",
]
@ -368,12 +366,6 @@ version = "0.2.141"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5"
[[package]]
name = "libm"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
[[package]]
name = "log"
version = "0.4.16"
@ -408,38 +400,24 @@ dependencies = [
"winapi",
]
[[package]]
name = "num-traits"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
dependencies = [
"autocfg",
"libm",
]
[[package]]
name = "once_cell"
version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "option-ext"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
name = "packed_simd"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f9f08af0c877571712e2e3e686ad79efad9657dbf0f7c3c8ba943ff6c38932d"
dependencies = [
"cfg-if",
"num-traits",
]
[[package]]
name = "pin-project-lite"
version = "0.2.9"
@ -521,7 +499,7 @@ dependencies = [
[[package]]
name = "rustfmt-nightly"
version = "1.7.0"
version = "1.7.1"
dependencies = [
"annotate-snippets",
"anyhow",
@ -534,7 +512,6 @@ dependencies = [
"getopts",
"ignore",
"itertools",
"lazy_static",
"regex",
"rustfmt-config_proc_macro",
"serde",

View File

@ -1,7 +1,7 @@
[package]
name = "rustfmt-nightly"
version = "1.7.0"
version = "1.7.1"
description = "Tool to find and fix Rust formatting issues"
repository = "https://github.com/rust-lang/rustfmt"
readme = "README.md"
@ -35,16 +35,15 @@ generic-simd = ["bytecount/generic-simd"]
[dependencies]
annotate-snippets = { version = "0.9", features = ["color"] }
anyhow = "1.0"
bytecount = "0.6.4"
cargo_metadata = "0.15.4"
bytecount = "0.6.8"
cargo_metadata = "0.18"
clap = { version = "4.4.2", features = ["derive"] }
clap-cargo = "0.12.0"
diff = "0.1"
dirs = "4.0"
dirs = "5.0"
getopts = "0.2"
ignore = "0.4"
itertools = "0.11"
lazy_static = "1.4"
itertools = "0.12"
regex = "1.7"
serde = { version = "1.0.160", features = ["derive"] }
serde_json = "1.0"

View File

@ -1,6 +1,6 @@
# Configuring Rustfmt
Rustfmt is designed to be very configurable. You can create a TOML file called `rustfmt.toml` or `.rustfmt.toml`, place it in the project or any other parent directory and it will apply the options in that file. If none of these directories contain such a file, both your home directory and a directory called `rustfmt` in your [global config directory](https://docs.rs/dirs/4.0.0/dirs/fn.config_dir.html) (e.g. `.config/rustfmt/`) are checked as well.
Rustfmt is designed to be very configurable. You can create a TOML file called `rustfmt.toml` or `.rustfmt.toml`, place it in the project or any other parent directory and it will apply the options in that file. If none of these directories contain such a file, both your home directory and a directory called `rustfmt` in your [global config directory](https://docs.rs/dirs/5.0.1/dirs/fn.config_dir.html) (e.g. `.config/rustfmt/`) are checked as well.
A possible content of `rustfmt.toml` or `.rustfmt.toml` might look like this:
@ -1050,8 +1050,8 @@ Max width for code snippets included in doc comments. Only used if [`format_code
## `format_generated_files`
Format generated files. A file is considered generated
if any of the first five lines contain a `@generated` comment marker.
Format generated files. A file is considered generated if any of the first several lines contain a `@generated` comment marker. The number of lines to check is configured by `generated_marker_line_search_limit`.
By default, generated files are reformatted, i. e. `@generated` marker is ignored.
This option is currently ignored for stdin (`@generated` in stdin is ignored.)
@ -1059,6 +1059,16 @@ This option is currently ignored for stdin (`@generated` in stdin is ignored.)
- **Possible values**: `true`, `false`
- **Stable**: No (tracking issue: [#5080](https://github.com/rust-lang/rustfmt/issues/5080))
## `generated_marker_line_search_limit`
Number of lines to check for a `@generated` pragma header, starting from the top of the file. Setting this value to `0` will treat all files as non-generated. When`format_generated_files` is `true`, this option has no effect.
- **Default value**: `5`
- **Possible values**: any positive integer
- **Stable**: No (tracking issue: [#5080](https://github.com/rust-lang/rustfmt/issues/5080))
See also [format_generated_files](#format_generated_files) link here.
## `format_macro_matchers`
Format the metavariable matching patterns in macros.
@ -1098,7 +1108,7 @@ See also [`format_macro_bodies`](#format_macro_bodies).
## `format_macro_bodies`
Format the bodies of macros.
Format the bodies of declarative macro definitions.
- **Default value**: `true`
- **Possible values**: `true`, `false`
@ -1248,12 +1258,20 @@ Control the case of the letters in hexadecimal literal values
## `hide_parse_errors`
Do not show parse errors if the parser failed to parse files.
This option is deprecated and has been renamed to `show_parse_errors` to avoid confusion around the double negative default of `hide_parse_errors=false`.
- **Default value**: `false`
- **Possible values**: `true`, `false`
- **Stable**: No (tracking issue: [#3390](https://github.com/rust-lang/rustfmt/issues/3390))
## `show_parse_errors`
Show parse errors if the parser failed to parse files.
- **Default value**: `true`
- **Possible values**: `true`, `false`
- **Stable**: No (tracking issue: [#5977](https://github.com/rust-lang/rustfmt/issues/5977))
## `ignore`
Skip formatting files and directories that match the specified pattern.
@ -1288,6 +1306,15 @@ If you want to ignore every file under the directory where you put your rustfmt.
ignore = ["/"]
```
If you want to allow specific paths that would otherwise be ignored, prefix those paths with a `!`:
```toml
ignore = ["bar_dir/*", "!bar_dir/*/what.rs"]
```
In this case, all files under `bar_dir` will be ignored, except files like `bar_dir/sub/what.rs`
or `bar_dir/another/what.rs`.
## `imports_indent`
Indent style of imports
@ -1655,7 +1682,7 @@ use core::slice;
Controls whether arm bodies are wrapped in cases where the first line of the body cannot fit on the same line as the `=>` operator.
The Style Guide requires that bodies are block wrapped by default if a line break is required after the `=>`, but this option can be used to disable that behavior to prevent wrapping arm bodies in that event, so long as the body does not contain multiple statements nor line comments.
The Style Guide requires that bodies are block wrapped by default if a line break is required after the `=>`, but this option can be used to disable that behavior to prevent wrapping arm bodies in that event, so long as the body contains neither multiple statements nor line comments.
- **Default value**: `true`
- **Possible values**: `true`, `false`

View File

@ -59,7 +59,7 @@ example, the `issue-1111.rs` test file is configured by the file
## Debugging
Some `rewrite_*` methods use the `debug!` macro for printing useful information.
These messages can be printed by using the environment variable `RUSTFMT_LOG=rustfmt=DEBUG`.
These messages can be printed by using the environment variable `RUSTFMT_LOG=debug`.
These traces can be helpful in understanding which part of the code was used
and get a better grasp on the execution flow.

View File

@ -16,7 +16,7 @@ In this Section, we describe how to stabilise an option of the rustfmt's configu
Open a pull request that closes the tracking issue. The tracking issue is listed beside the option in `Configurations.md`.
- Update the `Config` enum marking the option as stable.
- Update the the `Configuration.md` file marking the option as stable.
- Update the `Configuration.md` file marking the option as stable.
- Update `CHANGELOG.md` marking the option as stable.
## After the stabilisation

View File

@ -40,7 +40,7 @@ fn channel() -> String {
fn commit_hash() -> Option<String> {
Command::new("git")
.args(&["rev-parse", "--short", "HEAD"])
.args(["rev-parse", "--short", "HEAD"])
.output()
.ok()
.and_then(|r| String::from_utf8(r.stdout).ok())
@ -48,7 +48,7 @@ fn commit_hash() -> Option<String> {
fn commit_date() -> Option<String> {
Command::new("git")
.args(&["log", "-1", "--date=short", "--pretty=format:%cd"])
.args(["log", "-1", "--date=short", "--pretty=format:%cd"])
.output()
.ok()
.and_then(|r| String::from_utf8(r.stdout).ok())

View File

@ -0,0 +1 @@
/target

View File

@ -0,0 +1,237 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "anstream"
version = "0.6.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
[[package]]
name = "anstyle-parse"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
dependencies = [
"anstyle",
"windows-sys",
]
[[package]]
name = "check_diff"
version = "0.1.0"
dependencies = [
"clap",
]
[[package]]
name = "clap"
version = "4.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
[[package]]
name = "colorchoice"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "is_terminal_polyfill"
version = "1.70.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
[[package]]
name = "proc-macro2"
version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "utf8parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
[[package]]
name = "windows_i686_gnu"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
[[package]]
name = "windows_i686_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"

View File

@ -0,0 +1,9 @@
[package]
name = "check_diff"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
clap = { version = "4.4.2", features = ["derive"] }

View File

@ -0,0 +1,25 @@
use clap::Parser;
/// Inputs for the check_diff script
#[derive(Parser)]
struct CliInputs {
/// Git url of a rustfmt fork to compare against the latest master rustfmt
remote_repo_url: String,
/// Name of the feature branch on the forked repo
feature_branch: String,
/// Optional commit hash from the feature branch
#[arg(short, long)]
commit_hash: Option<String>,
/// Optional comma separated list of rustfmt config options to
/// pass when running the feature branch
#[arg(value_delimiter = ',', short, long, num_args = 1..)]
rustfmt_config: Option<Vec<String>>,
}
fn main() {
let args = CliInputs::parse();
println!(
"remote_repo_url: {:?}, feature_branch: {:?},
optional_commit_hash: {:?}, optional_rustfmt_config: {:?}",
args.remote_repo_url, args.feature_branch, args.commit_hash, args.rustfmt_config
);
}

View File

@ -2,9 +2,6 @@
set -e
# https://github.com/rust-lang/rustfmt/issues/5675
export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib:$LD_LIBRARY_PATH
function print_usage() {
echo "usage check_diff REMOTE_REPO FEATURE_BRANCH [COMMIT_HASH] [OPTIONAL_RUSTFMT_CONFIGS]"
}
@ -31,7 +28,7 @@ function clone_repo() {
GIT_TERMINAL_PROMPT=0 git clone --quiet $1 --depth 1 $2 && cd $2
}
# Initialize Git submoduels for the repo.
# Initialize Git submodules for the repo.
#
# Parameters
# $1: list of directories to initialize
@ -46,7 +43,7 @@ function init_submodules() {
# $2: Output file path for the diff
# $3: Any additional configuration options to pass to rustfmt
#
# Globlas:
# Globals:
# $OPTIONAL_RUSTFMT_CONFIGS: Optional configs passed to the script from $4
function create_diff() {
local config;
@ -67,7 +64,7 @@ function create_diff() {
# Parameters
# $1: Name of the repository (used for logging)
#
# Globlas:
# Globals:
# $RUSFMT_BIN: Path to the rustfmt master binary. Created when running `compile_rustfmt`
# $FEATURE_BIN: Path to the rustfmt feature binary. Created when running `compile_rustfmt`
# $OPTIONAL_RUSTFMT_CONFIGS: Optional configs passed to the script from $4
@ -90,7 +87,7 @@ function check_diff() {
)
if [ -z "$diff" ]; then
echo "no diff detected between rustfmt and the feture branch"
echo "no diff detected between rustfmt and the feature branch"
return 0
else
echo "$diff"
@ -104,7 +101,7 @@ function check_diff() {
# Parameters:
# $1: Directory where rustfmt will be cloned
#
# Globlas:
# Globals:
# $REMOTE_REPO: Clone URL to the rustfmt fork that we want to test
# $FEATURE_BRANCH: Name of the feature branch
# $OPTIONAL_COMMIT_HASH: Optional commit hash that will be checked out if provided
@ -114,15 +111,42 @@ function compile_rustfmt() {
git remote add feature $REMOTE_REPO
git fetch feature $FEATURE_BRANCH
cargo build --release --bin rustfmt && cp target/release/rustfmt $1/rustfmt
CARGO_VERSION=$(cargo --version)
echo -e "\ncompiling with $CARGO_VERSION\n"
# Because we're building standalone binaries we need to set `LD_LIBRARY_PATH` so each
# binary can find it's runtime dependencies. See https://github.com/rust-lang/rustfmt/issues/5675
# This will prepend the `LD_LIBRARY_PATH` for the master rustfmt binary
export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib:$LD_LIBRARY_PATH
echo "Building rustfmt from src"
cargo build -q --release --bin rustfmt && cp target/release/rustfmt $1/rustfmt
if [ -z "$OPTIONAL_COMMIT_HASH" ] || [ "$FEATURE_BRANCH" = "$OPTIONAL_COMMIT_HASH" ]; then
git switch $FEATURE_BRANCH
else
git switch $OPTIONAL_COMMIT_HASH --detach
fi
cargo build --release --bin rustfmt && cp target/release/rustfmt $1/feature_rustfmt
# This will prepend the `LD_LIBRARY_PATH` for the feature branch rustfmt binary.
# In most cases the `LD_LIBRARY_PATH` should be the same for both rustfmt binaries that we build
# in `compile_rustfmt`, however, there are scenarios where each binary has different runtime
# dependencies. For example, during subtree syncs we bump the nightly toolchain required to build
# rustfmt, and therefore the feature branch relies on a newer set of runtime dependencies.
export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib:$LD_LIBRARY_PATH
echo "Building feature rustfmt from src"
cargo build -q --release --bin rustfmt && cp target/release/rustfmt $1/feature_rustfmt
echo -e "\nRuntime dependencies for rustfmt -- LD_LIBRARY_PATH: $LD_LIBRARY_PATH"
RUSFMT_BIN=$1/rustfmt
RUSTFMT_VERSION=$($RUSFMT_BIN --version)
echo -e "\nRUSFMT_BIN $RUSTFMT_VERSION\n"
FEATURE_BIN=$1/feature_rustfmt
FEATURE_VERSION=$($FEATURE_BIN --version)
echo -e "FEATURE_BIN $FEATURE_VERSION\n"
}
# Check the diff for running rustfmt and the feature branch on all the .rs files in the repo.
@ -155,7 +179,7 @@ function check_repo() {
STATUSES+=($?)
set -e
echo "removing tmp_dir $tmp_dir"
echo -e "removing tmp_dir $tmp_dir\n\n"
rm -rf $tmp_dir
cd $WORKDIR
}

View File

@ -104,7 +104,7 @@ case ${INTEGRATION} in
check_fmt_with_all_tests
cd -
;;
error-chain | tempdir)
tempdir)
git clone --depth=1 https://github.com/rust-lang-deprecated/${INTEGRATION}.git
cd ${INTEGRATION}
show_head

View File

@ -68,7 +68,11 @@ fn get_name_value_str_lit(attr: &syn::Attribute, name: &str) -> Option<String> {
match &attr.meta {
syn::Meta::NameValue(syn::MetaNameValue {
path,
value: syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Str(lit_str), .. }),
value:
syn::Expr::Lit(syn::ExprLit {
lit: syn::Lit::Str(lit_str),
..
}),
..
}) if path.is_ident(name) => Some(lit_str.value()),
_ => None,

View File

@ -3,13 +3,33 @@
<head>
<meta name="viewport" content="width=device-width">
<title>Rustfmt</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/3.0.1/github-markdown.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.0/styles/github-gist.min.css">
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/3.0.1/github-markdown.min.css"
integrity="sha512-7e0rszTy0dKTIgYzCeBXpmycq0EOkwAvxZ0dv/LAtQfcXWCoaRhzs+v2Mn6of3jImxPazbYxiK0kpE/7wZ/UQA=="
crossorigin="anonymous"
referrerpolicy="no-referrer" />
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.0/styles/github-gist.min.css"
integrity="sha512-od7JLoOTxM8w/HSKGzP9Kexc20K9p/M2zxSWsd7H1e4Ctf+8SQFtCWEZnW5u6ul5ehSECa5QmOk9ju2nQMmlVA=="
crossorigin="anonymous"
referrerpolicy="no-referrer" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/12.0.2/marked.min.js"
integrity="sha512-xeUh+KxNyTufZOje++oQHstlMQ8/rpyzPuM+gjMFYK3z5ILJGE7l2NvYL+XfliKURMpBIKKp1XoPN/qswlSMFA=="
crossorigin="anonymous"
referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"
integrity="sha512-PwQ5+jgXxxprNGc80ycHE3spgj6TuDieHe/yTkbEJ+U5aol7dTupi/4VbwHHzlQVW77Vb0GLOIsiYigHgC5vcg=="
crossorigin="anonymous"
referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.0/highlight.min.js"
integrity="sha512-av6ZR84Ldk6j29DMhf6v0cssEhow1VROFLoKbX7wrvzZB++/nV8m0jXbYeWcHPEzSNONImx6zwBskCUT9AQidA=="
crossorigin="anonymous"
referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"
integrity="sha512-3BBFWr73Xrf8GRjO+0pl0cbVwESBvg3ovnuCXpoqOkC/mkt/hTkFtutUPrwRz8eLySYvy5v1daulkyUZYvH8jw=="
crossorigin="anonymous"
referrerpolicy="no-referrer"></script>
<script src="https://unpkg.com/vue-async-computed@3.8.1"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.0/highlight.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
<style>
@media (max-width: 767px) {
.markdown-body {

View File

@ -20,7 +20,7 @@
- Open Rustfmt settings (File → Settings → Languages & Frameworks → Rust → Rustfmt) and enable "Run rustfmt on Save"
![run_rustfmt_on_save](https://user-images.githubusercontent.com/6505554/83944610-3468f380-a81e-11ea-9c34-0cbd18dd4969.png)
- IntellJ uses autosave, so now your files will always be formatted according to rustfmt. Alternatively you can use Ctrl+S to reformat file manually
- IntelliJ uses autosave, so now your files will always be formatted according to rustfmt. Alternatively you can use Ctrl+S to reformat file manually
### Bind shortcut to "Reformat File with Rustfmt" action

View File

@ -1,3 +1,3 @@
[toolchain]
channel = "nightly-2023-10-22"
channel = "nightly-2024-06-13"
components = ["llvm-tools", "rustc-dev"]

View File

@ -353,10 +353,18 @@ impl Rewrite for ast::Attribute {
// 1 = `[`
let shape = shape.offset_left(prefix.len() + 1)?;
Some(
meta.rewrite(context, shape)
.map_or_else(|| snippet.to_owned(), |rw| format!("{}[{}]", prefix, rw)),
)
Some(meta.rewrite(context, shape).map_or_else(
|| snippet.to_owned(),
|rw| match &self.kind {
ast::AttrKind::Normal(normal_attr) => match normal_attr.item.unsafety {
// For #![feature(unsafe_attributes)]
// See https://github.com/rust-lang/rust/issues/123757
ast::Safety::Unsafe(_) => format!("{}[unsafe({})]", prefix, rw),
_ => format!("{}[{}]", prefix, rw),
},
_ => format!("{}[{}]", prefix, rw),
},
))
} else {
Some(snippet.to_owned())
}

View File

@ -387,16 +387,11 @@ fn format_and_emit_report<T: Write>(session: &mut Session<'_, T>, input: Input)
}
fn should_print_with_colors<T: Write>(session: &mut Session<'_, T>) -> bool {
match term::stderr() {
Some(ref t)
if session.config.color().use_colored_tty()
&& t.supports_color()
&& t.supports_attr(term::Attr::Bold) =>
{
true
}
_ => false,
}
term::stderr().is_some_and(|t| {
session.config.color().use_colored_tty()
&& t.supports_color()
&& t.supports_attr(term::Attr::Bold)
})
}
fn print_usage_to_stdout(opts: &Options, reason: &str) {
@ -445,7 +440,7 @@ fn print_version() {
fn determine_operation(matches: &Matches) -> Result<Operation, OperationError> {
if matches.opt_present("h") {
let topic = matches.opt_str("h");
if topic == None {
if topic.is_none() {
return Ok(Operation::Help(HelpOp::None));
} else if topic == Some("config".to_owned()) {
return Ok(Operation::Help(HelpOp::Config));

View File

@ -61,7 +61,7 @@ pub struct Opts {
/// Options passed to rustfmt
// 'raw = true' to make `--` explicit.
#[arg(name = "rustfmt_options", raw = true)]
#[arg(id = "rustfmt_options", raw = true)]
rustfmt_options: Vec<String>,
/// Format all packages, and also their local path-based dependencies
@ -209,9 +209,8 @@ fn convert_message_format_to_rustfmt_args(
fn print_usage_to_stderr(reason: &str) {
eprintln!("{reason}");
let app = Opts::command();
app.after_help("")
.write_help(&mut io::stderr())
.expect("failed to write to stderr");
let help = app.after_help("").render_help();
eprintln!("{help}");
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@ -507,7 +506,7 @@ fn run_rustfmt(
let mut command = rustfmt_command()
.stdout(stdout)
.args(files)
.args(&["--edition", edition.as_str()])
.args(["--edition", edition.as_str()])
.args(fmt_args)
.spawn()
.map_err(|e| match e.kind() {

View File

@ -20,7 +20,7 @@ fn default_options() {
#[test]
fn good_options() {
let o = Opts::parse_from(&[
let o = Opts::parse_from([
"test",
"-q",
"-p",
@ -48,7 +48,7 @@ fn good_options() {
fn unexpected_option() {
assert!(
Opts::command()
.try_get_matches_from(&["test", "unexpected"])
.try_get_matches_from(["test", "unexpected"])
.is_err()
);
}
@ -57,7 +57,7 @@ fn unexpected_option() {
fn unexpected_flag() {
assert!(
Opts::command()
.try_get_matches_from(&["test", "--flag"])
.try_get_matches_from(["test", "--flag"])
.is_err()
);
}
@ -66,19 +66,19 @@ fn unexpected_flag() {
fn mandatory_separator() {
assert!(
Opts::command()
.try_get_matches_from(&["test", "--emit"])
.try_get_matches_from(["test", "--emit"])
.is_err()
);
assert!(
Opts::command()
.try_get_matches_from(&["test", "--", "--emit"])
.try_get_matches_from(["test", "--", "--emit"])
.is_ok()
);
}
#[test]
fn multiple_packages_one_by_one() {
let o = Opts::parse_from(&[
let o = Opts::parse_from([
"test",
"-p",
"package1",
@ -92,7 +92,7 @@ fn multiple_packages_one_by_one() {
#[test]
fn multiple_packages_grouped() {
let o = Opts::parse_from(&[
let o = Opts::parse_from([
"test",
"--package",
"package1",
@ -108,7 +108,7 @@ fn multiple_packages_grouped() {
fn empty_packages_1() {
assert!(
Opts::command()
.try_get_matches_from(&["test", "-p"])
.try_get_matches_from(["test", "-p"])
.is_err()
);
}
@ -117,7 +117,7 @@ fn empty_packages_1() {
fn empty_packages_2() {
assert!(
Opts::command()
.try_get_matches_from(&["test", "-p", "--", "--check"])
.try_get_matches_from(["test", "-p", "--", "--check"])
.is_err()
);
}
@ -126,7 +126,7 @@ fn empty_packages_2() {
fn empty_packages_3() {
assert!(
Opts::command()
.try_get_matches_from(&["test", "-p", "--verbose"])
.try_get_matches_from(["test", "-p", "--verbose"])
.is_err()
);
}
@ -135,7 +135,7 @@ fn empty_packages_3() {
fn empty_packages_4() {
assert!(
Opts::command()
.try_get_matches_from(&["test", "-p", "--check"])
.try_get_matches_from(["test", "-p", "--check"])
.is_err()
);
}

View File

@ -3,8 +3,6 @@
use std::{borrow::Cow, iter};
use itertools::{multipeek, MultiPeek};
use lazy_static::lazy_static;
use regex::Regex;
use rustc_span::Span;
use crate::config::Config;
@ -17,17 +15,6 @@ use crate::utils::{
};
use crate::{ErrorKind, FormattingError};
lazy_static! {
/// A regex matching reference doc links.
///
/// ```markdown
/// /// An [example].
/// ///
/// /// [example]: this::is::a::link
/// ```
static ref REFERENCE_LINK_URL: Regex = Regex::new(r"^\[.+\]\s?:").unwrap();
}
fn is_custom_comment(comment: &str) -> bool {
if !comment.starts_with("//") {
false
@ -173,10 +160,7 @@ pub(crate) fn combine_strs_with_missing_comments(
) -> Option<String> {
trace!(
"combine_strs_with_missing_comments `{}` `{}` {:?} {:?}",
prev_str,
next_str,
span,
shape
prev_str, next_str, span, shape
);
let mut result =
@ -208,7 +192,7 @@ pub(crate) fn combine_strs_with_missing_comments(
// We have a missing comment between the first expression and the second expression.
// Peek the the original source code and find out whether there is a newline between the first
// Peek the original source code and find out whether there is a newline between the first
// expression and the second expression or the missing comment. We will preserve the original
// layout whenever possible.
let original_snippet = context.snippet(span);
@ -506,7 +490,7 @@ impl ItemizedBlock {
let mut line_start = " ".repeat(indent);
// Markdown blockquote start with a "> "
if line.trim_start().starts_with(">") {
if line.trim_start().starts_with('>') {
// remove the original +2 indent because there might be multiple nested block quotes
// and it's easier to reason about the final indent by just taking the length
// of the new line_start. We update the indent because it effects the max width
@ -657,7 +641,7 @@ impl<'a> CommentRewrite<'a> {
while let Some(line) = iter.next() {
result.push_str(line);
result.push_str(match iter.peek() {
Some(next_line) if next_line.is_empty() => sep.trim_end(),
Some(&"") => sep.trim_end(),
Some(..) => sep,
None => "",
});
@ -666,7 +650,7 @@ impl<'a> CommentRewrite<'a> {
}
/// Check if any characters were written to the result buffer after the start of the comment.
/// when calling [`CommentRewrite::new()`] the result buffer is initiazlied with the opening
/// when calling [`CommentRewrite::new()`] the result buffer is initialized with the opening
/// characters for the comment.
fn buffer_contains_comment(&self) -> bool {
// if self.result.len() < self.opener.len() then an empty comment is in the buffer
@ -839,7 +823,7 @@ impl<'a> CommentRewrite<'a> {
}
}
let is_markdown_header_doc_comment = is_doc_comment && line.starts_with("#");
let is_markdown_header_doc_comment = is_doc_comment && line.starts_with('#');
// We only want to wrap the comment if:
// 1) wrap_comments = true is configured
@ -979,12 +963,21 @@ fn trim_custom_comment_prefix(s: &str) -> String {
/// Returns `true` if the given string MAY include URLs or alike.
fn has_url(s: &str) -> bool {
// A regex matching reference doc links.
//
// ```markdown
// /// An [example].
// ///
// /// [example]: this::is::a::link
// ```
let reference_link_url = static_regex!(r"^\[.+\]\s?:");
// This function may return false positive, but should get its job done in most cases.
s.contains("https://")
|| s.contains("http://")
|| s.contains("ftp://")
|| s.contains("file://")
|| REFERENCE_LINK_URL.is_match(s)
|| reference_link_url.is_match(s)
}
/// Returns true if the given string may be part of a Markdown table.
@ -1263,15 +1256,15 @@ pub(crate) enum FullCodeCharKind {
InComment,
/// Last character of a comment, '\n' for a line comment, '/' for a block comment.
EndComment,
/// Start of a mutlitine string inside a comment
/// Start of a multiline string inside a comment
StartStringCommented,
/// End of a mutlitine string inside a comment
/// End of a multiline string inside a comment
EndStringCommented,
/// Inside a commented string
InStringCommented,
/// Start of a mutlitine string
/// Start of a multiline string
StartString,
/// End of a mutlitine string
/// End of a multiline string
EndString,
/// Inside a string.
InString,
@ -1764,7 +1757,7 @@ fn changed_comment_content(orig: &str, new: &str) -> bool {
let code_comment_content = |code| {
let slices = UngroupedCommentCodeSlices::new(code);
slices
.filter(|&(ref kind, _, _)| *kind == CodeCharKind::Comment)
.filter(|(kind, _, _)| *kind == CodeCharKind::Comment)
.flat_map(|(_, _, s)| CommentReducer::new(s))
};
let res = code_comment_content(orig).ne(code_comment_content(new));

View File

@ -66,7 +66,7 @@ impl ConfigType for IgnoreList {
}
macro_rules! create_config {
// Options passed in to the macro.
// Options passed into the macro.
//
// - $i: the ident name of the option
// - $ty: the type of the option value
@ -129,6 +129,7 @@ macro_rules! create_config {
| "chain_width" => self.0.set_heuristics(),
"merge_imports" => self.0.set_merge_imports(),
"fn_args_layout" => self.0.set_fn_args_layout(),
"hide_parse_errors" => self.0.set_hide_parse_errors(),
&_ => (),
}
}
@ -184,6 +185,7 @@ macro_rules! create_config {
self.set_ignore(dir);
self.set_merge_imports();
self.set_fn_args_layout();
self.set_hide_parse_errors();
self
}
@ -278,19 +280,21 @@ macro_rules! create_config {
| "chain_width" => self.set_heuristics(),
"merge_imports" => self.set_merge_imports(),
"fn_args_layout" => self.set_fn_args_layout(),
"hide_parse_errors" => self.set_hide_parse_errors(),
&_ => (),
}
}
#[allow(unreachable_pub)]
pub fn is_hidden_option(name: &str) -> bool {
const HIDE_OPTIONS: [&str; 6] = [
const HIDE_OPTIONS: [&str; 7] = [
"verbose",
"verbose_diff",
"file_lines",
"width_heuristics",
"merge_imports",
"fn_args_layout"
"fn_args_layout",
"hide_parse_errors"
];
HIDE_OPTIONS.contains(&name)
}
@ -461,6 +465,18 @@ macro_rules! create_config {
}
}
fn set_hide_parse_errors(&mut self) {
if self.was_set().hide_parse_errors() {
eprintln!(
"Warning: the `hide_parse_errors` option is deprecated. \
Use `show_parse_errors` instead"
);
if !self.was_set().show_parse_errors() {
self.show_parse_errors.2 = self.hide_parse_errors();
}
}
}
#[allow(unreachable_pub)]
/// Returns `true` if the config key was explicitly set and is the default value.
pub fn is_default(&self, key: &str) -> bool {

View File

@ -26,6 +26,7 @@ pub(crate) mod file_lines;
#[allow(unreachable_pub)]
pub(crate) mod lists;
pub(crate) mod macro_names;
pub(crate) mod style_edition;
// This macro defines configuration options used in rustfmt. Each option
// is defined as follows:
@ -73,7 +74,7 @@ create_config! {
format_strings: bool, false, false, "Format string literals where necessary";
format_macro_matchers: bool, false, false,
"Format the metavariable matching patterns in macros";
format_macro_bodies: bool, true, false, "Format the bodies of macros";
format_macro_bodies: bool, true, false, "Format the bodies of declarative macro definitions";
skip_macro_invocations: MacroSelectors, MacroSelectors::default(), false,
"Skip formatting the bodies of macros invoked with the following names.";
hex_literal_case: HexLiteralCase, HexLiteralCase::Preserve, false,
@ -150,6 +151,8 @@ create_config! {
"Write an item and its attribute on the same line \
if their combined width is below a threshold";
format_generated_files: bool, true, false, "Format generated files";
generated_marker_line_search_limit: usize, 5, false, "Number of lines to check for a \
`@generated` marker when `format_generated_files` is enabled";
// Options that can change the source code beyond whitespace/blocks (somewhat linty things)
merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one";
@ -168,7 +171,8 @@ create_config! {
"Enables unstable features. Only available on nightly channel";
disable_all_formatting: bool, false, true, "Don't reformat anything";
skip_children: bool, false, false, "Don't reformat out of line modules";
hide_parse_errors: bool, false, false, "Hide errors from the parser";
hide_parse_errors: bool, false, false, "(deprecated: use show_parse_errors instead)";
show_parse_errors: bool, true, false, "Show errors from the parser (unstable)";
error_on_line_overflow: bool, false, false, "Error if unable to get all lines within max_width";
error_on_unformatted: bool, false, false,
"Error if unable to get comments or string literals within max_width, \
@ -203,6 +207,7 @@ impl PartialConfig {
cloned.print_misformatted_file_names = None;
cloned.merge_imports = None;
cloned.fn_args_layout = None;
cloned.hide_parse_errors = None;
::toml::to_string(&cloned).map_err(ToTomlError)
}
@ -282,7 +287,7 @@ impl Config {
}
}
// If none was found ther either, check in the user's configuration directory.
// If none was found there either, check in the user's configuration directory.
if let Some(mut config_dir) = dirs::config_dir() {
config_dir.push("rustfmt");
if let Some(path) = get_toml_path(&config_dir)? {
@ -455,6 +460,13 @@ mod test {
fn_params_layout: Density, Density::Tall, true,
"Control the layout of parameters in a function signatures.";
// hide_parse_errors renamed to show_parse_errors
hide_parse_errors: bool, false, false,
"(deprecated: use show_parse_errors instead)";
show_parse_errors: bool, true, false,
"Show errors from the parser (unstable)";
// Width Heuristics
use_small_heuristics: Heuristics, Heuristics::Default, true,
"Whether to use different formatting for items and \
@ -670,6 +682,7 @@ edition = "2015"
version = "One"
inline_attribute_width = 0
format_generated_files = true
generated_marker_line_search_limit = 5
merge_derives = true
use_try_shorthand = false
use_field_init_shorthand = false
@ -680,7 +693,7 @@ required_version = "{}"
unstable_features = false
disable_all_formatting = false
skip_children = false
hide_parse_errors = false
show_parse_errors = true
error_on_line_overflow = false
error_on_unformatted = false
ignore = []

View File

@ -191,7 +191,7 @@ pub enum Color {
pub enum Version {
/// 1.x.y. When specified, rustfmt will format in the same style as 1.0.0.
One,
/// 2.x.y. When specified, rustfmt will format in the the latest style.
/// 2.x.y. When specified, rustfmt will format in the latest style.
Two,
}
@ -416,7 +416,7 @@ pub trait CliOptions {
fn config_path(&self) -> Option<&Path>;
}
/// The edition of the syntax and semntics of code (RFC 2052).
/// The edition of the syntax and semantics of code (RFC 2052).
#[config_type]
pub enum Edition {
#[value = "2015"]
@ -470,3 +470,27 @@ pub enum MatchArmLeadingPipe {
/// Preserve any existing leading pipes
Preserve,
}
/// Defines the default values for each config according to [the style guide].
/// rustfmt output may differ between style editions.
///
/// [the style guide]: https://doc.rust-lang.org/nightly/style-guide/
#[config_type]
pub enum StyleEdition {
#[value = "2015"]
#[doc_hint = "2015"]
/// [Edition 2015]()
Edition2015,
#[value = "2018"]
#[doc_hint = "2018"]
/// [Edition 2018]()
Edition2018,
#[value = "2021"]
#[doc_hint = "2021"]
/// [Edition 2021]()
Edition2021,
#[value = "2024"]
#[doc_hint = "2024"]
/// [Edition 2024]().
Edition2024,
}

View File

@ -0,0 +1,70 @@
use crate::config::StyleEdition;
/// Defines the default value for the given style edition
#[allow(dead_code)]
pub(crate) trait StyleEditionDefault {
type ConfigType;
fn style_edition_default(style_edition: StyleEdition) -> Self::ConfigType;
}
/// macro to help implement `StyleEditionDefault` for config options
#[macro_export]
macro_rules! style_edition_default {
($ty:ident, $config_ty:ty, _ => $default:expr) => {
impl $crate::config::style_edition::StyleEditionDefault for $ty {
type ConfigType = $config_ty;
fn style_edition_default(_: $crate::config::StyleEdition) -> Self::ConfigType {
$default
}
}
};
($ty:ident, $config_ty:ty, Edition2024 => $default_2024:expr, _ => $default_2015:expr) => {
impl $crate::config::style_edition::StyleEditionDefault for $ty {
type ConfigType = $config_ty;
fn style_edition_default(
style_edition: $crate::config::StyleEdition,
) -> Self::ConfigType {
match style_edition {
$crate::config::StyleEdition::Edition2015
| $crate::config::StyleEdition::Edition2018
| $crate::config::StyleEdition::Edition2021 => $default_2015,
$crate::config::StyleEdition::Edition2024 => $default_2024,
}
}
}
};
}
#[cfg(test)]
mod test {
use super::*;
use crate::config::StyleEdition;
#[test]
fn test_impl_default_style_edition_struct_for_all_editions() {
struct Unit;
style_edition_default!(Unit, usize, _ => 100);
// regardless of the style edition used the value will always return 100
assert_eq!(Unit::style_edition_default(StyleEdition::Edition2015), 100);
assert_eq!(Unit::style_edition_default(StyleEdition::Edition2018), 100);
assert_eq!(Unit::style_edition_default(StyleEdition::Edition2021), 100);
assert_eq!(Unit::style_edition_default(StyleEdition::Edition2024), 100);
}
#[test]
fn test_impl_default_style_edition_for_old_and_new_editions() {
struct Unit;
style_edition_default!(Unit, usize, Edition2024 => 50, _ => 100);
// style edition 2015-2021 are all the same
assert_eq!(Unit::style_edition_default(StyleEdition::Edition2015), 100);
assert_eq!(Unit::style_edition_default(StyleEdition::Edition2018), 100);
assert_eq!(Unit::style_edition_default(StyleEdition::Edition2021), 100);
// style edition 2024
assert_eq!(Unit::style_edition_default(StyleEdition::Edition2024), 50);
}
}

View File

@ -89,11 +89,11 @@ mod tests {
#[test]
fn emits_single_xml_tree_containing_all_files() {
let bin_file = "src/bin.rs";
let bin_original = vec!["fn main() {", "println!(\"Hello, world!\");", "}"];
let bin_formatted = vec!["fn main() {", " println!(\"Hello, world!\");", "}"];
let bin_original = ["fn main() {", "println!(\"Hello, world!\");", "}"];
let bin_formatted = ["fn main() {", " println!(\"Hello, world!\");", "}"];
let lib_file = "src/lib.rs";
let lib_original = vec!["fn greet() {", "println!(\"Greetings!\");", "}"];
let lib_formatted = vec!["fn greet() {", " println!(\"Greetings!\");", "}"];
let lib_original = ["fn greet() {", "println!(\"Greetings!\");", "}"];
let lib_formatted = ["fn greet() {", " println!(\"Greetings!\");", "}"];
let mut writer = Vec::new();
let mut emitter = CheckstyleEmitter::default();
let _ = emitter.emit_header(&mut writer);
@ -118,7 +118,7 @@ mod tests {
)
.unwrap();
let _ = emitter.emit_footer(&mut writer);
let exp_bin_xml = vec![
let exp_bin_xml = [
format!(r#"<file name="{}">"#, bin_file),
format!(
r#"<error line="2" severity="warning" message="Should be `{}`" />"#,
@ -126,7 +126,7 @@ mod tests {
),
String::from("</file>"),
];
let exp_lib_xml = vec![
let exp_lib_xml = [
format!(r#"<file name="{}">"#, lib_file),
format!(
r#"<error line="2" severity="warning" message="Should be `{}`" />"#,
@ -136,7 +136,7 @@ mod tests {
];
assert_eq!(
String::from_utf8(writer).unwrap(),
vec![
[
r#"<?xml version="1.0" encoding="utf-8"?>"#,
"\n",
r#"<checkstyle version="4.3">"#,

View File

@ -32,7 +32,7 @@ impl Emitter for DiffEmitter {
} else {
print_diff(
mismatch,
|line_num| format!("Diff in {} at line {}:", filename, line_num),
|line_num| format!("Diff in {}:{}:", filename, line_num),
&self.config,
);
}

View File

@ -212,7 +212,7 @@ mod tests {
#[test]
fn emits_array_with_files_with_diffs() {
let file_name = "src/bin.rs";
let original = vec![
let original = [
"fn main() {",
"println!(\"Hello, world!\");",
"}",
@ -225,7 +225,7 @@ mod tests {
"}",
"}",
];
let formatted = vec![
let formatted = [
"fn main() {",
" println!(\"Hello, world!\");",
"}",
@ -285,11 +285,11 @@ mod tests {
#[test]
fn emits_valid_json_with_multiple_files() {
let bin_file = "src/bin.rs";
let bin_original = vec!["fn main() {", "println!(\"Hello, world!\");", "}"];
let bin_formatted = vec!["fn main() {", " println!(\"Hello, world!\");", "}"];
let bin_original = ["fn main() {", "println!(\"Hello, world!\");", "}"];
let bin_formatted = ["fn main() {", " println!(\"Hello, world!\");", "}"];
let lib_file = "src/lib.rs";
let lib_original = vec!["fn greet() {", "println!(\"Greetings!\");", "}"];
let lib_formatted = vec!["fn greet() {", " println!(\"Greetings!\");", "}"];
let lib_original = ["fn greet() {", "println!(\"Greetings!\");", "}"];
let lib_formatted = ["fn greet() {", " println!(\"Greetings!\");", "}"];
let mut writer = Vec::new();
let mut emitter = JsonEmitter::default();
let _ = emitter.emit_header(&mut writer);

View File

@ -139,7 +139,17 @@ pub(crate) fn format_expr(
| ast::ExprKind::While(..) => to_control_flow(expr, expr_type)
.and_then(|control_flow| control_flow.rewrite(context, shape)),
ast::ExprKind::ConstBlock(ref anon_const) => {
Some(format!("const {}", anon_const.rewrite(context, shape)?))
let rewrite = match anon_const.value.kind {
ast::ExprKind::Block(ref block, opt_label) => {
// Inner attributes are associated with the `ast::ExprKind::ConstBlock` node,
// not the `ast::Block` node we're about to rewrite. To prevent dropping inner
// attributes call `rewrite_block` directly.
// See https://github.com/rust-lang/rustfmt/issues/6158
rewrite_block(block, Some(&expr.attrs), opt_label, context, shape)?
}
_ => anon_const.rewrite(context, shape)?,
};
Some(format!("const {}", rewrite))
}
ast::ExprKind::Block(ref block, opt_label) => {
match expr_type {
@ -253,14 +263,6 @@ pub(crate) fn format_expr(
shape,
SeparatorPlace::Front,
),
ast::ExprKind::Type(ref expr, ref ty) => rewrite_pair(
&**expr,
&**ty,
PairParts::infix(": "),
context,
shape,
SeparatorPlace::Back,
),
ast::ExprKind::Index(ref expr, ref index, _) => {
rewrite_index(&**expr, &**index, context, shape)
}
@ -282,6 +284,9 @@ pub(crate) fn format_expr(
match lhs.kind {
ast::ExprKind::Lit(token_lit) => lit_ends_in_dot(&token_lit),
ast::ExprKind::Unary(_, ref expr) => needs_space_before_range(context, expr),
ast::ExprKind::Binary(_, _, ref rhs_expr) => {
needs_space_before_range(context, rhs_expr)
}
_ => false,
}
}
@ -399,10 +404,14 @@ pub(crate) fn format_expr(
}
ast::ExprKind::Underscore => Some("_".to_owned()),
ast::ExprKind::FormatArgs(..)
| ast::ExprKind::Type(..)
| ast::ExprKind::IncludedBytes(..)
| ast::ExprKind::OffsetOf(..) => {
// These do not occur in the AST because macros aren't expanded.
unreachable!()
// These don't normally occur in the AST because macros aren't expanded. However,
// rustfmt tries to parse macro arguments when formatting macros, so it's not totally
// impossible for rustfmt to come across one of these nodes when formatting a file.
// Also, rustfmt might get passed the output from `-Zunpretty=expanded`.
None
}
ast::ExprKind::Err(_) | ast::ExprKind::Dummy => None,
};

View File

@ -38,14 +38,14 @@ enum FormatDiffError {
}
#[derive(Parser, Debug)]
#[clap(
#[command(
name = "rustfmt-format-diff",
disable_version_flag = true,
next_line_help = true
)]
pub struct Opts {
/// Skip the smallest prefix containing NUMBER slashes
#[clap(
#[arg(
short = 'p',
long = "skip-prefix",
value_name = "NUMBER",
@ -54,7 +54,7 @@ pub struct Opts {
skip_prefix: u32,
/// Custom pattern selecting file paths to reformat
#[clap(
#[arg(
short = 'f',
long = "filter",
value_name = "PATTERN",
@ -234,14 +234,14 @@ mod cmd_line_tests {
#[test]
fn default_options() {
let empty: Vec<String> = vec![];
let o = Opts::parse_from(&empty);
let o = Opts::parse_from(empty);
assert_eq!(DEFAULT_PATTERN, o.filter);
assert_eq!(0, o.skip_prefix);
}
#[test]
fn good_options() {
let o = Opts::parse_from(&["test", "-p", "10", "-f", r".*\.hs"]);
let o = Opts::parse_from(["test", "-p", "10", "-f", r".*\.hs"]);
assert_eq!(r".*\.hs", o.filter);
assert_eq!(10, o.skip_prefix);
}
@ -250,7 +250,7 @@ mod cmd_line_tests {
fn unexpected_option() {
assert!(
Opts::command()
.try_get_matches_from(&["test", "unexpected"])
.try_get_matches_from(["test", "unexpected"])
.is_err()
);
}
@ -259,7 +259,7 @@ mod cmd_line_tests {
fn unexpected_flag() {
assert!(
Opts::command()
.try_get_matches_from(&["test", "--flag"])
.try_get_matches_from(["test", "--flag"])
.is_err()
);
}
@ -268,7 +268,7 @@ mod cmd_line_tests {
fn overridden_option() {
assert!(
Opts::command()
.try_get_matches_from(&["test", "-p", "10", "-p", "20"])
.try_get_matches_from(["test", "-p", "10", "-p", "20"])
.is_err()
);
}
@ -277,7 +277,7 @@ mod cmd_line_tests {
fn negative_filter() {
assert!(
Opts::command()
.try_get_matches_from(&["test", "-p", "-1"])
.try_get_matches_from(["test", "-p", "-1"])
.is_err()
);
}

View File

@ -82,7 +82,7 @@ fn should_skip_module<T: FormatHandler>(
let source_file = context.psess.span_to_file_contents(module.span);
let src = source_file.src.as_ref().expect("SourceFile without src");
if is_generated_file(src) {
if is_generated_file(src, config) {
return true;
}
}

View File

@ -1,7 +1,10 @@
use crate::Config;
/// Returns `true` if the given span is a part of generated files.
pub(super) fn is_generated_file(original_snippet: &str) -> bool {
pub(super) fn is_generated_file(original_snippet: &str, config: &Config) -> bool {
original_snippet
.lines()
.take(5) // looking for marker only in the beginning of the file
// looking for marker only in the beginning of the file
.take(config.generated_marker_line_search_limit())
.any(|line| line.contains("@generated"))
}

View File

@ -49,4 +49,22 @@ mod test {
assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("bar_dir/baz.rs"))));
assert!(!ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/bar.rs"))));
}
#[nightly_only_test]
#[test]
fn test_negated_ignore_path_set() {
use crate::config::{Config, FileName};
use crate::ignore_path::IgnorePathSet;
use std::path::{Path, PathBuf};
let config = Config::from_toml(
r#"ignore = ["foo.rs", "bar_dir/*", "!bar_dir/*/what.rs"]"#,
Path::new(""),
)
.unwrap();
let ignore_path_set = IgnorePathSet::from_ignore_list(&config.ignore()).unwrap();
assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("bar_dir/what.rs"))));
assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("bar_dir/baz/a.rs"))));
assert!(!ignore_path_set.is_match(&FileName::Real(PathBuf::from("bar_dir/baz/what.rs"))));
}
}

View File

@ -685,9 +685,9 @@ impl UseTree {
let prefix = &self.path[..self.path.len() - 1];
let mut result = vec![];
for nested_use_tree in list {
for flattend in &mut nested_use_tree.clone().flatten(import_granularity) {
for flattened in &mut nested_use_tree.clone().flatten(import_granularity) {
let mut new_path = prefix.to_vec();
new_path.append(&mut flattend.path);
new_path.append(&mut flattened.path);
result.push(UseTree {
path: new_path,
span: self.span,

View File

@ -656,9 +656,16 @@ impl<'a> FmtVisitor<'a> {
}
let context = self.get_context();
// 1 = ','
let shape = self.shape().sub_width(1)?;
let attrs_str = field.attrs.rewrite(&context, shape)?;
let shape = self.shape();
let attrs_str = if context.config.version() == Version::Two {
field.attrs.rewrite(&context, shape)?
} else {
// Version::One formatting that was off by 1. See issue #5801
field.attrs.rewrite(&context, shape.sub_width(1)?)?
};
// sub_width(1) to take the trailing comma into account
let shape = shape.sub_width(1)?;
let lo = field
.attrs
.last()
@ -836,13 +843,15 @@ pub(crate) fn format_impl(
if is_impl_single_line(context, items.as_slice(), &result, &where_clause_str, item)? {
result.push_str(&where_clause_str);
if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) {
// if the where_clause contains extra comments AND
// there is only one where-clause predicate
// recover the suppressed comma in single line where_clause formatting
if where_clause_str.contains('\n') {
// If there is only one where-clause predicate
// and the where-clause spans multiple lines,
// then recover the suppressed comma in single line where-clause formatting
if generics.where_clause.predicates.len() == 1 {
result.push(',');
}
}
if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) {
result.push_str(&format!("{sep}{{{sep}}}"));
} else {
result.push_str(" {}");
@ -1161,9 +1170,9 @@ pub(crate) fn format_trait(
// FIXME(#2055): rustfmt fails to format when there are comments between trait bounds.
if !bounds.is_empty() {
let ident_hi = context
.snippet_provider
.span_after(item.span, item.ident.as_str());
// Retrieve *unnormalized* ident (See #6069)
let source_ident = context.snippet(item.ident.span);
let ident_hi = context.snippet_provider.span_after(item.span, source_ident);
let bound_hi = bounds.last().unwrap().span().hi();
let snippet = context.snippet(mk_sp(ident_hi, bound_hi));
if contains_comment(snippet) {
@ -1906,6 +1915,7 @@ pub(crate) fn rewrite_struct_field(
pub(crate) struct StaticParts<'a> {
prefix: &'a str,
safety: ast::Safety,
vis: &'a ast::Visibility,
ident: symbol::Ident,
ty: &'a ast::Ty,
@ -1917,11 +1927,12 @@ pub(crate) struct StaticParts<'a> {
impl<'a> StaticParts<'a> {
pub(crate) fn from_item(item: &'a ast::Item) -> Self {
let (defaultness, prefix, ty, mutability, expr) = match &item.kind {
ast::ItemKind::Static(s) => (None, "static", &s.ty, s.mutability, &s.expr),
let (defaultness, prefix, safety, ty, mutability, expr) = match &item.kind {
ast::ItemKind::Static(s) => (None, "static", s.safety, &s.ty, s.mutability, &s.expr),
ast::ItemKind::Const(c) => (
Some(c.defaultness),
"const",
ast::Safety::Default,
&c.ty,
ast::Mutability::Not,
&c.expr,
@ -1930,6 +1941,7 @@ impl<'a> StaticParts<'a> {
};
StaticParts {
prefix,
safety,
vis: &item.vis,
ident: item.ident,
ty,
@ -1947,6 +1959,7 @@ impl<'a> StaticParts<'a> {
};
StaticParts {
prefix: "const",
safety: ast::Safety::Default,
vis: &ti.vis,
ident: ti.ident,
ty,
@ -1964,6 +1977,7 @@ impl<'a> StaticParts<'a> {
};
StaticParts {
prefix: "const",
safety: ast::Safety::Default,
vis: &ii.vis,
ident: ii.ident,
ty,
@ -1980,11 +1994,13 @@ fn rewrite_static(
static_parts: &StaticParts<'_>,
offset: Indent,
) -> Option<String> {
println!("rewriting static");
let colon = colon_spaces(context.config);
let mut prefix = format!(
"{}{}{} {}{}{}",
"{}{}{}{} {}{}{}",
format_visibility(context, static_parts.vis),
static_parts.defaultness.map_or("", format_defaultness),
format_safety(static_parts.safety),
static_parts.prefix,
format_mutability(static_parts.mutability),
rewrite_ident(context, static_parts.ident),
@ -2483,7 +2499,7 @@ fn rewrite_fn_base(
|| context.config.indent_style() == IndentStyle::Visual
{
let indent = if param_str.is_empty() {
// Aligning with non-existent params looks silly.
// Aligning with nonexistent params looks silly.
force_new_line_for_brace = true;
indent + 4
} else {
@ -2498,7 +2514,7 @@ fn rewrite_fn_base(
} else {
let mut ret_shape = Shape::indented(indent, context.config);
if param_str.is_empty() {
// Aligning with non-existent params looks silly.
// Aligning with nonexistent params looks silly.
force_new_line_for_brace = true;
ret_shape = if context.use_block_indent() {
ret_shape.offset_left(4).unwrap_or(ret_shape)
@ -3329,10 +3345,12 @@ impl Rewrite for ast::ForeignItem {
// FIXME(#21): we're dropping potential comments in between the
// function kw here.
let vis = format_visibility(context, &self.vis);
let safety = format_safety(static_foreign_item.safety);
let mut_str = format_mutability(static_foreign_item.mutability);
let prefix = format!(
"{}static {}{}:",
"{}{}static {}{}:",
vis,
safety,
mut_str,
rewrite_ident(context, self.ident)
);

View File

@ -5,9 +5,6 @@
#![allow(clippy::match_like_matches_macro)]
#![allow(unreachable_pub)]
#[cfg(test)]
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate tracing;
@ -62,6 +59,13 @@ pub use crate::rustfmt_diff::{ModifiedChunk, ModifiedLines};
#[macro_use]
mod utils;
macro_rules! static_regex {
($re:literal) => {{
static RE: ::std::sync::OnceLock<::regex::Regex> = ::std::sync::OnceLock::new();
RE.get_or_init(|| ::regex::Regex::new($re).unwrap())
}};
}
mod attr;
mod chains;
mod closures;
@ -258,8 +262,8 @@ impl FormatReport {
self.internal
.borrow()
.0
.iter()
.map(|(_, errors)| errors.len())
.values()
.map(|errors| errors.len())
.sum()
}
@ -305,7 +309,7 @@ fn format_snippet(snippet: &str, config: &Config, is_macro_def: bool) -> Option<
let mut out: Vec<u8> = Vec::with_capacity(snippet.len() * 2);
config.set().emit_mode(config::EmitMode::Stdout);
config.set().verbose(Verbosity::Quiet);
config.set().hide_parse_errors(true);
config.set().show_parse_errors(false);
if is_macro_def {
config.set().error_on_unformatted(true);
}

View File

@ -25,6 +25,7 @@ use crate::comment::{
contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses,
};
use crate::config::lists::*;
use crate::config::Version;
use crate::expr::{rewrite_array, rewrite_assign_rhs, RhsAssignKind};
use crate::lists::{itemize_list, write_list, ListFormatting};
use crate::overflow;
@ -389,7 +390,7 @@ fn rewrite_empty_macro_def_body(
stmts: vec![].into(),
id: rustc_ast::node_id::DUMMY_NODE_ID,
rules: ast::BlockCheckMode::Default,
span: span,
span,
tokens: None,
could_be_bare_literal: false,
};
@ -1245,8 +1246,16 @@ impl MacroBranch {
return None;
}
// 5 = " => {"
let mut result = format_macro_args(context, self.args.clone(), shape.sub_width(5)?)?;
let old_body = context.snippet(self.body).trim();
let has_block_body = old_body.starts_with('{');
let mut prefix_width = 5; // 5 = " => {"
if context.config.version() == Version::Two {
if has_block_body {
prefix_width = 6; // 6 = " => {{"
}
}
let mut result =
format_macro_args(context, self.args.clone(), shape.sub_width(prefix_width)?)?;
if multi_branch_style {
result += " =>";
@ -1264,12 +1273,10 @@ impl MacroBranch {
// `$$`). We'll try and format like an AST node, but we'll substitute
// variables for new names with the same length first.
let old_body = context.snippet(self.body).trim();
let (body_str, substs) = replace_names(old_body)?;
let has_block_body = old_body.starts_with('{');
let mut config = context.config.clone();
config.set().hide_parse_errors(true);
config.set().show_parse_errors(false);
result += " {";

View File

@ -5,7 +5,7 @@ use std::iter::repeat;
use rustc_ast::{ast, ptr, MatchKind};
use rustc_span::{BytePos, Span};
use crate::comment::{combine_strs_with_missing_comments, rewrite_comment};
use crate::comment::{combine_strs_with_missing_comments, rewrite_comment, FindUncommented};
use crate::config::lists::*;
use crate::config::{Config, ControlBraceStyle, IndentStyle, MatchArmLeadingPipe, Version};
use crate::expr::{
@ -104,6 +104,10 @@ pub(crate) fn rewrite_match(
let inner_attrs_str = if inner_attrs.is_empty() {
String::new()
} else {
let shape = match context.config.version() {
Version::One => shape,
_ => shape.block_indent(context.config.tab_spaces()),
};
inner_attrs
.rewrite(context, shape)
.map(|s| format!("{}{}\n", nested_indent_str, s))?
@ -352,10 +356,10 @@ fn flatten_arm_body<'a>(
(true, body)
}
} else {
let cond_becomes_muti_line = opt_shape
let cond_becomes_multi_line = opt_shape
.and_then(|shape| rewrite_cond(context, expr, shape))
.map_or(false, |cond| cond.contains('\n'));
if cond_becomes_muti_line {
if cond_becomes_multi_line {
(false, &*body)
} else {
(can_extend(expr), &*expr)
@ -415,7 +419,11 @@ fn rewrite_match_body(
let arrow_snippet = context.snippet(arrow_span).trim();
// search for the arrow starting from the end of the snippet since there may be a match
// expression within the guard
let arrow_index = arrow_snippet.rfind("=>").unwrap();
let arrow_index = if context.config.version() == Version::One {
arrow_snippet.rfind("=>").unwrap()
} else {
arrow_snippet.find_last_uncommented("=>").unwrap()
};
// 2 = `=>`
let comment_str = arrow_snippet[arrow_index + 2..].trim();
if comment_str.is_empty() {
@ -464,8 +472,8 @@ fn rewrite_match_body(
};
let block_sep = match context.config.control_brace_style() {
ControlBraceStyle::AlwaysNextLine => format!("{}{}", alt_block_sep, body_prefix),
_ if body_prefix.is_empty() => "".to_owned(),
ControlBraceStyle::AlwaysNextLine => format!("{}{}", alt_block_sep, body_prefix),
_ if forbid_same_line || !arrow_comment.is_empty() => {
format!("{}{}", alt_block_sep, body_prefix)
}

View File

@ -8,8 +8,8 @@ use rustc_ast::{ast, ptr};
use rustc_span::Span;
use crate::closures;
use crate::config::lists::*;
use crate::config::Version;
use crate::config::{lists::*, Config};
use crate::expr::{
can_be_overflowed_expr, is_every_expr_simple, is_method_call, is_nested_call, is_simple_expr,
rewrite_cond,
@ -60,6 +60,13 @@ const SPECIAL_CASE_MACROS: &[(&str, usize)] = &[
("debug_assert_ne!", 2),
];
/// Additional special case macros for version 2; these are separated to avoid breaking changes in
/// version 1.
const SPECIAL_CASE_MACROS_V2: &[(&str, usize)] = &[
// From the `log` crate.
("trace!", 0),
];
const SPECIAL_CASE_ATTR: &[(&str, usize)] = &[
// From the `failure` crate.
("fail", 0),
@ -182,12 +189,17 @@ impl<'a> OverflowableItem<'a> {
}
}
fn special_cases(&self) -> &'static [(&'static str, usize)] {
match self {
fn special_cases(&self, config: &Config) -> impl Iterator<Item = &(&'static str, usize)> {
let base_cases = match self {
OverflowableItem::MacroArg(..) => SPECIAL_CASE_MACROS,
OverflowableItem::NestedMetaItem(..) => SPECIAL_CASE_ATTR,
_ => &[],
}
};
let additional_cases = match (self, config.version()) {
(OverflowableItem::MacroArg(..), Version::Two) => SPECIAL_CASE_MACROS_V2,
_ => &[],
};
base_cases.iter().chain(additional_cases)
}
}
@ -511,7 +523,7 @@ impl<'a> Context<'a> {
// However, when the inner function has a prefix or a suffix
// (e.g., `foo() as u32`), this budget reduction may produce poorly
// formatted code, where a prefix or a suffix being left on its own
// line. Here we explicitlly check those cases.
// line. Here we explicitly check those cases.
if count_newlines(overflowed) == 1 {
let rw = self
.items
@ -551,7 +563,7 @@ impl<'a> Context<'a> {
if tactic == DefinitiveListTactic::Vertical {
if let Some((all_simple, num_args_before)) =
maybe_get_args_offset(self.ident, &self.items)
maybe_get_args_offset(self.ident, &self.items, &self.context.config)
{
let one_line = all_simple
&& definitive_tactic(
@ -771,11 +783,11 @@ fn no_long_items(list: &[ListItem], short_array_element_width_threshold: usize)
pub(crate) fn maybe_get_args_offset(
callee_str: &str,
args: &[OverflowableItem<'_>],
config: &Config,
) -> Option<(bool, usize)> {
if let Some(&(_, num_args_before)) = args
.get(0)?
.special_cases()
.iter()
.special_cases(config)
.find(|&&(s, _)| s == callee_str)
{
let all_simple = args.len() > num_args_before

View File

@ -31,7 +31,6 @@ pub(crate) fn parse_lazy_static(
}
}
}
while parser.token.kind != TokenKind::Eof {
// Parse a `lazy_static!` item.
let vis = parse_or!(parse_visibility, rustc_parse::parser::FollowedByType::No);

View File

@ -97,7 +97,7 @@ fn default_dcx(
source_map: Lrc<SourceMap>,
ignore_path_set: Lrc<IgnorePathSet>,
can_reset: Lrc<AtomicBool>,
hide_parse_errors: bool,
show_parse_errors: bool,
color: Color,
) -> DiagCtxt {
let supports_color = term::stderr().map_or(false, |term| term.supports_color());
@ -116,7 +116,7 @@ fn default_dcx(
.sm(Some(source_map.clone())),
);
let emitter: Box<DynEmitter> = if hide_parse_errors {
let emitter: Box<DynEmitter> = if !show_parse_errors {
Box::new(SilentEmitter {
fallback_bundle,
fatal_dcx: DiagCtxt::new(emitter),
@ -148,7 +148,7 @@ impl ParseSess {
Lrc::clone(&source_map),
Lrc::clone(&ignore_path_set),
Lrc::clone(&can_reset_errors),
config.hide_parse_errors(),
config.show_parse_errors(),
config.color(),
);
let raw_psess = RawParseSess::with_dcx(dcx, source_map);
@ -164,7 +164,7 @@ impl ParseSess {
///
/// * `id` - The name of the module
/// * `relative` - If Some(symbol), the symbol name is a directory relative to the dir_path.
/// If relative is Some, resolve the submodle at {dir_path}/{symbol}/{id}.rs
/// If relative is Some, resolve the submodule at {dir_path}/{symbol}/{id}.rs
/// or {dir_path}/{symbol}/{id}/mod.rs. if None, resolve the module at {dir_path}/{id}.rs.
/// * `dir_path` - Module resolution will occur relative to this directory.
pub(crate) fn default_submod_path(
@ -175,7 +175,7 @@ impl ParseSess {
) -> Result<ModulePathSuccess, ModError<'_>> {
rustc_expand::module::default_submod_path(&self.raw_psess, id, relative, dir_path).or_else(
|e| {
// If resloving a module relative to {dir_path}/{symbol} fails because a file
// If resolving a module relative to {dir_path}/{symbol} fails because a file
// could not be found, then try to resolve the module relative to {dir_path}.
// If we still can't find the module after searching for it in {dir_path},
// surface the original error.

View File

@ -33,7 +33,7 @@ where
let mut emitter = create_emitter(config);
emitter.emit_header(out)?;
for &(ref filename, ref text) in source_file {
for (filename, text) in source_file {
write_file(
None,
filename,

View File

@ -24,19 +24,13 @@ impl ConfigurationSection {
fn get_section<I: Iterator<Item = String>>(
file: &mut Enumerate<I>,
) -> Option<ConfigurationSection> {
lazy_static! {
static ref CONFIG_NAME_REGEX: regex::Regex =
regex::Regex::new(r"^## `([^`]+)`").expect("failed creating configuration pattern");
// Configuration values, which will be passed to `from_str`:
//
// - must be prefixed with `####`
// - must be wrapped in backticks
// - may by wrapped in double quotes (which will be stripped)
static ref CONFIG_VALUE_REGEX: regex::Regex =
regex::Regex::new(r#"^#### `"?([^`]+?)"?`"#)
.expect("failed creating configuration value pattern");
}
let config_name_regex = static_regex!(r"^## `([^`]+)`");
// Configuration values, which will be passed to `from_str`:
//
// - must be prefixed with `####`
// - must be wrapped in backticks
// - may by wrapped in double quotes (which will be stripped)
let config_value_regex = static_regex!(r#"^#### `"?([^`]+?)"?`"#);
loop {
match file.next() {
Some((i, line)) => {
@ -53,9 +47,9 @@ impl ConfigurationSection {
let start_line = (i + 2) as u32;
return Some(ConfigurationSection::CodeBlock((block, start_line)));
} else if let Some(c) = CONFIG_NAME_REGEX.captures(&line) {
} else if let Some(c) = config_name_regex.captures(&line) {
return Some(ConfigurationSection::ConfigName(String::from(&c[1])));
} else if let Some(c) = CONFIG_VALUE_REGEX.captures(&line) {
} else if let Some(c) = config_value_regex.captures(&line) {
return Some(ConfigurationSection::ConfigValue(String::from(&c[1])));
}
}
@ -208,7 +202,7 @@ impl ConfigCodeBlock {
}
// Extract a code block from the iterator. Behavior:
// - Rust code blocks are identifed by lines beginning with "```rust".
// - Rust code blocks are identified by lines beginning with "```rust".
// - One explicit configuration setting is supported per code block.
// - Rust code blocks with no configuration setting are illegal and cause an
// assertion failure, unless the snippet begins with #![rustfmt::skip].

View File

@ -332,7 +332,7 @@ fn assert_stdin_output(
let mut session = Session::new(config, Some(&mut buf));
session.format(input).unwrap();
let errors = ReportedErrors {
has_diff: has_diff,
has_diff,
..Default::default()
};
assert_eq!(session.errors, errors);
@ -390,6 +390,26 @@ fn self_tests() {
path.push("main.rs");
files.push(path);
}
// for crates that need to be included but lies outside src
let external_crates = vec!["check_diff", "config_proc_macro"];
for external_crate in external_crates {
let mut path = PathBuf::from(external_crate);
path.push("src");
let directory = fs::read_dir(&path).unwrap();
let search_files = directory.filter_map(|file| {
file.ok().and_then(|f| {
let name = f.file_name();
if matches!(name.as_os_str().to_str(), Some("main.rs" | "lib.rs")) {
Some(f.path())
} else {
None
}
})
});
for file in search_files {
files.push(file);
}
}
files.push(PathBuf::from("src/lib.rs"));
let (reports, count, fails) = check_files(files, &Some(PathBuf::from("rustfmt.toml")));
@ -835,7 +855,7 @@ fn handle_result(
// Ignore LF and CRLF difference for Windows.
if !string_eq_ignore_newline_repr(&fmt_text, &text) {
if std::env::var_os("RUSTC_BLESS").is_some_and(|v| v != "0") {
std::fs::write(file_name, fmt_text).unwrap();
std::fs::write(target, fmt_text).unwrap();
continue;
}
let diff = make_diff(&text, &fmt_text, DIFF_CONTEXT_SIZE);

View File

@ -43,11 +43,13 @@ pub(crate) fn rewrite_path(
) -> Option<String> {
let skip_count = qself.as_ref().map_or(0, |x| x.position);
let mut result = if path.is_global() && qself.is_none() && path_context != PathContext::Import {
"::".to_owned()
} else {
String::new()
};
// 32 covers almost all path lengths measured when compiling core, and there isn't a big
// downside from allocating slightly more than necessary.
let mut result = String::with_capacity(32);
if path.is_global() && qself.is_none() && path_context != PathContext::Import {
result.push_str("::");
}
let mut span_lo = path.span.lo();
@ -693,10 +695,12 @@ impl Rewrite for ast::Ty {
};
let mut res = bounds.rewrite(context, shape)?;
// We may have falsely removed a trailing `+` inside macro call.
if context.inside_macro() && bounds.len() == 1 {
if context.snippet(self.span).ends_with('+') && !res.ends_with('+') {
res.push('+');
}
if context.inside_macro()
&& bounds.len() == 1
&& context.snippet(self.span).ends_with('+')
&& !res.ends_with('+')
{
res.push('+');
}
Some(format!("{prefix}{res}"))
}

View File

@ -81,7 +81,7 @@ pub(crate) struct FmtVisitor<'a> {
pub(crate) snippet_provider: &'a SnippetProvider,
pub(crate) line_number: usize,
/// List of 1-based line ranges which were annotated with skip
/// Both bounds are inclusifs.
/// Both bounds are inclusive.
pub(crate) skipped_range: Rc<RefCell<Vec<(usize, usize)>>>,
pub(crate) macro_rewrite_failure: bool,
pub(crate) report: FormatReport,

View File

@ -0,0 +1,3 @@
max_width = 120
version = "One"
attr_fn_like_width = 120

View File

@ -0,0 +1,3 @@
max_width = 120
version = "Two"
attr_fn_like_width = 120

View File

@ -6,4 +6,4 @@ mod one;
fn main() {println!("Hello, world!");
}
// trailing commet
// trailing comment

View File

@ -176,7 +176,14 @@ fn rustfmt_emits_error_on_line_overflow_true() {
#[test]
#[allow(non_snake_case)]
fn dont_emit_ICE() {
let files = ["tests/target/issue_5728.rs", "tests/target/issue_5729.rs", "tests/target/issue_6082.rs"];
let files = [
"tests/target/issue_5728.rs",
"tests/target/issue_5729.rs",
"tests/target/issue-5885.rs",
"tests/target/issue_6082.rs",
"tests/target/issue_6069.rs",
"tests/target/issue-6105.rs",
];
for file in files {
let args = [file];
@ -184,3 +191,19 @@ fn dont_emit_ICE() {
assert!(!stderr.contains("thread 'main' panicked"));
}
}
#[test]
fn rustfmt_emits_error_when_control_brace_style_is_always_next_line() {
// See also https://github.com/rust-lang/rustfmt/issues/5912
let args = [
"--config=color=Never",
"--config",
"control_brace_style=AlwaysNextLine",
"--config",
"match_arm_blocks=false",
"tests/target/issue_5912.rs",
];
let (_stdout, stderr) = rustfmt(&args);
assert!(!stderr.contains("error[internal]: left behind trailing whitespace"))
}

View File

@ -0,0 +1,10 @@
// rustfmt-version: Two
fn main() {
match a {
_ =>
// comment with =>
{
println!("A")
}
}
}

View File

@ -0,0 +1,14 @@
// rustfmt-version: Two
fn main() {
match a {
_ => // comment with =>
match b {
// one goes to =>
one => {
println("1");
}
// two goes to =>
two => { println("2"); }
}
}
}

View File

@ -0,0 +1,10 @@
// rustfmt-format_generated_files: false
// rustfmt-generated_marker_line_search_limit: 15
fn main()
{
println!("hello, world")
;
}
// @generated

View File

@ -0,0 +1,10 @@
// rustfmt-format_generated_files: false
// rustfmt-generated_marker_line_search_limit: 1
fn main()
{
println!("hello, world")
;
}
// @generated

View File

@ -0,0 +1,9 @@
// rustfmt-format_generated_files: false
// rustfmt-generated_marker_line_search_limit: 0
// @generated
fn main() {
println!("hello, world")
;
}
// @generated

View File

@ -0,0 +1,10 @@
// rustfmt-format_generated_files: true
// rustfmt-generated_marker_line_search_limit: 20
fn main()
{
println!("hello, world")
;
}
// @generated

View File

@ -0,0 +1,9 @@
// rustfmt-format_generated_files: true
fn main()
{
println!("hello, world")
;
}
// @generated

View File

@ -0,0 +1,65 @@
// rustfmt-version: Two
// rustfmt-format_macro_matchers: true
// From original issue example - Line length 101
macro_rules! test {
($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr) => {{
return;
}};
}
// Spaces between the `{` and `}`
macro_rules! test {
($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr) => { {
return;
} };
}
// Multi `{}`
macro_rules! test {
($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr) => {{{{
return;
}}}};
}
// Multi `{}` with spaces
macro_rules! test {
($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr) => { { { {
return;
} } } };
}
// Line length 102
macro_rules! test {
($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeiou:expr, $add:expr) => {{
return;
}};
}
// Line length 103
macro_rules! test {
($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeioua:expr, $add:expr) => {{
return;
}};
}
// With extended macro body - Line length 101
macro_rules! test {
($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr) => {{
let VAR = "VALUE"; return VAR;
}};
}
// With extended macro body - Line length 102
macro_rules! test {
($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeiou:expr, $add:expr) => {{
let VAR = "VALUE"; return VAR;
}};
}
// With extended macro body - Line length 103
macro_rules! test {
($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeioua:expr, $add:expr) => {{
let VAR = "VALUE"; return VAR;
}};
}

View File

@ -0,0 +1,8 @@
// rustfmt-config: issue-5801-v1.toml
pub enum Severity {
#[something(AAAAAAAAAAAAA, BBBBBBBBBBBBBB, CCCCCCCCCCCCCCCC, DDDDDDDDDDDDD, EEEEEEEEEEEE, FFFFFFFFFFF, GGGGGGGGGGG)]
AttrsWillWrap,
#[something_else(hhhhhhhhhhhhhhhh, iiiiiiiiiiiiiiii, jjjjjjjjjjjjjjj, kkkkkkkkkkkkk, llllllllllll, mmmmmmmmmmmmmm)]
AttrsWontWrap,
}

View File

@ -0,0 +1,17 @@
// rustfmt-comment_width: 120
// rustfmt-wrap_comments: true
// rustfmt-max_width: 120
// rustfmt-version: One
/// This function is 120 columns wide and is left alone. This comment is 120 columns wide and the formatter is also fine
fn my_super_cool_function_name(my_very_cool_argument_name: String, my_other_very_cool_argument_name: String) -> String {
unimplemented!()
}
pub enum Severity {
/// In version one, the below line got wrapped prematurely as we subtracted 1 to account for `,`. See issue #5801.
/// But here, this comment is 120 columns wide and the formatter wants to split it up onto two separate lines still.
Error,
/// This comment is 119 columns wide and works perfectly. Lorem ipsum. lorem ipsum. lorem ipsum. lorem ipsum lorem.
Warning,
}

View File

@ -0,0 +1,13 @@
// rustfmt-version: Two
fn main() {
trace!(
"get some longer length in here yes yes {} {}",
"hello",
"world"
);
debug!(
"get some longer length in here yes yes {} {}",
"hello", "world"
);
}

View File

@ -0,0 +1,3 @@
fn float_range_tests() {
self.coords.x -= rng.gen_range(-self.radius / 2. .. self.radius / 2.);
}

View File

@ -0,0 +1,20 @@
// rustfmt-version: One
pub fn main() {
let a = Some(12);
match a {
#![attr1]
#![attr2]
#![attr3]
_ => None,
}
{
match a {
#![attr1]
#![attr2]
#![attr3]
_ => None,
}
}
}

View File

@ -0,0 +1,20 @@
// rustfmt-version: Two
pub fn main() {
let a = Some(12);
match a {
#![attr1]
#![attr2]
#![attr3]
_ => None,
}
{
match a {
#![attr1]
#![attr2]
#![attr3]
_ => None,
}
}
}

View File

@ -0,0 +1,15 @@
// rustfmt-match_arm_blocks: false
// rustfmt-control_brace_style: AlwaysNextLine
fn foo() {
match 0 {
0 => {
aaaaaaaaaaaaaaaaaaaaaaaa
+ bbbbbbbbbbbbbbbbbbbbbbbbb
+ bbbbbbbbbbbbbbbbbbbbbbbbb
+ bbbbbbbbbbbbbbbbbbbbbbbbb
+ bbbbbbbbbbbbbbbbbbbbbbbbb
}
_ => 2,
}
}

View File

@ -117,8 +117,8 @@ fn unbreakable_initializer_expr_pre_formatting_length_through_initializer_expr_n
// Break after the `=` and put the initializer expr on it's own line.
// Because the initializer expr is multi-lined the else is placed on it's own line.
// The initializer expr has a length of 91, which when indented on the next line
// The `(indent)init` line has a lengh of 99. This is the max length that the `init` can be
// before we start running into max_width issues. I suspect this is becuase the shape is
// The `(indent)init` line has a length of 99. This is the max length that the `init` can be
// before we start running into max_width issues. I suspect this is because the shape is
// accounting for the `;` at the end of the `let-else` statement.
let Some(x) = some_really_really_really_really_really_really_really_really_really_really_long_name______I else {return};
@ -127,7 +127,7 @@ fn unbreakable_initializer_expr_pre_formatting_length_through_initializer_expr_n
// Post Formatting:
// Max length issues prevent us from formatting.
// The initializer expr has a length of 92, which if it would be indented on the next line
// the `(indent)init` line has a lengh of 100 which == max_width of 100.
// the `(indent)init` line has a length of 100 which == max_width of 100.
// One might expect formatting to succeed, but I suspect the reason we hit max_width issues is
// because the Shape is accounting for the `;` at the end of the `let-else` statement.
let Some(x) = some_really_really_really_really_really_really_really_really_really_really_really_long_nameJ else {return};

View File

@ -1,2 +1,2 @@
fn foo( /* cooment */
fn foo( /* comment */
) {}

View File

@ -0,0 +1,10 @@
// rustfmt-version: Two
fn main() {
match a {
_ =>
// comment with =>
{
println!("A")
}
}
}

View File

@ -0,0 +1,19 @@
// rustfmt-version: Two
fn main() {
match a {
_ =>
// comment with =>
{
match b {
// one goes to =>
one => {
println("1");
}
// two goes to =>
two => {
println("2");
}
}
}
}
}

View File

@ -0,0 +1,10 @@
// rustfmt-format_generated_files: false
// rustfmt-generated_marker_line_search_limit: 15
fn main()
{
println!("hello, world")
;
}
// @generated

View File

@ -0,0 +1,8 @@
// rustfmt-format_generated_files: false
// rustfmt-generated_marker_line_search_limit: 1
fn main() {
println!("hello, world");
}
// @generated

View File

@ -0,0 +1,8 @@
// rustfmt-format_generated_files: false
// rustfmt-generated_marker_line_search_limit: 0
// @generated
fn main() {
println!("hello, world");
}
// @generated

View File

@ -0,0 +1,8 @@
// rustfmt-format_generated_files: true
// rustfmt-generated_marker_line_search_limit: 20
fn main() {
println!("hello, world");
}
// @generated

View File

@ -0,0 +1,7 @@
// rustfmt-format_generated_files: true
fn main() {
println!("hello, world");
}
// @generated

View File

@ -32,6 +32,11 @@ where
{
}
// #5941
impl T where (): Clone // Should not add comma to comment
{
}
// #1823
default impl Trait for X {}
default unsafe impl Trait for Y {}

View File

@ -0,0 +1,94 @@
// rustfmt-version: Two
// rustfmt-format_macro_matchers: true
// From original issue example - Line length 101
macro_rules! test {
(
$aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr
) => {{
return;
}};
}
// Spaces between the `{` and `}`
macro_rules! test {
(
$aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr
) => {{
return;
}};
}
// Multi `{}`
macro_rules! test {
(
$aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr
) => {{
{
{
return;
}
}
}};
}
// Multi `{}` with spaces
macro_rules! test {
(
$aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr
) => {{
{
{
return;
}
}
}};
}
// Line length 102
macro_rules! test {
(
$aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeiou:expr, $add:expr
) => {{
return;
}};
}
// Line length 103
macro_rules! test {
(
$aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeioua:expr, $add:expr
) => {{
return;
}};
}
// With extended macro body - Line length 101
macro_rules! test {
(
$aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr
) => {{
let VAR = "VALUE";
return VAR;
}};
}
// With extended macro body - Line length 102
macro_rules! test {
(
$aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeiou:expr, $add:expr
) => {{
let VAR = "VALUE";
return VAR;
}};
}
// With extended macro body - Line length 103
macro_rules! test {
(
$aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeioua:expr, $add:expr
) => {{
let VAR = "VALUE";
return VAR;
}};
}

View File

@ -0,0 +1,8 @@
// rustfmt-config: issue-5801-v2.toml
pub enum Severity {
#[something(AAAAAAAAAAAAA, BBBBBBBBBBBBBB, CCCCCCCCCCCCCCCC, DDDDDDDDDDDDD, EEEEEEEEEEEE, FFFFFFFFFFF, GGGGGGGGGGG)]
AttrsWillWrap,
#[something_else(hhhhhhhhhhhhhhhh, iiiiiiiiiiiiiiii, jjjjjjjjjjjjjjj, kkkkkkkkkkkkk, llllllllllll, mmmmmmmmmmmmmm)]
AttrsWontWrap,
}

View File

@ -0,0 +1,16 @@
// rustfmt-config: issue-5801-v1.toml
pub enum Severity {
#[something(
AAAAAAAAAAAAA,
BBBBBBBBBBBBBB,
CCCCCCCCCCCCCCCC,
DDDDDDDDDDDDD,
EEEEEEEEEEEE,
FFFFFFFFFFF,
GGGGGGGGGGG
)]
AttrsWillWrap,
#[something_else(hhhhhhhhhhhhhhhh, iiiiiiiiiiiiiiii, jjjjjjjjjjjjjjj, kkkkkkkkkkkkk, llllllllllll, mmmmmmmmmmmmmm)]
AttrsWontWrap,
}

View File

@ -0,0 +1,16 @@
// rustfmt-comment_width: 120
// rustfmt-wrap_comments: true
// rustfmt-max_width: 120
// rustfmt-version: Two
/// This function is 120 columns wide and is left alone. This comment is 120 columns wide and the formatter is also fine
fn my_super_cool_function_name(my_very_cool_argument_name: String, my_other_very_cool_argument_name: String) -> String {
unimplemented!()
}
pub enum Severity {
/// But here, this comment is 120 columns wide and the formatter wants to split it up onto two separate lines still.
Error,
/// This comment is 119 columns wide and works perfectly. Lorem ipsum. lorem ipsum. lorem ipsum. lorem ipsum lorem.
Warning,
}

View File

@ -0,0 +1,18 @@
// rustfmt-comment_width: 120
// rustfmt-wrap_comments: true
// rustfmt-max_width: 120
// rustfmt-version: One
/// This function is 120 columns wide and is left alone. This comment is 120 columns wide and the formatter is also fine
fn my_super_cool_function_name(my_very_cool_argument_name: String, my_other_very_cool_argument_name: String) -> String {
unimplemented!()
}
pub enum Severity {
/// In version one, the below line got wrapped prematurely as we subtracted 1 to account for `,`. See issue #5801.
/// But here, this comment is 120 columns wide and the formatter wants to split it up onto two separate lines
/// still.
Error,
/// This comment is 119 columns wide and works perfectly. Lorem ipsum. lorem ipsum. lorem ipsum. lorem ipsum lorem.
Warning,
}

View File

@ -0,0 +1,3 @@
fn main() {
println!("{}", builtin # offset_of(A, 0. 1.1.1));
}

View File

@ -0,0 +1,13 @@
// rustfmt-version: One
fn main() {
trace!(
"get some longer length in here yes yes {} {}",
"hello",
"world"
);
debug!(
"get some longer length in here yes yes {} {}",
"hello", "world"
);
}

View File

@ -0,0 +1,12 @@
// rustfmt-version: Two
fn main() {
trace!(
"get some longer length in here yes yes {} {}",
"hello", "world"
);
debug!(
"get some longer length in here yes yes {} {}",
"hello", "world"
);
}

View File

@ -0,0 +1,6 @@
fn float_range_tests() {
let _range = 3. / 2. ..4.;
let _range = 3.0 / 2. ..4.0;
let _range = 3.0 / 2.0..4.0;
let _range = 3. / 2.0..4.0;
}

View File

@ -0,0 +1,3 @@
fn float_range_tests() {
self.coords.x -= rng.gen_range(-self.radius / 2. ..self.radius / 2.);
}

View File

@ -0,0 +1 @@
const _: () = builtin # offset_of(x, x);

View File

@ -0,0 +1,20 @@
// rustfmt-version: One
pub fn main() {
let a = Some(12);
match a {
#![attr1]
#![attr2]
#![attr3]
_ => None,
}
{
match a {
#![attr1]
#![attr2]
#![attr3]
_ => None,
}
}
}

View File

@ -0,0 +1,20 @@
// rustfmt-version: Two
pub fn main() {
let a = Some(12);
match a {
#![attr1]
#![attr2]
#![attr3]
_ => None,
}
{
match a {
#![attr1]
#![attr2]
#![attr3]
_ => None,
}
}
}

View File

@ -0,0 +1,15 @@
// rustfmt-match_arm_blocks: false
// rustfmt-control_brace_style: AlwaysNextLine
fn foo() {
match 0
{
0 =>
aaaaaaaaaaaaaaaaaaaaaaaa
+ bbbbbbbbbbbbbbbbbbbbbbbbb
+ bbbbbbbbbbbbbbbbbbbbbbbbb
+ bbbbbbbbbbbbbbbbbbbbbbbbb
+ bbbbbbbbbbbbbbbbbbbbbbbbb,
_ => 2,
}
}

View File

@ -0,0 +1,3 @@
// `Foó` as written here ends with ASCII 6F `'o'` followed by `'\u{0301}'` COMBINING ACUTE ACCENT.
// The compiler normalizes that combination to NFC form, `'\u{00F3}'` LATIN SMALL LETTER O WITH ACUTE.
trait Foó: Bar {}

View File

@ -0,0 +1,7 @@
fn main() {
const {
#![allow(clippy::assertions_on_constants)]
assert!(1 < 2);
}
}

View File

@ -0,0 +1,3 @@
fn main() {
builtin # type_ascribe(10, usize)
}

View File

@ -180,8 +180,8 @@ fn unbreakable_initializer_expr_pre_formatting_length_through_initializer_expr_n
// Break after the `=` and put the initializer expr on it's own line.
// Because the initializer expr is multi-lined the else is placed on it's own line.
// The initializer expr has a length of 91, which when indented on the next line
// The `(indent)init` line has a lengh of 99. This is the max length that the `init` can be
// before we start running into max_width issues. I suspect this is becuase the shape is
// The `(indent)init` line has a length of 99. This is the max length that the `init` can be
// before we start running into max_width issues. I suspect this is because the shape is
// accounting for the `;` at the end of the `let-else` statement.
let Some(x) =
some_really_really_really_really_really_really_really_really_really_really_long_name______I
@ -194,7 +194,7 @@ fn unbreakable_initializer_expr_pre_formatting_length_through_initializer_expr_n
// Post Formatting:
// Max length issues prevent us from formatting.
// The initializer expr has a length of 92, which if it would be indented on the next line
// the `(indent)init` line has a lengh of 100 which == max_width of 100.
// the `(indent)init` line has a length of 100 which == max_width of 100.
// One might expect formatting to succeed, but I suspect the reason we hit max_width issues is
// because the Shape is accounting for the `;` at the end of the `let-else` statement.
let Some(x) = some_really_really_really_really_really_really_really_really_really_really_really_long_nameJ else {return};

View File

@ -1 +1 @@
fn foo(/* cooment */) {}
fn foo(/* comment */) {}

View File

@ -0,0 +1,34 @@
#![feature(unsafe_attributes)]
// https://github.com/rust-lang/rust/issues/123757
//
#![simple_ident]
#![simple::path]
#![simple_ident_expr = ""]
#![simple::path::Expr = ""]
#![simple_ident_tt(a b c)]
#![simple_ident_tt[a b c]]
#![simple_ident_tt{a b c}]
#![simple::path::tt(a b c)]
#![simple::path::tt[a b c]]
#![simple::path::tt{a b c}]
#![unsafe(simple_ident)]
#![unsafe(simple::path)]
#![unsafe(simple_ident_expr = "")]
#![unsafe(simple::path::Expr = "")]
#![unsafe(simple_ident_tt(a b c))]
#![unsafe(simple_ident_tt[a b c])]
#![unsafe(simple_ident_tt{a b c})]
#![unsafe(simple::path::tt(a b c))]
#![unsafe(simple::path::tt[a b c])]
#![unsafe(simple::path::tt{a b c})]
// I don't think `safe` attributes are a thing, but adding these formatting cases here just in case
#![safe(simple_ident)]
#![safe(simple::path)]
#![safe(simple_ident_expr = "")]
#![safe(simple::path::Expr = "")]
#![safe(simple_ident_tt(a b c))]
#![safe(simple_ident_tt[a b c])]
#![safe(simple_ident_tt{a b c})]
#![safe(simple::path::tt(a b c))]
#![safe(simple::path::tt[a b c])]
#![safe(simple::path::tt{a b c})]

View File

@ -0,0 +1,18 @@
// See tracking issue for unsafe_extern_blocks
// https://github.com/rust-lang/rust/issues/123743
#![feature(unsafe_extern_blocks)]
safe static TEST1: i32;
unsafe extern "C" {
safe static TEST2: i32;
unsafe static TEST3: i32;
static TEST4: i32;
pub safe static TEST5: i32;
pub unsafe static TEST6: i32;
pub static TEST7: i32;
safe fn test1(i: i32);
}