From 80d196d789fdd9adb43b474d9a3a74af4633937f Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 11 Jan 2023 22:25:29 +0100 Subject: [PATCH 01/58] Update rustfmt for ast::ExprKind::FormatArgs. Rustfmt doesn't expand macros, so that's easy: FormatArgs nodes do not occur in the unexpanded AST. --- src/expr.rs | 5 ++++- src/utils.rs | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/expr.rs b/src/expr.rs index 414e767690bd0..cdbdcedd58fea 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -399,7 +399,10 @@ pub(crate) fn format_expr( } } ast::ExprKind::Underscore => Some("_".to_owned()), - ast::ExprKind::IncludedBytes(..) => unreachable!(), + ast::ExprKind::FormatArgs(..) | ast::ExprKind::IncludedBytes(..) => { + // These do not occur in the AST because macros aren't expanded. + unreachable!() + } ast::ExprKind::Err => None, }; diff --git a/src/utils.rs b/src/utils.rs index 3e884419f1a32..80dce525e3957 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -462,6 +462,7 @@ pub(crate) fn first_line_ends_with(s: &str, c: char) -> bool { pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr: &str) -> bool { match expr.kind { ast::ExprKind::MacCall(..) + | ast::ExprKind::FormatArgs(..) | ast::ExprKind::Call(..) | ast::ExprKind::MethodCall(..) | ast::ExprKind::Array(..) From 2791cc37e6f882f8ab7fa6c234885be652f930c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 15 Jan 2023 22:36:46 +0000 Subject: [PATCH 02/58] Teach parser to understand fake anonymous enum syntax Parse `-> Ty | OtherTy`. Parse type ascription in top level patterns. --- src/types.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/types.rs b/src/types.rs index c1991e8d2c808..f065ec680d724 100644 --- a/src/types.rs +++ b/src/types.rs @@ -839,7 +839,9 @@ impl Rewrite for ast::Ty { }) } ast::TyKind::CVarArgs => Some("...".to_owned()), - ast::TyKind::Err => Some(context.snippet(self.span).to_owned()), + ast::TyKind::AnonEnum(_) | ast::TyKind::Err => { + Some(context.snippet(self.span).to_owned()) + } ast::TyKind::Typeof(ref anon_const) => rewrite_call( context, "typeof", From 4e3ed18e1d3724f223bbdec5593263653b7158e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 23 Jan 2023 14:29:53 +0000 Subject: [PATCH 03/58] review comment: Remove AST AnonTy --- src/types.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/types.rs b/src/types.rs index f065ec680d724..c1991e8d2c808 100644 --- a/src/types.rs +++ b/src/types.rs @@ -839,9 +839,7 @@ impl Rewrite for ast::Ty { }) } ast::TyKind::CVarArgs => Some("...".to_owned()), - ast::TyKind::AnonEnum(_) | ast::TyKind::Err => { - Some(context.snippet(self.span).to_owned()) - } + ast::TyKind::Err => Some(context.snippet(self.span).to_owned()), ast::TyKind::Typeof(ref anon_const) => rewrite_call( context, "typeof", From 094b7f599cb1e3420021e496c72d9e1dd36043a0 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Tue, 24 Jan 2023 14:16:03 -0600 Subject: [PATCH 04/58] Merge commit '1d8491b120223272b13451fc81265aa64f7f4d5b' into sync-from-rustfmt --- .github/workflows/check_diff.yml | 33 +++ .github/workflows/integration.yml | 4 - CHANGELOG.md | 28 ++- Cargo.lock | 4 +- Cargo.toml | 4 +- Configurations.md | 185 +++++++++++++++- Processes.md | 2 +- ci/build_and_test.bat | 1 + ci/build_and_test.sh | 1 + ci/check_diff.sh | 199 ++++++++++++++++++ ci/integration.sh | 18 +- config_proc_macro/Cargo.lock | 2 +- config_proc_macro/Cargo.toml | 2 +- config_proc_macro/src/attrs.rs | 27 ++- config_proc_macro/src/item_enum.rs | 40 +++- config_proc_macro/src/lib.rs | 13 ++ config_proc_macro/tests/smoke.rs | 1 + rust-toolchain | 4 +- src/attr.rs | 4 +- src/bin/main.rs | 2 +- src/cargo-fmt/main.rs | 12 +- src/cargo-fmt/test/mod.rs | 4 +- src/chains.rs | 120 ++++++++--- src/config/config_type.rs | 122 +++++++++-- src/config/macro_names.rs | 118 +++++++++++ src/config/mod.rs | 149 ++++++++++++- src/expr.rs | 9 +- src/imports.rs | 4 +- src/items.rs | 10 +- src/lists.rs | 16 +- src/macros.rs | 18 +- src/skip.rs | 79 +++++-- src/test/configuration_snippet.rs | 7 +- src/test/mod.rs | 6 +- src/types.rs | 44 +++- src/utils.rs | 5 +- src/visitor.rs | 13 +- tests/cargo-fmt/main.rs | 29 ++- tests/cargo-fmt/source/issue_3164/Cargo.toml | 8 + tests/cargo-fmt/source/issue_3164/src/main.rs | 13 ++ tests/config/small_tabs.toml | 2 +- .../issue-5198/lib/c/d/explanation.txt | 2 +- .../issue-5198/lib/explanation.txt | 2 +- tests/rustfmt/main.rs | 21 +- tests/source/cfg_if/detect/arch/x86.rs | 2 +- tests/source/comments_unicode.rs | 140 ++++++++++++ .../compressed.rs | 2 +- .../tall.rs | 2 +- .../vertical.rs | 2 +- tests/source/enum.rs | 2 +- tests/source/fn-custom-7.rs | 2 +- tests/source/fn-custom.rs | 2 +- tests/source/fn_args_layout-vertical.rs | 2 +- .../issue-3987/format_macro_bodies_true.rs | 26 +++ tests/source/issue-4643.rs | 23 ++ tests/source/issue-4689/one.rs | 149 +++++++++++++ tests/source/issue-4689/two.rs | 149 +++++++++++++ tests/source/issue_1306.rs | 29 +++ tests/source/issue_3245.rs | 4 + tests/source/issue_3561.rs | 6 + tests/source/skip_macro_invocations/all.rs | 11 + .../skip_macro_invocations/all_and_name.rs | 11 + tests/source/skip_macro_invocations/empty.rs | 11 + tests/source/skip_macro_invocations/name.rs | 11 + .../skip_macro_invocations/name_unknown.rs | 6 + tests/source/skip_macro_invocations/names.rs | 16 ++ .../path_qualified_invocation_mismatch.rs | 6 + .../path_qualified_match.rs | 6 + .../path_qualified_name_mismatch.rs | 6 + .../use_alias_examples.rs | 32 +++ tests/source/tuple.rs | 2 +- ...ts_should_not_imply_format_doc_comments.rs | 2 +- tests/target/cfg_if/detect/arch/x86.rs | 2 +- tests/target/comments_unicode.rs | 140 ++++++++++++ .../compressed.rs | 2 +- .../tall.rs | 2 +- .../vertical.rs | 2 +- tests/target/enum.rs | 2 +- tests/target/fn-custom-7.rs | 2 +- tests/target/fn-custom.rs | 2 +- tests/target/fn_args_layout-vertical.rs | 2 +- .../issue-2534/format_macro_matchers_false.rs | 6 + .../issue-2534/format_macro_matchers_true.rs | 6 + .../issue-3987/format_macro_bodies_false.rs | 26 +++ .../issue-3987/format_macro_bodies_true.rs | 21 ++ tests/target/issue-4643.rs | 19 ++ tests/target/issue-4689/one.rs | 150 +++++++++++++ tests/target/issue-4689/two.rs | 152 +++++++++++++ tests/target/issue-4791/issue_4928.rs | 2 +- tests/target/issue-5358.rs | 4 + tests/target/issue_1306.rs | 33 +++ tests/target/issue_3033.rs | 2 + tests/target/issue_3245.rs | 4 + tests/target/issue_3561.rs | 7 + tests/target/issue_4350.rs | 13 ++ tests/target/issue_5668.rs | 8 + tests/target/skip_macro_invocations/all.rs | 11 + .../skip_macro_invocations/all_and_name.rs | 11 + tests/target/skip_macro_invocations/empty.rs | 11 + tests/target/skip_macro_invocations/name.rs | 11 + .../skip_macro_invocations/name_unknown.rs | 6 + tests/target/skip_macro_invocations/names.rs | 16 ++ .../path_qualified_invocation_mismatch.rs | 6 + .../path_qualified_match.rs | 6 + .../path_qualified_name_mismatch.rs | 6 + .../use_alias_examples.rs | 32 +++ tests/target/tuple.rs | 2 +- ...ts_should_not_imply_format_doc_comments.rs | 2 +- 108 files changed, 2591 insertions(+), 187 deletions(-) create mode 100644 .github/workflows/check_diff.yml create mode 100755 ci/check_diff.sh create mode 100644 src/config/macro_names.rs create mode 100644 tests/cargo-fmt/source/issue_3164/Cargo.toml create mode 100644 tests/cargo-fmt/source/issue_3164/src/main.rs create mode 100644 tests/source/comments_unicode.rs rename tests/source/configs/{fn_args_layout => fn_params_layout}/compressed.rs (92%) rename tests/source/configs/{fn_args_layout => fn_params_layout}/tall.rs (93%) rename tests/source/configs/{fn_args_layout => fn_params_layout}/vertical.rs (92%) create mode 100644 tests/source/issue-3987/format_macro_bodies_true.rs create mode 100644 tests/source/issue-4643.rs create mode 100644 tests/source/issue-4689/one.rs create mode 100644 tests/source/issue-4689/two.rs create mode 100644 tests/source/issue_1306.rs create mode 100644 tests/source/issue_3245.rs create mode 100644 tests/source/issue_3561.rs create mode 100644 tests/source/skip_macro_invocations/all.rs create mode 100644 tests/source/skip_macro_invocations/all_and_name.rs create mode 100644 tests/source/skip_macro_invocations/empty.rs create mode 100644 tests/source/skip_macro_invocations/name.rs create mode 100644 tests/source/skip_macro_invocations/name_unknown.rs create mode 100644 tests/source/skip_macro_invocations/names.rs create mode 100644 tests/source/skip_macro_invocations/path_qualified_invocation_mismatch.rs create mode 100644 tests/source/skip_macro_invocations/path_qualified_match.rs create mode 100644 tests/source/skip_macro_invocations/path_qualified_name_mismatch.rs create mode 100644 tests/source/skip_macro_invocations/use_alias_examples.rs create mode 100644 tests/target/comments_unicode.rs rename tests/target/configs/{fn_args_layout => fn_params_layout}/compressed.rs (92%) rename tests/target/configs/{fn_args_layout => fn_params_layout}/tall.rs (94%) rename tests/target/configs/{fn_args_layout => fn_params_layout}/vertical.rs (94%) create mode 100644 tests/target/issue-2534/format_macro_matchers_false.rs create mode 100644 tests/target/issue-2534/format_macro_matchers_true.rs create mode 100644 tests/target/issue-3987/format_macro_bodies_false.rs create mode 100644 tests/target/issue-3987/format_macro_bodies_true.rs create mode 100644 tests/target/issue-4643.rs create mode 100644 tests/target/issue-4689/one.rs create mode 100644 tests/target/issue-4689/two.rs create mode 100644 tests/target/issue-5358.rs create mode 100644 tests/target/issue_1306.rs create mode 100644 tests/target/issue_3033.rs create mode 100644 tests/target/issue_3245.rs create mode 100644 tests/target/issue_3561.rs create mode 100644 tests/target/issue_4350.rs create mode 100644 tests/target/issue_5668.rs create mode 100644 tests/target/skip_macro_invocations/all.rs create mode 100644 tests/target/skip_macro_invocations/all_and_name.rs create mode 100644 tests/target/skip_macro_invocations/empty.rs create mode 100644 tests/target/skip_macro_invocations/name.rs create mode 100644 tests/target/skip_macro_invocations/name_unknown.rs create mode 100644 tests/target/skip_macro_invocations/names.rs create mode 100644 tests/target/skip_macro_invocations/path_qualified_invocation_mismatch.rs create mode 100644 tests/target/skip_macro_invocations/path_qualified_match.rs create mode 100644 tests/target/skip_macro_invocations/path_qualified_name_mismatch.rs create mode 100644 tests/target/skip_macro_invocations/use_alias_examples.rs diff --git a/.github/workflows/check_diff.yml b/.github/workflows/check_diff.yml new file mode 100644 index 0000000000000..8bfb5834519cd --- /dev/null +++ b/.github/workflows/check_diff.yml @@ -0,0 +1,33 @@ +name: Diff Check +on: + workflow_dispatch: + inputs: + clone_url: + description: 'Git url of a rustfmt fork to compare against the latest master rustfmt' + required: true + branch_name: + description: 'Name of the feature branch on the forked repo' + required: true + commit_hash: + description: 'Optional commit hash from the feature branch' + required: false + rustfmt_configs: + description: 'Optional comma separated list of rustfmt config options to pass when running the feature branch' + required: false + +jobs: + diff_check: + runs-on: ubuntu-latest + + steps: + - name: checkout + uses: actions/checkout@v3 + + - name: install rustup + run: | + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh + sh rustup-init.sh -y --default-toolchain none + rustup target add x86_64-unknown-linux-gnu + + - name: check diff + run: bash ${GITHUB_WORKSPACE}/ci/check_diff.sh ${{ github.event.inputs.clone_url }} ${{ github.event.inputs.branch_name }} ${{ github.event.inputs.commit_hash }} ${{ github.event.inputs.rustfmt_configs }} diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 4d8899b434bbe..314ce0e84c61b 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -27,7 +27,6 @@ jobs: tempdir, futures-rs, rust-clippy, - failure, ] include: # Allowed Failures @@ -63,9 +62,6 @@ jobs: # Original comment was: temporal build failure due to breaking changes in the nightly compiler - integration: rust-semverver allow-failure: true - # Can be moved back to include section after https://github.com/rust-lang-nursery/failure/pull/298 is merged - - integration: failure - allow-failure: true steps: - name: checkout diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c1893bf8c387..60f961fa12ac8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,32 @@ ## [Unreleased] +## [1.5.2] 2023-01-24 + +### Fixed + +- Resolve issue when comments are found within const generic defaults in unit structs [#5668](https://github.com/rust-lang/rustfmt/issues/5668) +- Resolve issue when block comments are found within trait generics [#5358](https://github.com/rust-lang/rustfmt/issues/5358) +- Correctly handle alignment of comments containing unicode characters [#5504](https://github.com/rust-lang/rustfmt/issues/5504) +- Properly indent a single generic bound that requires being written across multiple lines [#4689](https://github.com/rust-lang/rustfmt/issues/4689) (n.b. this change is version gated and will only appear when the `version` configuration option is set to `Two`) + +### Changed + +- Renamed `fn_args_layout` configuration option to `fn_params_layout` [#4149](https://github.com/rust-lang/rustfmt/issues/4149). Note that `fn_args_layout` has only been soft deprecated: `fn_args_layout` will continue to work without issue, but rustfmt will display a warning to encourage users to switch to the new name + +### Added + +- New configuration option (`skip_macro_invocations`)[https://rust-lang.github.io/rustfmt/?version=master&search=#skip_macro_invocations] [#5347](https://github.com/rust-lang/rustfmt/pull/5347) that can be used to globally define a single enumerated list of macro calls that rustfmt should skip formatting. rustfmt [currently also supports this via a custom tool attribute](https://github.com/rust-lang/rustfmt#tips), however, these cannot be used in all contexts because [custom inner attributes are unstable](https://github.com/rust-lang/rust/issues/54726) + +### Misc + +- rustfmt now internally supports the ability to have both stable and unstable variants of a configuration option [#5378](https://github.com/rust-lang/rustfmt/issues/5378). This ability will allow the rustfmt team to make certain configuration options available on stable toolchains more quickly because we no longer have to wait for _every_ variant to be stable-ready before stabilizing _any_ variant. + +### Install/Download Options +- **rustup (nightly)** - nightly-2023-01-24 +- **GitHub Release Binaries** - [Release v1.5.2](https://github.com/rust-lang/rustfmt/releases/tag/v1.5.2) +- **Build from source** - [Tag v1.5.2](https://github.com/rust-lang/rustfmt/tree/v1.5.2), see instructions for how to [install rustfmt from source][install-from-source] + ## [1.5.1] 2022-06-24 **N.B** A bug was introduced in v1.5.0/nightly-2022-06-15 which modified formatting. If you happened to run rustfmt over your code with one of those ~10 nightlies it's possible you may have seen formatting changes, and you may see additional changes after this fix since that bug has now been reverted. @@ -840,7 +866,7 @@ from formatting an attribute #3665 - Fix formatting of raw string literals #2983 - Handle chain with try operators with spaces #2986 - Use correct shape in Visual tuple rewriting #2987 -- Impove formatting of arguments with `visual_style = "Visual"` option #2988 +- Improve formatting of arguments with `visual_style = "Visual"` option #2988 - Change `print_diff` to output the correct line number 992b179 - Propagate errors about failing to rewrite a macro 6f318e3 - Handle formatting of long function signature #3010 diff --git a/Cargo.lock b/Cargo.lock index 311df226da19d..24166d51c51fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -476,7 +476,7 @@ checksum = "fc71d2faa173b74b232dedc235e3ee1696581bb132fc116fa3626d6151a1a8fb" [[package]] name = "rustfmt-config_proc_macro" -version = "0.2.0" +version = "0.3.0" dependencies = [ "proc-macro2", "quote", @@ -485,7 +485,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.5.1" +version = "1.5.2" dependencies = [ "annotate-snippets", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index 7a4e02d69eddc..87ce59d0217e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "1.5.1" +version = "1.5.2" description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang/rustfmt" readme = "README.md" @@ -57,7 +57,7 @@ unicode-segmentation = "1.9" unicode-width = "0.1" unicode_categories = "0.1" -rustfmt-config_proc_macro = { version = "0.2", path = "config_proc_macro" } +rustfmt-config_proc_macro = { version = "0.3", path = "config_proc_macro" } # A noop dependency that changes in the Rust repository, it's a bit of a hack. # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` diff --git a/Configurations.md b/Configurations.md index 8b96b9d36892a..49e7e4e64892a 100644 --- a/Configurations.md +++ b/Configurations.md @@ -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/1.0.4/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/4.0.0/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: @@ -425,7 +425,7 @@ fn example() { ## `comment_width` -Maximum length of comments. No effect unless`wrap_comments = true`. +Maximum length of comments. No effect unless `wrap_comments = true`. - **Default value**: `80` - **Possible values**: any positive integer @@ -589,7 +589,7 @@ doesn't get ignored when aligning. #### `0` (default): ```rust -enum Bar { +enum Foo { A = 0, Bb = 1, RandomLongVariantGoesHere = 10, @@ -645,7 +645,8 @@ trailing whitespaces. ## `fn_args_layout` -Control the layout of arguments in a function +This option is deprecated and has been renamed to `fn_params_layout` to better communicate that +it affects the layout of parameters in function signatures. - **Default value**: `"Tall"` - **Possible values**: `"Compressed"`, `"Tall"`, `"Vertical"` @@ -753,6 +754,8 @@ trait Lorem { } ``` +See also [`fn_params_layout`](#fn_params_layout) + ## `fn_call_width` Maximum width of the args of a function call before falling back to vertical formatting. @@ -765,6 +768,117 @@ By default this option is set as a percentage of [`max_width`](#max_width) provi See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics) +## `fn_params_layout` + +Control the layout of parameters in function signatures. + +- **Default value**: `"Tall"` +- **Possible values**: `"Compressed"`, `"Tall"`, `"Vertical"` +- **Stable**: Yes + +#### `"Tall"` (default): + +```rust +trait Lorem { + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { + // body + } + + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: Consectetur, + adipiscing: Adipiscing, + elit: Elit, + ); + + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: Consectetur, + adipiscing: Adipiscing, + elit: Elit, + ) { + // body + } +} +``` + +#### `"Compressed"`: + +```rust +trait Lorem { + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { + // body + } + + fn lorem( + ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: Consectetur, + adipiscing: Adipiscing, elit: Elit, + ); + + fn lorem( + ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: Consectetur, + adipiscing: Adipiscing, elit: Elit, + ) { + // body + } +} +``` + +#### `"Vertical"`: + +```rust +trait Lorem { + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + ); + + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + ) { + // body + } + + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: Consectetur, + adipiscing: Adipiscing, + elit: Elit, + ); + + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: Consectetur, + adipiscing: Adipiscing, + elit: Elit, + ) { + // body + } +} +``` + + ## `fn_single_line` Put single-expression functions on a single line @@ -1014,6 +1128,62 @@ macro_rules! foo { See also [`format_macro_matchers`](#format_macro_matchers). +## `skip_macro_invocations` + +Skip formatting the bodies of macro invocations with the following names. + +rustfmt will not format any macro invocation for macros with names set in this list. +Including the special value "*" will prevent any macro invocations from being formatted. + +Note: This option does not have any impact on how rustfmt formats macro definitions. + +- **Default value**: `[]` +- **Possible values**: a list of macro name idents, `["name_0", "name_1", ..., "*"]` +- **Stable**: No (tracking issue: [#5346](https://github.com/rust-lang/rustfmt/issues/5346)) + +#### `[]` (default): + +rustfmt will follow its standard approach to formatting macro invocations. + +No macro invocations will be skipped based on their name. More information about rustfmt's standard macro invocation formatting behavior can be found in [#5437](https://github.com/rust-lang/rustfmt/discussions/5437). + +```rust +lorem!( + const _: u8 = 0; +); + +ipsum!( + const _: u8 = 0; +); +``` + +#### `["lorem"]`: + +The named macro invocations will be skipped. + +```rust +lorem!( + const _: u8 = 0; +); + +ipsum!( + const _: u8 = 0; +); +``` + +#### `["*"]`: + +The special selector `*` will skip all macro invocations. + +```rust +lorem!( + const _: u8 = 0; +); + +ipsum!( + const _: u8 = 0; +); +``` ## `format_strings` @@ -1687,13 +1857,16 @@ pub enum Foo {} ## `imports_granularity` -How imports should be grouped into `use` statements. Imports will be merged or split to the configured level of granularity. +Controls how imports are structured in `use` statements. Imports will be merged or split to the configured level of granularity. + +Similar to other `import` related configuration options, this option operates within the bounds of user-defined groups of imports. See [`group_imports`](#group_imports) for more information on import groups. + +Note that rustfmt will not modify the granularity of imports containing comments if doing so could potentially lose or misplace said comments. - **Default value**: `Preserve` - **Possible values**: `Preserve`, `Crate`, `Module`, `Item`, `One` - **Stable**: No (tracking issue: [#4991](https://github.com/rust-lang/rustfmt/issues/4991)) -Note that rustfmt will not modify the granularity of imports containing comments if doing so could potentially lose or misplace said comments. #### `Preserve` (default): diff --git a/Processes.md b/Processes.md index f763b5714ce2c..61abc87eec9ff 100644 --- a/Processes.md +++ b/Processes.md @@ -2,7 +2,7 @@ This document outlines processes regarding management of rustfmt. # Stabilising an Option -In this Section, we describe how to stabilise an option of the rustfmt's configration. +In this Section, we describe how to stabilise an option of the rustfmt's configuration. ## Conditions diff --git a/ci/build_and_test.bat b/ci/build_and_test.bat index ef41017783feb..69dae1fff7b4d 100755 --- a/ci/build_and_test.bat +++ b/ci/build_and_test.bat @@ -1,4 +1,5 @@ set "RUSTFLAGS=-D warnings" +set "RUSTFMT_CI=1" :: Print version information rustc -Vv || exit /b 1 diff --git a/ci/build_and_test.sh b/ci/build_and_test.sh index 8fa0f67b0d021..94991853263ce 100755 --- a/ci/build_and_test.sh +++ b/ci/build_and_test.sh @@ -3,6 +3,7 @@ set -euo pipefail export RUSTFLAGS="-D warnings" +export RUSTFMT_CI=1 # Print version information rustc -Vv diff --git a/ci/check_diff.sh b/ci/check_diff.sh new file mode 100755 index 0000000000000..062c2dd8673ab --- /dev/null +++ b/ci/check_diff.sh @@ -0,0 +1,199 @@ +#!/bin/bash + +function print_usage() { + echo "usage check_diff REMOTE_REPO FEATURE_BRANCH [COMMIT_HASH] [OPTIONAL_RUSTFMT_CONFIGS]" +} + +if [ $# -le 1 ]; then + print_usage + exit 1 +fi + +REMOTE_REPO=$1 +FEATURE_BRANCH=$2 +OPTIONAL_COMMIT_HASH=$3 +OPTIONAL_RUSTFMT_CONFIGS=$4 + +# OUTPUT array used to collect all the status of running diffs on various repos +STATUSES=() + +# Clone a git repository and cd into it. +# +# Parameters: +# $1: git clone url +# $2: directory where the repo should be cloned +function clone_repo() { + GIT_TERMINAL_PROMPT=0 git clone --quiet $1 --depth 1 $2 && cd $2 +} + +# Initialize Git submoduels for the repo. +# +# Parameters +# $1: list of directories to initialize +function init_submodules() { + git submodule update --init $1 +} + +# Run rusfmt with the --check flag to see if a diff is produced. +# +# Parameters: +# $1: Path to a rustfmt binary +# $2: Output file path for the diff +# $3: Any additional configuration options to pass to rustfmt +# +# Globlas: +# $OPTIONAL_RUSTFMT_CONFIGS: Optional configs passed to the script from $4 +function create_diff() { + local config; + if [ -z "$3" ]; then + config="--config=error_on_line_overflow=false,error_on_unformatted=false" + else + config="--config=error_on_line_overflow=false,error_on_unformatted=false,$OPTIONAL_RUSTFMT_CONFIGS" + fi + + for i in `find . | grep "\.rs$"` + do + $1 --unstable-features --skip-children --check --color=always $config $i >> $2 2>/dev/null + done +} + +# Run the master rustfmt binary and the feature branch binary in the current directory and compare the diffs +# +# Parameters +# $1: Name of the repository (used for logging) +# +# Globlas: +# $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 +function check_diff() { + echo "running rustfmt (master) on $1" + create_diff $RUSFMT_BIN rustfmt_diff.txt + + echo "running rustfmt (feature) on $1" + create_diff $FEATURE_BIN feature_diff.txt $OPTIONAL_RUSTFMT_CONFIGS + + echo "checking diff" + local diff; + # we don't add color to the diff since we added color when running rustfmt --check. + # tail -n + 6 removes the git diff header info + # cut -c 2- removes the leading diff characters("+","-"," ") from running git diff. + # Again, the diff output we care about was already added when we ran rustfmt --check + diff=$( + git --no-pager diff --color=never \ + --unified=0 --no-index rustfmt_diff.txt feature_diff.txt 2>&1 | tail -n +6 | cut -c 2- + ) + + if [ -z "$diff" ]; then + echo "no diff detected between rustfmt and the feture branch" + return 0 + else + echo "$diff" + return 1 + fi +} + +# Compiles and produces two rustfmt binaries. +# One for the current master, and another for the feature branch +# +# Parameters: +# $1: Directory where rustfmt will be cloned +# +# Globlas: +# $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 +function compile_rustfmt() { + RUSTFMT_REPO="https://github.com/rust-lang/rustfmt.git" + clone_repo $RUSTFMT_REPO $1 + git remote add feature $REMOTE_REPO + git fetch feature $FEATURE_BRANCH + + cargo build --release --bin rustfmt && cp target/release/rustfmt $1/rustfmt + if [ -z "$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 + RUSFMT_BIN=$1/rustfmt + FEATURE_BIN=$1/feature_rustfmt +} + +# Check the diff for running rustfmt and the feature branch on all the .rs files in the repo. +# +# Parameters +# $1: Clone URL for the repo +# $2: Name of the repo (mostly used for logging) +# $3: Path to any submodules that should be initialized +function check_repo() { + WORKDIR=$(pwd) + REPO_URL=$1 + REPO_NAME=$2 + SUBMODULES=$3 + + local tmp_dir; + tmp_dir=$(mktemp -d -t $REPO_NAME-XXXXXXXX) + clone_repo $REPO_URL $tmp_dir + + if [ ! -z "$SUBMODULES" ]; then + init_submodules $SUBMODULES + fi + + check_diff $REPO_NAME + # append the status of running `check_diff` to the STATUSES array + STATUSES+=($?) + + echo "removing tmp_dir $tmp_dir" + rm -rf $tmp_dir + cd $WORKDIR +} + +function main() { + tmp_dir=$(mktemp -d -t rustfmt-XXXXXXXX) + echo Created tmp_dir $tmp_dir + + compile_rustfmt $tmp_dir + + # run checks + check_repo "https://github.com/rust-lang/rust.git" rust-lang-rust + check_repo "https://github.com/rust-lang/cargo.git" cargo + check_repo "https://github.com/rust-lang/miri.git" miri + check_repo "https://github.com/rust-lang/rust-analyzer.git" rust-analyzer + check_repo "https://github.com/bitflags/bitflags.git" bitflags + check_repo "https://github.com/rust-lang/log.git" log + check_repo "https://github.com/rust-lang/mdBook.git" mdBook + check_repo "https://github.com/rust-lang/packed_simd.git" packed_simd + check_repo "https://github.com/rust-lang/rust-semverver.git" check_repo + check_repo "https://github.com/Stebalien/tempfile.git" tempfile + check_repo "https://github.com/rust-lang/futures-rs.git" futures-rs + check_repo "https://github.com/dtolnay/anyhow.git" anyhow + check_repo "https://github.com/dtolnay/thiserror.git" thiserror + check_repo "https://github.com/dtolnay/syn.git" syn + check_repo "https://github.com/serde-rs/serde.git" serde + check_repo "https://github.com/rust-lang/rustlings.git" rustlings + check_repo "https://github.com/rust-lang/rustup.git" rustup + check_repo "https://github.com/SergioBenitez/Rocket.git" Rocket + check_repo "https://github.com/rustls/rustls.git" rustls + check_repo "https://github.com/rust-lang/rust-bindgen.git" rust-bindgen + check_repo "https://github.com/hyperium/hyper.git" hyper + check_repo "https://github.com/actix/actix.git" actix + check_repo "https://github.com/denoland/deno.git" denoland_deno + + # cleanup temp dir + echo removing tmp_dir $tmp_dir + rm -rf $tmp_dir + + # figure out the exit code + for status in ${STATUSES[@]} + do + if [ $status -eq 1 ]; then + echo "formatting diff found 💔" + return 1 + fi + done + + echo "no diff found 😊" +} + +main diff --git a/ci/integration.sh b/ci/integration.sh index 562d5d70c70ba..19d502bc5c7bd 100755 --- a/ci/integration.sh +++ b/ci/integration.sh @@ -91,14 +91,28 @@ case ${INTEGRATION} in cd - ;; crater) - git clone --depth=1 https://github.com/rust-lang-nursery/${INTEGRATION}.git + git clone --depth=1 https://github.com/rust-lang/${INTEGRATION}.git cd ${INTEGRATION} show_head check_fmt_with_lib_tests cd - ;; + bitflags) + git clone --depth=1 https://github.com/bitflags/${INTEGRATION}.git + cd ${INTEGRATION} + show_head + check_fmt_with_all_tests + cd - + ;; + error-chain | tempdir) + git clone --depth=1 https://github.com/rust-lang-deprecated/${INTEGRATION}.git + cd ${INTEGRATION} + show_head + check_fmt_with_all_tests + cd - + ;; *) - git clone --depth=1 https://github.com/rust-lang-nursery/${INTEGRATION}.git + git clone --depth=1 https://github.com/rust-lang/${INTEGRATION}.git cd ${INTEGRATION} show_head check_fmt_with_all_tests diff --git a/config_proc_macro/Cargo.lock b/config_proc_macro/Cargo.lock index ecf561f28fb6a..49f2f72a8d219 100644 --- a/config_proc_macro/Cargo.lock +++ b/config_proc_macro/Cargo.lock @@ -22,7 +22,7 @@ dependencies = [ [[package]] name = "rustfmt-config_proc_macro" -version = "0.2.0" +version = "0.3.0" dependencies = [ "proc-macro2", "quote", diff --git a/config_proc_macro/Cargo.toml b/config_proc_macro/Cargo.toml index a41b3a5e6bf88..d10d0469cc401 100644 --- a/config_proc_macro/Cargo.toml +++ b/config_proc_macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustfmt-config_proc_macro" -version = "0.2.0" +version = "0.3.0" edition = "2018" description = "A collection of procedural macros for rustfmt" license = "Apache-2.0/MIT" diff --git a/config_proc_macro/src/attrs.rs b/config_proc_macro/src/attrs.rs index 0baba046f9e91..dd18ff572cb1c 100644 --- a/config_proc_macro/src/attrs.rs +++ b/config_proc_macro/src/attrs.rs @@ -1,8 +1,10 @@ //! This module provides utilities for handling attributes on variants -//! of `config_type` enum. Currently there are two types of attributes -//! that could appear on the variants of `config_type` enum: `doc_hint` -//! and `value`. Both comes in the form of name-value pair whose value -//! is string literal. +//! of `config_type` enum. Currently there are the following attributes +//! that could appear on the variants of `config_type` enum: +//! +//! - `doc_hint`: name-value pair whose value is string literal +//! - `value`: name-value pair whose value is string literal +//! - `unstable_variant`: name only /// Returns the value of the first `doc_hint` attribute in the given slice or /// `None` if `doc_hint` attribute is not available. @@ -27,6 +29,11 @@ pub fn find_config_value(attrs: &[syn::Attribute]) -> Option { attrs.iter().filter_map(config_value).next() } +/// Returns `true` if the there is at least one `unstable` attribute in the given slice. +pub fn any_unstable_variant(attrs: &[syn::Attribute]) -> bool { + attrs.iter().any(is_unstable_variant) +} + /// Returns a string literal value if the given attribute is `value` /// attribute or `None` otherwise. pub fn config_value(attr: &syn::Attribute) -> Option { @@ -38,6 +45,11 @@ pub fn is_config_value(attr: &syn::Attribute) -> bool { is_attr_name_value(attr, "value") } +/// Returns `true` if the given attribute is an `unstable` attribute. +pub fn is_unstable_variant(attr: &syn::Attribute) -> bool { + is_attr_path(attr, "unstable_variant") +} + fn is_attr_name_value(attr: &syn::Attribute, name: &str) -> bool { attr.parse_meta().ok().map_or(false, |meta| match meta { syn::Meta::NameValue(syn::MetaNameValue { ref path, .. }) if path.is_ident(name) => true, @@ -45,6 +57,13 @@ fn is_attr_name_value(attr: &syn::Attribute, name: &str) -> bool { }) } +fn is_attr_path(attr: &syn::Attribute, name: &str) -> bool { + attr.parse_meta().ok().map_or(false, |meta| match meta { + syn::Meta::Path(path) if path.is_ident(name) => true, + _ => false, + }) +} + fn get_name_value_str_lit(attr: &syn::Attribute, name: &str) -> Option { attr.parse_meta().ok().and_then(|meta| match meta { syn::Meta::NameValue(syn::MetaNameValue { diff --git a/config_proc_macro/src/item_enum.rs b/config_proc_macro/src/item_enum.rs index dcee77a8549c5..731a7ea06077b 100644 --- a/config_proc_macro/src/item_enum.rs +++ b/config_proc_macro/src/item_enum.rs @@ -1,5 +1,6 @@ use proc_macro2::TokenStream; -use quote::quote; +use quote::{quote, quote_spanned}; +use syn::spanned::Spanned; use crate::attrs::*; use crate::utils::*; @@ -47,12 +48,23 @@ fn process_variant(variant: &syn::Variant) -> TokenStream { let metas = variant .attrs .iter() - .filter(|attr| !is_doc_hint(attr) && !is_config_value(attr)); + .filter(|attr| !is_doc_hint(attr) && !is_config_value(attr) && !is_unstable_variant(attr)); let attrs = fold_quote(metas, |meta| quote!(#meta)); let syn::Variant { ident, fields, .. } = variant; quote!(#attrs #ident #fields) } +/// Return the correct syntax to pattern match on the enum variant, discarding all +/// internal field data. +fn fields_in_variant(variant: &syn::Variant) -> TokenStream { + // With thanks to https://stackoverflow.com/a/65182902 + match &variant.fields { + syn::Fields::Unnamed(_) => quote_spanned! { variant.span() => (..) }, + syn::Fields::Unit => quote_spanned! { variant.span() => }, + syn::Fields::Named(_) => quote_spanned! { variant.span() => {..} }, + } +} + fn impl_doc_hint(ident: &syn::Ident, variants: &Variants) -> TokenStream { let doc_hint = variants .iter() @@ -60,12 +72,26 @@ fn impl_doc_hint(ident: &syn::Ident, variants: &Variants) -> TokenStream { .collect::>() .join("|"); let doc_hint = format!("[{}]", doc_hint); + + let variant_stables = variants + .iter() + .map(|v| (&v.ident, fields_in_variant(&v), !unstable_of_variant(v))); + let match_patterns = fold_quote(variant_stables, |(v, fields, stable)| { + quote! { + #ident::#v #fields => #stable, + } + }); quote! { use crate::config::ConfigType; impl ConfigType for #ident { fn doc_hint() -> String { #doc_hint.to_owned() } + fn stable_variant(&self) -> bool { + match self { + #match_patterns + } + } } } } @@ -123,13 +149,21 @@ fn impl_from_str(ident: &syn::Ident, variants: &Variants) -> TokenStream { } fn doc_hint_of_variant(variant: &syn::Variant) -> String { - find_doc_hint(&variant.attrs).unwrap_or(variant.ident.to_string()) + let mut text = find_doc_hint(&variant.attrs).unwrap_or(variant.ident.to_string()); + if unstable_of_variant(&variant) { + text.push_str(" (unstable)") + }; + text } fn config_value_of_variant(variant: &syn::Variant) -> String { find_config_value(&variant.attrs).unwrap_or(variant.ident.to_string()) } +fn unstable_of_variant(variant: &syn::Variant) -> bool { + any_unstable_variant(&variant.attrs) +} + fn impl_serde(ident: &syn::Ident, variants: &Variants) -> TokenStream { let arms = fold_quote(variants.iter(), |v| { let v_ident = &v.ident; diff --git a/config_proc_macro/src/lib.rs b/config_proc_macro/src/lib.rs index e772c53f42361..0c54c132c97d8 100644 --- a/config_proc_macro/src/lib.rs +++ b/config_proc_macro/src/lib.rs @@ -69,3 +69,16 @@ pub fn stable_only_test(_args: TokenStream, input: TokenStream) -> TokenStream { TokenStream::from_str("").unwrap() } } + +/// Used to conditionally output the TokenStream for tests that should be run as part of rustfmts +/// test suite, but should be ignored when running in the rust-lang/rust test suite. +#[proc_macro_attribute] +pub fn rustfmt_only_ci_test(_args: TokenStream, input: TokenStream) -> TokenStream { + if option_env!("RUSTFMT_CI").is_some() { + input + } else { + let mut token_stream = TokenStream::from_str("#[ignore]").unwrap(); + token_stream.extend(input); + token_stream + } +} diff --git a/config_proc_macro/tests/smoke.rs b/config_proc_macro/tests/smoke.rs index 940a8a0c251e4..c8a83e39c9efc 100644 --- a/config_proc_macro/tests/smoke.rs +++ b/config_proc_macro/tests/smoke.rs @@ -1,6 +1,7 @@ pub mod config { pub trait ConfigType: Sized { fn doc_hint() -> String; + fn stable_variant(&self) -> bool; } } diff --git a/rust-toolchain b/rust-toolchain index 2640a9e0ecc28..22283b3d62002 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2022-06-21" -components = ["rustc-dev"] +channel = "nightly-2023-01-24" +components = ["llvm-tools", "rustc-dev"] diff --git a/src/attr.rs b/src/attr.rs index c503eeeb9b3b9..5648e1254ed7c 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -336,7 +336,7 @@ impl Rewrite for ast::Attribute { } else { let should_skip = self .ident() - .map(|s| context.skip_context.skip_attribute(s.name.as_str())) + .map(|s| context.skip_context.attributes.skip(s.name.as_str())) .unwrap_or(false); let prefix = attr_prefix(self); @@ -390,7 +390,7 @@ impl Rewrite for [ast::Attribute] { // Determine if the source text is annotated with `#[rustfmt::skip::attributes(derive)]` // or `#![rustfmt::skip::attributes(derive)]` - let skip_derives = context.skip_context.skip_attribute("derive"); + let skip_derives = context.skip_context.attributes.skip("derive"); // This is not just a simple map because we need to handle doc comments // (where we take as many doc comment attributes as possible) and possibly diff --git a/src/bin/main.rs b/src/bin/main.rs index 8e871e61f2683..be64559e87745 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -136,7 +136,7 @@ fn make_opts() -> Options { "l", "files-with-diff", "Prints the names of mismatched files that were formatted. Prints the names of \ - files that would be formated when used with `--check` mode. ", + files that would be formatted when used with `--check` mode. ", ); opts.optmulti( "", diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 9031d29b45f7f..2b714b68df00e 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -198,12 +198,10 @@ fn convert_message_format_to_rustfmt_args( Ok(()) } "human" => Ok(()), - _ => { - return Err(format!( - "invalid --message-format value: {}. Allowed values are: short|json|human", - message_format - )); - } + _ => Err(format!( + "invalid --message-format value: {}. Allowed values are: short|json|human", + message_format + )), } } @@ -215,7 +213,7 @@ fn print_usage_to_stderr(reason: &str) { .expect("failed to write to stderr"); } -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Verbosity { Verbose, Normal, diff --git a/src/cargo-fmt/test/mod.rs b/src/cargo-fmt/test/mod.rs index 56e52fbabb68b..696326e4f9406 100644 --- a/src/cargo-fmt/test/mod.rs +++ b/src/cargo-fmt/test/mod.rs @@ -70,9 +70,9 @@ fn mandatory_separator() { .is_err() ); assert!( - !Opts::command() + Opts::command() .try_get_matches_from(&["test", "--", "--emit"]) - .is_err() + .is_ok() ); } diff --git a/src/chains.rs b/src/chains.rs index a1a73cf4bd570..39b8d6878097d 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -70,10 +70,64 @@ use crate::rewrite::{Rewrite, RewriteContext}; use crate::shape::Shape; use crate::source_map::SpanUtils; use crate::utils::{ - self, first_line_width, last_line_extendable, last_line_width, mk_sp, rewrite_ident, - trimmed_last_line_width, wrap_str, + self, filtered_str_fits, first_line_width, last_line_extendable, last_line_width, mk_sp, + rewrite_ident, trimmed_last_line_width, wrap_str, }; +/// Provides the original input contents from the span +/// of a chain element with trailing spaces trimmed. +fn format_overflow_style(span: Span, context: &RewriteContext<'_>) -> Option { + context.snippet_provider.span_to_snippet(span).map(|s| { + s.lines() + .map(|l| l.trim_end()) + .collect::>() + .join("\n") + }) +} + +fn format_chain_item( + item: &ChainItem, + context: &RewriteContext<'_>, + rewrite_shape: Shape, + allow_overflow: bool, +) -> Option { + if allow_overflow { + item.rewrite(context, rewrite_shape) + .or_else(|| format_overflow_style(item.span, context)) + } else { + item.rewrite(context, rewrite_shape) + } +} + +fn get_block_child_shape( + prev_ends_with_block: bool, + context: &RewriteContext<'_>, + shape: Shape, +) -> Shape { + if prev_ends_with_block { + shape.block_indent(0) + } else { + shape.block_indent(context.config.tab_spaces()) + } + .with_max_width(context.config) +} + +fn get_visual_style_child_shape( + context: &RewriteContext<'_>, + shape: Shape, + offset: usize, + parent_overflowing: bool, +) -> Option { + if !parent_overflowing { + shape + .with_max_width(context.config) + .offset_left(offset) + .map(|s| s.visual_indent(0)) + } else { + Some(shape.visual_indent(offset)) + } +} + pub(crate) fn rewrite_chain( expr: &ast::Expr, context: &RewriteContext<'_>, @@ -496,6 +550,8 @@ struct ChainFormatterShared<'a> { // The number of children in the chain. This is not equal to `self.children.len()` // because `self.children` will change size as we process the chain. child_count: usize, + // Whether elements are allowed to overflow past the max_width limit + allow_overflow: bool, } impl<'a> ChainFormatterShared<'a> { @@ -505,6 +561,8 @@ impl<'a> ChainFormatterShared<'a> { rewrites: Vec::with_capacity(chain.children.len() + 1), fits_single_line: false, child_count: chain.children.len(), + // TODO(calebcartwright) + allow_overflow: false, } } @@ -517,6 +575,14 @@ impl<'a> ChainFormatterShared<'a> { } } + fn format_children(&mut self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<()> { + for item in &self.children[..self.children.len() - 1] { + let rewrite = format_chain_item(item, context, child_shape, self.allow_overflow)?; + self.rewrites.push(rewrite); + } + Some(()) + } + // Rewrite the last child. The last child of a chain requires special treatment. We need to // know whether 'overflowing' the last child make a better formatting: // @@ -729,22 +795,12 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { } fn child_shape(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - Some( - if self.root_ends_with_block { - shape.block_indent(0) - } else { - shape.block_indent(context.config.tab_spaces()) - } - .with_max_width(context.config), - ) + let block_end = self.root_ends_with_block; + Some(get_block_child_shape(block_end, context, shape)) } fn format_children(&mut self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<()> { - for item in &self.shared.children[..self.shared.children.len() - 1] { - let rewrite = item.rewrite(context, child_shape)?; - self.shared.rewrites.push(rewrite); - } - Some(()) + self.shared.format_children(context, child_shape) } fn format_last_child( @@ -808,15 +864,14 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { .visual_indent(self.offset) .sub_width(self.offset)?; let rewrite = item.rewrite(context, child_shape)?; - match wrap_str(rewrite, context.config.max_width(), shape) { - Some(rewrite) => root_rewrite.push_str(&rewrite), - None => { - // We couldn't fit in at the visual indent, try the last - // indent. - let rewrite = item.rewrite(context, parent_shape)?; - root_rewrite.push_str(&rewrite); - self.offset = 0; - } + if filtered_str_fits(&rewrite, context.config.max_width(), shape) { + root_rewrite.push_str(&rewrite); + } else { + // We couldn't fit in at the visual indent, try the last + // indent. + let rewrite = item.rewrite(context, parent_shape)?; + root_rewrite.push_str(&rewrite); + self.offset = 0; } self.shared.children = &self.shared.children[1..]; @@ -827,18 +882,17 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { } fn child_shape(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - shape - .with_max_width(context.config) - .offset_left(self.offset) - .map(|s| s.visual_indent(0)) + get_visual_style_child_shape( + context, + shape, + self.offset, + // TODO(calebcartwright): self.shared.permissibly_overflowing_parent, + false, + ) } fn format_children(&mut self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<()> { - for item in &self.shared.children[..self.shared.children.len() - 1] { - let rewrite = item.rewrite(context, child_shape)?; - self.shared.rewrites.push(rewrite); - } - Some(()) + self.shared.format_children(context, child_shape) } fn format_last_child( diff --git a/src/config/config_type.rs b/src/config/config_type.rs index c5e61658ad1ed..54ca7676dfc8b 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -1,4 +1,5 @@ use crate::config::file_lines::FileLines; +use crate::config::macro_names::MacroSelectors; use crate::config::options::{IgnoreList, WidthHeuristics}; /// Trait for types that can be used in `Config`. @@ -6,6 +7,14 @@ pub(crate) trait ConfigType: Sized { /// Returns hint text for use in `Config::print_docs()`. For enum types, this is a /// pipe-separated list of variants; for other types it returns ``. fn doc_hint() -> String; + + /// Return `true` if the variant (i.e. value of this type) is stable. + /// + /// By default, return true for all values. Enums annotated with `#[config_type]` + /// are automatically implemented, based on the `#[unstable_variant]` annotation. + fn stable_variant(&self) -> bool { + true + } } impl ConfigType for bool { @@ -38,6 +47,12 @@ impl ConfigType for FileLines { } } +impl ConfigType for MacroSelectors { + fn doc_hint() -> String { + String::from("[, ...]") + } +} + impl ConfigType for WidthHeuristics { fn doc_hint() -> String { String::new() @@ -51,6 +66,13 @@ impl ConfigType for IgnoreList { } macro_rules! create_config { + // Options passed in to the macro. + // + // - $i: the ident name of the option + // - $ty: the type of the option value + // - $def: the default value of the option + // - $stb: true if the option is stable + // - $dstring: description of the option ($($i:ident: $ty:ty, $def:expr, $stb:expr, $( $dstring:expr ),+ );+ $(;)*) => ( #[cfg(test)] use std::collections::HashSet; @@ -61,9 +83,12 @@ macro_rules! create_config { #[derive(Clone)] #[allow(unreachable_pub)] pub struct Config { - // For each config item, we store a bool indicating whether it has - // been accessed and the value, and a bool whether the option was - // manually initialised, or taken from the default, + // For each config item, we store: + // + // - 0: true if the value has been access + // - 1: true if the option was manually initialized + // - 2: the option value + // - 3: true if the option is unstable $($i: (Cell, bool, $ty, bool)),+ } @@ -102,6 +127,7 @@ macro_rules! create_config { | "array_width" | "chain_width" => self.0.set_heuristics(), "merge_imports" => self.0.set_merge_imports(), + "fn_args_layout" => self.0.set_fn_args_layout(), &_ => (), } } @@ -143,24 +169,20 @@ macro_rules! create_config { fn fill_from_parsed_config(mut self, parsed: PartialConfig, dir: &Path) -> Config { $( - if let Some(val) = parsed.$i { - if self.$i.3 { + if let Some(option_value) = parsed.$i { + let option_stable = self.$i.3; + if $crate::config::config_type::is_stable_option_and_value( + stringify!($i), option_stable, &option_value + ) { self.$i.1 = true; - self.$i.2 = val; - } else { - if crate::is_nightly_channel!() { - self.$i.1 = true; - self.$i.2 = val; - } else { - eprintln!("Warning: can't set `{} = {:?}`, unstable features are only \ - available in nightly channel.", stringify!($i), val); - } + self.$i.2 = option_value; } } )+ self.set_heuristics(); self.set_ignore(dir); self.set_merge_imports(); + self.set_fn_args_layout(); self } @@ -221,12 +243,22 @@ macro_rules! create_config { match key { $( stringify!($i) => { - self.$i.1 = true; - self.$i.2 = val.parse::<$ty>() + let option_value = val.parse::<$ty>() .expect(&format!("Failed to parse override for {} (\"{}\") as a {}", stringify!($i), val, stringify!($ty))); + + // Users are currently allowed to set unstable + // options/variants via the `--config` options override. + // + // There is ongoing discussion about how to move forward here: + // https://github.com/rust-lang/rustfmt/pull/5379 + // + // For now, do not validate whether the option or value is stable, + // just always set it. + self.$i.1 = true; + self.$i.2 = option_value; } )+ _ => panic!("Unknown config key in override: {}", key) @@ -243,14 +275,21 @@ macro_rules! create_config { | "array_width" | "chain_width" => self.set_heuristics(), "merge_imports" => self.set_merge_imports(), + "fn_args_layout" => self.set_fn_args_layout(), &_ => (), } } #[allow(unreachable_pub)] pub fn is_hidden_option(name: &str) -> bool { - const HIDE_OPTIONS: [&str; 5] = - ["verbose", "verbose_diff", "file_lines", "width_heuristics", "merge_imports"]; + const HIDE_OPTIONS: [&str; 6] = [ + "verbose", + "verbose_diff", + "file_lines", + "width_heuristics", + "merge_imports", + "fn_args_layout" + ]; HIDE_OPTIONS.contains(&name) } @@ -400,6 +439,18 @@ macro_rules! create_config { } } + fn set_fn_args_layout(&mut self) { + if self.was_set().fn_args_layout() { + eprintln!( + "Warning: the `fn_args_layout` option is deprecated. \ + Use `fn_params_layout`. instead" + ); + if !self.was_set().fn_params_layout() { + self.fn_params_layout.2 = self.fn_args_layout(); + } + } + } + #[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 { @@ -424,3 +475,38 @@ macro_rules! create_config { } ) } + +pub(crate) fn is_stable_option_and_value( + option_name: &str, + option_stable: bool, + option_value: &T, +) -> bool +where + T: PartialEq + std::fmt::Debug + ConfigType, +{ + let nightly = crate::is_nightly_channel!(); + let variant_stable = option_value.stable_variant(); + match (nightly, option_stable, variant_stable) { + // Stable with an unstable option + (false, false, _) => { + eprintln!( + "Warning: can't set `{} = {:?}`, unstable features are only \ + available in nightly channel.", + option_name, option_value + ); + false + } + // Stable with a stable option, but an unstable variant + (false, true, false) => { + eprintln!( + "Warning: can't set `{} = {:?}`, unstable variants are only \ + available in nightly channel.", + option_name, option_value + ); + false + } + // Nightly: everything allowed + // Stable with stable option and variant: allowed + (true, _, _) | (false, true, true) => true, + } +} diff --git a/src/config/macro_names.rs b/src/config/macro_names.rs new file mode 100644 index 0000000000000..26ad78d6dcae8 --- /dev/null +++ b/src/config/macro_names.rs @@ -0,0 +1,118 @@ +//! This module contains types and functions to support formatting specific macros. + +use itertools::Itertools; +use std::{fmt, str}; + +use serde::{Deserialize, Serialize}; +use serde_json as json; +use thiserror::Error; + +/// Defines the name of a macro. +#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)] +pub struct MacroName(String); + +impl MacroName { + pub fn new(other: String) -> Self { + Self(other) + } +} + +impl fmt::Display for MacroName { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +impl From for String { + fn from(other: MacroName) -> Self { + other.0 + } +} + +/// Defines a selector to match against a macro. +#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)] +pub enum MacroSelector { + Name(MacroName), + All, +} + +impl fmt::Display for MacroSelector { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Name(name) => name.fmt(f), + Self::All => write!(f, "*"), + } + } +} + +impl str::FromStr for MacroSelector { + type Err = std::convert::Infallible; + + fn from_str(s: &str) -> Result { + Ok(match s { + "*" => MacroSelector::All, + name => MacroSelector::Name(MacroName(name.to_owned())), + }) + } +} + +/// A set of macro selectors. +#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)] +pub struct MacroSelectors(pub Vec); + +impl fmt::Display for MacroSelectors { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0.iter().format(", ")) + } +} + +#[derive(Error, Debug)] +pub enum MacroSelectorsError { + #[error("{0}")] + Json(json::Error), +} + +// This impl is needed for `Config::override_value` to work for use in tests. +impl str::FromStr for MacroSelectors { + type Err = MacroSelectorsError; + + fn from_str(s: &str) -> Result { + let raw: Vec<&str> = json::from_str(s).map_err(MacroSelectorsError::Json)?; + Ok(Self( + raw.into_iter() + .map(|raw| { + MacroSelector::from_str(raw).expect("MacroSelector from_str is infallible") + }) + .collect(), + )) + } +} + +#[cfg(test)] +mod test { + use super::*; + use std::str::FromStr; + + #[test] + fn macro_names_from_str() { + let macro_names = MacroSelectors::from_str(r#"["foo", "*", "bar"]"#).unwrap(); + assert_eq!( + macro_names, + MacroSelectors( + [ + MacroSelector::Name(MacroName("foo".to_owned())), + MacroSelector::All, + MacroSelector::Name(MacroName("bar".to_owned())) + ] + .into_iter() + .collect() + ) + ); + } + + #[test] + fn macro_names_display() { + let macro_names = MacroSelectors::from_str(r#"["foo", "*", "bar"]"#).unwrap(); + assert_eq!(format!("{}", macro_names), "foo, *, bar"); + } +} diff --git a/src/config/mod.rs b/src/config/mod.rs index f49c18d3a4603..14f27f3f8b692 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -13,15 +13,20 @@ pub use crate::config::file_lines::{FileLines, FileName, Range}; #[allow(unreachable_pub)] pub use crate::config::lists::*; #[allow(unreachable_pub)] +pub use crate::config::macro_names::{MacroSelector, MacroSelectors}; +#[allow(unreachable_pub)] pub use crate::config::options::*; #[macro_use] pub(crate) mod config_type; #[macro_use] +#[allow(unreachable_pub)] pub(crate) mod options; pub(crate) mod file_lines; +#[allow(unreachable_pub)] pub(crate) mod lists; +pub(crate) mod macro_names; // This macro defines configuration options used in rustfmt. Each option // is defined as follows: @@ -67,6 +72,8 @@ create_config! { format_macro_matchers: bool, false, false, "Format the metavariable matching patterns in macros"; format_macro_bodies: bool, true, false, "Format the bodies of macros"; + 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, "Format hexadecimal integer literals"; @@ -119,7 +126,9 @@ create_config! { force_multiline_blocks: bool, false, false, "Force multiline closure bodies and match arms to be wrapped in a block"; fn_args_layout: Density, Density::Tall, true, - "Control the layout of arguments in a function"; + "(deprecated: use fn_params_layout instead)"; + fn_params_layout: Density, Density::Tall, true, + "Control the layout of parameters in function signatures."; brace_style: BraceStyle, BraceStyle::SameLineWhere, false, "Brace style for items"; control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, false, "Brace style for control flow constructs"; @@ -175,7 +184,7 @@ create_config! { make_backup: bool, false, false, "Backup changed files"; print_misformatted_file_names: bool, false, true, "Prints the names of mismatched files that were formatted. Prints the names of \ - files that would be formated when used with `--check` mode. "; + files that would be formatted when used with `--check` mode. "; } #[derive(Error, Debug)] @@ -191,6 +200,7 @@ impl PartialConfig { cloned.width_heuristics = None; cloned.print_misformatted_file_names = None; cloned.merge_imports = None; + cloned.fn_args_layout = None; ::toml::to_string(&cloned).map_err(ToTomlError) } @@ -403,11 +413,21 @@ mod test { use super::*; use std::str; + use crate::config::macro_names::MacroName; use rustfmt_config_proc_macro::{nightly_only_test, stable_only_test}; #[allow(dead_code)] mod mock { use super::super::*; + use rustfmt_config_proc_macro::config_type; + + #[config_type] + pub(crate) enum PartiallyUnstableOption { + V1, + V2, + #[unstable_variant] + V3, + } create_config! { // Options that are used by the generated functions @@ -427,6 +447,12 @@ mod test { "Merge imports"; merge_imports: bool, false, false, "(deprecated: use imports_granularity instead)"; + // fn_args_layout renamed to fn_params_layout + fn_args_layout: Density, Density::Tall, true, + "(deprecated: use fn_params_layout instead)"; + fn_params_layout: Density, Density::Tall, true, + "Control the layout of parameters in a function signatures."; + // Width Heuristics use_small_heuristics: Heuristics, Heuristics::Default, true, "Whether to use different formatting for items and \ @@ -451,6 +477,63 @@ mod test { // Options that are used by the tests stable_option: bool, false, true, "A stable option"; unstable_option: bool, false, false, "An unstable option"; + partially_unstable_option: PartiallyUnstableOption, PartiallyUnstableOption::V1, true, + "A partially unstable option"; + } + + #[cfg(test)] + mod partially_unstable_option { + use super::{Config, PartialConfig, PartiallyUnstableOption}; + use rustfmt_config_proc_macro::{nightly_only_test, stable_only_test}; + use std::path::Path; + + /// From the config file, we can fill with a stable variant + #[test] + fn test_from_toml_stable_value() { + let toml = r#" + partially_unstable_option = "V2" + "#; + let partial_config: PartialConfig = toml::from_str(toml).unwrap(); + let config = Config::default(); + let config = config.fill_from_parsed_config(partial_config, Path::new("")); + assert_eq!( + config.partially_unstable_option(), + PartiallyUnstableOption::V2 + ); + } + + /// From the config file, we cannot fill with an unstable variant (stable only) + #[stable_only_test] + #[test] + fn test_from_toml_unstable_value_on_stable() { + let toml = r#" + partially_unstable_option = "V3" + "#; + let partial_config: PartialConfig = toml::from_str(toml).unwrap(); + let config = Config::default(); + let config = config.fill_from_parsed_config(partial_config, Path::new("")); + assert_eq!( + config.partially_unstable_option(), + // default value from config, i.e. fill failed + PartiallyUnstableOption::V1 + ); + } + + /// From the config file, we can fill with an unstable variant (nightly only) + #[nightly_only_test] + #[test] + fn test_from_toml_unstable_value_on_nightly() { + let toml = r#" + partially_unstable_option = "V3" + "#; + let partial_config: PartialConfig = toml::from_str(toml).unwrap(); + let config = Config::default(); + let config = config.fill_from_parsed_config(partial_config, Path::new("")); + assert_eq!( + config.partially_unstable_option(), + PartiallyUnstableOption::V3 + ); + } } } @@ -489,6 +572,11 @@ mod test { assert_eq!(config.was_set().verbose(), false); } + const PRINT_DOCS_STABLE_OPTION: &str = "stable_option Default: false"; + const PRINT_DOCS_UNSTABLE_OPTION: &str = "unstable_option Default: false (unstable)"; + const PRINT_DOCS_PARTIALLY_UNSTABLE_OPTION: &str = + "partially_unstable_option [V1|V2|V3 (unstable)] Default: V1"; + #[test] fn test_print_docs_exclude_unstable() { use self::mock::Config; @@ -497,10 +585,9 @@ mod test { Config::print_docs(&mut output, false); let s = str::from_utf8(&output).unwrap(); - - assert_eq!(s.contains("stable_option"), true); - assert_eq!(s.contains("unstable_option"), false); - assert_eq!(s.contains("(unstable)"), false); + assert_eq!(s.contains(PRINT_DOCS_STABLE_OPTION), true); + assert_eq!(s.contains(PRINT_DOCS_UNSTABLE_OPTION), false); + assert_eq!(s.contains(PRINT_DOCS_PARTIALLY_UNSTABLE_OPTION), true); } #[test] @@ -511,9 +598,9 @@ mod test { Config::print_docs(&mut output, true); let s = str::from_utf8(&output).unwrap(); - assert_eq!(s.contains("stable_option"), true); - assert_eq!(s.contains("unstable_option"), true); - assert_eq!(s.contains("(unstable)"), true); + assert_eq!(s.contains(PRINT_DOCS_STABLE_OPTION), true); + assert_eq!(s.contains(PRINT_DOCS_UNSTABLE_OPTION), true); + assert_eq!(s.contains(PRINT_DOCS_PARTIALLY_UNSTABLE_OPTION), true); } #[test] @@ -541,6 +628,7 @@ normalize_doc_attributes = false format_strings = false format_macro_matchers = false format_macro_bodies = true +skip_macro_invocations = [] hex_literal_case = "Preserve" empty_item_single_line = true struct_lit_single_line = true @@ -567,7 +655,7 @@ enum_discrim_align_threshold = 0 match_arm_blocks = true match_arm_leading_pipes = "Never" force_multiline_blocks = false -fn_args_layout = "Tall" +fn_params_layout = "Tall" brace_style = "SameLineWhere" control_brace_style = "AlwaysSameLine" trailing_semicolon = true @@ -921,4 +1009,45 @@ make_backup = false assert_eq!(config.single_line_if_else_max_width(), 100); } } + + #[cfg(test)] + mod partially_unstable_option { + use super::mock::{Config, PartiallyUnstableOption}; + use super::*; + + /// From the command line, we can override with a stable variant. + #[test] + fn test_override_stable_value() { + let mut config = Config::default(); + config.override_value("partially_unstable_option", "V2"); + assert_eq!( + config.partially_unstable_option(), + PartiallyUnstableOption::V2 + ); + } + + /// From the command line, we can override with an unstable variant. + #[test] + fn test_override_unstable_value() { + let mut config = Config::default(); + config.override_value("partially_unstable_option", "V3"); + assert_eq!( + config.partially_unstable_option(), + PartiallyUnstableOption::V3 + ); + } + } + + #[test] + fn test_override_skip_macro_invocations() { + let mut config = Config::default(); + config.override_value("skip_macro_invocations", r#"["*", "println"]"#); + assert_eq!( + config.skip_macro_invocations(), + MacroSelectors(vec![ + MacroSelector::All, + MacroSelector::Name(MacroName::new("println".to_owned())) + ]) + ); + } } diff --git a/src/expr.rs b/src/expr.rs index 868ff045ab78b..0be4c3cf168cc 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -29,9 +29,9 @@ use crate::spanned::Spanned; use crate::string::{rewrite_string, StringFormat}; use crate::types::{rewrite_path, PathContext}; use crate::utils::{ - colon_spaces, contains_skip, count_newlines, first_line_ends_with, inner_attributes, - last_line_extendable, last_line_width, mk_sp, outer_attributes, semicolon_for_expr, - unicode_str_width, wrap_str, + colon_spaces, contains_skip, count_newlines, filtered_str_fits, first_line_ends_with, + inner_attributes, last_line_extendable, last_line_width, mk_sp, outer_attributes, + semicolon_for_expr, unicode_str_width, wrap_str, }; use crate::vertical::rewrite_with_alignment; use crate::visitor::FmtVisitor; @@ -2050,8 +2050,7 @@ fn choose_rhs( match (orig_rhs, new_rhs) { (Some(ref orig_rhs), Some(ref new_rhs)) - if wrap_str(new_rhs.clone(), context.config.max_width(), new_shape) - .is_none() => + if !filtered_str_fits(&new_rhs, context.config.max_width(), new_shape) => { Some(format!("{}{}", before_space_str, orig_rhs)) } diff --git a/src/imports.rs b/src/imports.rs index d9dc8d004aff4..339e5cef5af91 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -251,8 +251,8 @@ fn flatten_use_trees( use_trees: Vec, import_granularity: ImportGranularity, ) -> Vec { - // Return non-sorted single occurance of the use-trees text string; - // order is by first occurance of the use-tree. + // Return non-sorted single occurrence of the use-trees text string; + // order is by first occurrence of the use-tree. use_trees .into_iter() .flat_map(|tree| tree.flatten(import_granularity)) diff --git a/src/items.rs b/src/items.rs index a2a73f0a5fb3a..25e8a024857ce 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1084,7 +1084,11 @@ pub(crate) fn format_trait( let item_snippet = context.snippet(item.span); if let Some(lo) = item_snippet.find('/') { // 1 = `{` - let comment_hi = body_lo - BytePos(1); + let comment_hi = if generics.params.len() > 0 { + generics.span.lo() - BytePos(1) + } else { + body_lo - BytePos(1) + }; let comment_lo = item.span.lo() + BytePos(lo as u32); if comment_lo < comment_hi { match recover_missing_comment_in_span( @@ -1241,7 +1245,7 @@ fn format_unit_struct( ) -> Option { let header_str = format_header(context, p.prefix, p.ident, p.vis, offset); let generics_str = if let Some(generics) = p.generics { - let hi = context.snippet_provider.span_before(p.span, ";"); + let hi = context.snippet_provider.span_before_last(p.span, ";"); format_generics( context, generics, @@ -2602,7 +2606,7 @@ fn rewrite_params( ¶m_items, context .config - .fn_args_layout() + .fn_params_layout() .to_list_tactic(param_items.len()), Separator::Comma, one_line_budget, diff --git a/src/lists.rs b/src/lists.rs index e87850507824f..a878e6cf9b2fc 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -297,9 +297,9 @@ where } else { inner_item.as_ref() }; - let mut item_last_line_width = item_last_line.len() + item_sep_len; + let mut item_last_line_width = unicode_str_width(item_last_line) + item_sep_len; if item_last_line.starts_with(&**indent_str) { - item_last_line_width -= indent_str.len(); + item_last_line_width -= unicode_str_width(indent_str); } if !item.is_substantial() { @@ -449,7 +449,7 @@ where } else if starts_with_newline(comment) { false } else { - comment.trim().contains('\n') || comment.trim().len() > width + comment.trim().contains('\n') || unicode_str_width(comment.trim()) > width }; rewrite_comment( @@ -465,7 +465,7 @@ where if !starts_with_newline(comment) { if formatting.align_comments { let mut comment_alignment = - post_comment_alignment(item_max_width, inner_item.len()); + post_comment_alignment(item_max_width, unicode_str_width(inner_item)); if first_line_width(&formatted_comment) + last_line_width(&result) + comment_alignment @@ -475,7 +475,7 @@ where item_max_width = None; formatted_comment = rewrite_post_comment(&mut item_max_width)?; comment_alignment = - post_comment_alignment(item_max_width, inner_item.len()); + post_comment_alignment(item_max_width, unicode_str_width(inner_item)); } for _ in 0..=comment_alignment { result.push(' '); @@ -533,7 +533,7 @@ where let mut first = true; for item in items.clone().into_iter().skip(i) { let item = item.as_ref(); - let inner_item_width = item.inner_as_ref().len(); + let inner_item_width = unicode_str_width(item.inner_as_ref()); if !first && (item.is_different_group() || item.post_comment.is_none() @@ -552,8 +552,8 @@ where max_width } -fn post_comment_alignment(item_max_width: Option, inner_item_len: usize) -> usize { - item_max_width.unwrap_or(0).saturating_sub(inner_item_len) +fn post_comment_alignment(item_max_width: Option, inner_item_width: usize) -> usize { + item_max_width.unwrap_or(0).saturating_sub(inner_item_width) } pub(crate) struct ListItems<'a, I, F1, F2, F3> diff --git a/src/macros.rs b/src/macros.rs index df94938803788..d58f7547fefb3 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -35,8 +35,8 @@ use crate::shape::{Indent, Shape}; use crate::source_map::SpanUtils; use crate::spanned::Spanned; use crate::utils::{ - format_visibility, indent_next_line, is_empty_line, mk_sp, remove_trailing_white_spaces, - rewrite_ident, trim_left_preserve_layout, wrap_str, NodeIdExt, + filtered_str_fits, format_visibility, indent_next_line, is_empty_line, mk_sp, + remove_trailing_white_spaces, rewrite_ident, trim_left_preserve_layout, NodeIdExt, }; use crate::visitor::FmtVisitor; @@ -157,7 +157,8 @@ pub(crate) fn rewrite_macro( ) -> Option { let should_skip = context .skip_context - .skip_macro(context.snippet(mac.path.span)); + .macros + .skip(context.snippet(mac.path.span)); if should_skip { None } else { @@ -1265,15 +1266,14 @@ impl MacroBranch { } } }; - let new_body = wrap_str( - new_body_snippet.snippet.to_string(), - config.max_width(), - shape, - )?; + + if !filtered_str_fits(&new_body_snippet.snippet, config.max_width(), shape) { + return None; + } // Indent the body since it is in a block. let indent_str = body_indent.to_string(&config); - let mut new_body = LineClasses::new(new_body.trim_end()) + let mut new_body = LineClasses::new(new_body_snippet.snippet.trim_end()) .enumerate() .fold( (String::new(), true), diff --git a/src/skip.rs b/src/skip.rs index 032922d421df7..68f85b2ade48a 100644 --- a/src/skip.rs +++ b/src/skip.rs @@ -2,33 +2,84 @@ use rustc_ast::ast; use rustc_ast_pretty::pprust; +use std::collections::HashSet; -/// Take care of skip name stack. You can update it by attributes slice or -/// by other context. Query this context to know if you need skip a block. +/// Track which blocks of code are to be skipped when formatting. +/// +/// You can update it by: +/// +/// - attributes slice +/// - manually feeding values into the underlying contexts +/// +/// Query this context to know if you need to skip a block. #[derive(Default, Clone)] pub(crate) struct SkipContext { - macros: Vec, - attributes: Vec, + pub(crate) macros: SkipNameContext, + pub(crate) attributes: SkipNameContext, } impl SkipContext { pub(crate) fn update_with_attrs(&mut self, attrs: &[ast::Attribute]) { - self.macros.append(&mut get_skip_names("macros", attrs)); - self.attributes - .append(&mut get_skip_names("attributes", attrs)); + self.macros.extend(get_skip_names("macros", attrs)); + self.attributes.extend(get_skip_names("attributes", attrs)); } - pub(crate) fn update(&mut self, mut other: SkipContext) { - self.macros.append(&mut other.macros); - self.attributes.append(&mut other.attributes); + pub(crate) fn update(&mut self, other: SkipContext) { + let SkipContext { macros, attributes } = other; + self.macros.update(macros); + self.attributes.update(attributes); + } +} + +/// Track which names to skip. +/// +/// Query this context with a string to know whether to skip it. +#[derive(Clone)] +pub(crate) enum SkipNameContext { + All, + Values(HashSet), +} + +impl Default for SkipNameContext { + fn default() -> Self { + Self::Values(Default::default()) + } +} + +impl Extend for SkipNameContext { + fn extend>(&mut self, iter: T) { + match self { + Self::All => {} + Self::Values(values) => values.extend(iter), + } + } +} + +impl SkipNameContext { + pub(crate) fn update(&mut self, other: Self) { + match (self, other) { + // If we're already skipping everything, nothing more can be added + (Self::All, _) => {} + // If we want to skip all, set it + (this, Self::All) => { + *this = Self::All; + } + // If we have some new values to skip, add them + (Self::Values(existing_values), Self::Values(new_values)) => { + existing_values.extend(new_values) + } + } } - pub(crate) fn skip_macro(&self, name: &str) -> bool { - self.macros.iter().any(|n| n == name) + pub(crate) fn skip(&self, name: &str) -> bool { + match self { + Self::All => true, + Self::Values(values) => values.contains(name), + } } - pub(crate) fn skip_attribute(&self, name: &str) -> bool { - self.attributes.iter().any(|n| n == name) + pub(crate) fn skip_all(&mut self) { + *self = Self::All; } } diff --git a/src/test/configuration_snippet.rs b/src/test/configuration_snippet.rs index c8fda7c8556db..c70b3c5facd50 100644 --- a/src/test/configuration_snippet.rs +++ b/src/test/configuration_snippet.rs @@ -27,8 +27,13 @@ impl 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#"^#### `"?([^`"]+)"?`"#) + regex::Regex::new(r#"^#### `"?([^`]+?)"?`"#) .expect("failed creating configuration value pattern"); } diff --git a/src/test/mod.rs b/src/test/mod.rs index 6b5bc2b30dd5a..cfad4a8ed0e3e 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -982,11 +982,7 @@ fn rustfmt() -> PathBuf { assert!( me.is_file() || me.with_extension("exe").is_file(), "{}", - if cfg!(release) { - "no rustfmt bin, try running `cargo build --release` before testing" - } else { - "no rustfmt bin, try running `cargo build` before testing" - } + "no rustfmt bin, try running `cargo build` or `cargo build --release` before testing" ); me } diff --git a/src/types.rs b/src/types.rs index c1991e8d2c808..01e2fb6e61e15 100644 --- a/src/types.rs +++ b/src/types.rs @@ -941,6 +941,28 @@ fn join_bounds_inner( ast::GenericBound::Trait(..) => last_line_extendable(s), }; + // Whether a GenericBound item is a PathSegment segment that includes internal array + // that contains more than one item + let is_item_with_multi_items_array = |item: &ast::GenericBound| match item { + ast::GenericBound::Trait(ref poly_trait_ref, ..) => { + let segments = &poly_trait_ref.trait_ref.path.segments; + if segments.len() > 1 { + true + } else { + if let Some(args_in) = &segments[0].args { + matches!( + args_in.deref(), + ast::GenericArgs::AngleBracketed(bracket_args) + if bracket_args.args.len() > 1 + ) + } else { + false + } + } + } + _ => false, + }; + let result = items.iter().enumerate().try_fold( (String::new(), None, false), |(strs, prev_trailing_span, prev_extendable), (i, item)| { @@ -1035,10 +1057,24 @@ fn join_bounds_inner( }, )?; - if !force_newline - && items.len() > 1 - && (result.0.contains('\n') || result.0.len() > shape.width) - { + // Whether to retry with a forced newline: + // Only if result is not already multiline and did not exceed line width, + // and either there is more than one item; + // or the single item is of type `Trait`, + // and any of the internal arrays contains more than one item; + let retry_with_force_newline = match context.config.version() { + Version::One => { + !force_newline + && items.len() > 1 + && (result.0.contains('\n') || result.0.len() > shape.width) + } + Version::Two if force_newline => false, + Version::Two if (!result.0.contains('\n') && result.0.len() <= shape.width) => false, + Version::Two if items.len() > 1 => true, + Version::Two => is_item_with_multi_items_array(&items[0]), + }; + + if retry_with_force_newline { join_bounds_inner(context, shape, items, need_indent, true) } else { Some(result.0) diff --git a/src/utils.rs b/src/utils.rs index 3e884419f1a32..f681f55b37b9d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -384,14 +384,15 @@ macro_rules! skip_out_of_file_lines_range_visitor { // Wraps String in an Option. Returns Some when the string adheres to the // Rewrite constraints defined for the Rewrite trait and None otherwise. pub(crate) fn wrap_str(s: String, max_width: usize, shape: Shape) -> Option { - if is_valid_str(&filter_normal_code(&s), max_width, shape) { + if filtered_str_fits(&s, max_width, shape) { Some(s) } else { None } } -fn is_valid_str(snippet: &str, max_width: usize, shape: Shape) -> bool { +pub(crate) fn filtered_str_fits(snippet: &str, max_width: usize, shape: Shape) -> bool { + let snippet = &filter_normal_code(snippet); if !snippet.is_empty() { // First line must fits with `shape.width`. if first_line_width(snippet) > shape.width { diff --git a/src/visitor.rs b/src/visitor.rs index 9c3cc7820d299..f4d84d1381fc0 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -8,7 +8,7 @@ use rustc_span::{symbol, BytePos, Pos, Span}; use crate::attr::*; use crate::comment::{contains_comment, rewrite_comment, CodeCharKind, CommentCodeSlices}; use crate::config::Version; -use crate::config::{BraceStyle, Config}; +use crate::config::{BraceStyle, Config, MacroSelector}; use crate::coverage::transform_missing_snippet; use crate::items::{ format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, rewrite_extern_crate, @@ -770,6 +770,15 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { snippet_provider: &'a SnippetProvider, report: FormatReport, ) -> FmtVisitor<'a> { + let mut skip_context = SkipContext::default(); + let mut macro_names = Vec::new(); + for macro_selector in config.skip_macro_invocations().0 { + match macro_selector { + MacroSelector::Name(name) => macro_names.push(name.to_string()), + MacroSelector::All => skip_context.macros.skip_all(), + } + } + skip_context.macros.extend(macro_names); FmtVisitor { parent_context: None, parse_sess: parse_session, @@ -784,7 +793,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { is_macro_def: false, macro_rewrite_failure: false, report, - skip_context: Default::default(), + skip_context, } } diff --git a/tests/cargo-fmt/main.rs b/tests/cargo-fmt/main.rs index 348876cd264fa..701c36fadeafa 100644 --- a/tests/cargo-fmt/main.rs +++ b/tests/cargo-fmt/main.rs @@ -4,6 +4,8 @@ use std::env; use std::path::Path; use std::process::Command; +use rustfmt_config_proc_macro::rustfmt_only_ci_test; + /// Run the cargo-fmt executable and return its output. fn cargo_fmt(args: &[&str]) -> (String, String) { let mut bin_dir = env::current_exe().unwrap(); @@ -47,7 +49,7 @@ macro_rules! assert_that { }; } -#[ignore] +#[rustfmt_only_ci_test] #[test] fn version() { assert_that!(&["--version"], starts_with("rustfmt ")); @@ -56,7 +58,7 @@ fn version() { assert_that!(&["--", "--version"], starts_with("rustfmt ")); } -#[ignore] +#[rustfmt_only_ci_test] #[test] fn print_config() { assert_that!( @@ -65,7 +67,7 @@ fn print_config() { ); } -#[ignore] +#[rustfmt_only_ci_test] #[test] fn rustfmt_help() { assert_that!(&["--", "--help"], contains("Format Rust code")); @@ -73,7 +75,7 @@ fn rustfmt_help() { assert_that!(&["--", "--help=config"], contains("Configuration Options:")); } -#[ignore] +#[rustfmt_only_ci_test] #[test] fn cargo_fmt_out_of_line_test_modules() { // See also https://github.com/rust-lang/rustfmt/issues/5119 @@ -96,3 +98,22 @@ fn cargo_fmt_out_of_line_test_modules() { assert!(stdout.contains(&format!("Diff in {}", path.display()))) } } + +#[rustfmt_only_ci_test] +#[test] +fn cargo_fmt_emits_error_on_line_overflow_true() { + // See also https://github.com/rust-lang/rustfmt/issues/3164 + let args = [ + "--check", + "--manifest-path", + "tests/cargo-fmt/source/issue_3164/Cargo.toml", + "--", + "--config", + "error_on_line_overflow=true", + ]; + + let (_stdout, stderr) = cargo_fmt(&args); + assert!(stderr.contains( + "line formatted, but exceeded maximum width (maximum: 100 (see `max_width` option)" + )) +} diff --git a/tests/cargo-fmt/source/issue_3164/Cargo.toml b/tests/cargo-fmt/source/issue_3164/Cargo.toml new file mode 100644 index 0000000000000..580ef7e6e24fe --- /dev/null +++ b/tests/cargo-fmt/source/issue_3164/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "issue_3164" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/tests/cargo-fmt/source/issue_3164/src/main.rs b/tests/cargo-fmt/source/issue_3164/src/main.rs new file mode 100644 index 0000000000000..9330107ac8dc7 --- /dev/null +++ b/tests/cargo-fmt/source/issue_3164/src/main.rs @@ -0,0 +1,13 @@ +#[allow(unused_macros)] +macro_rules! foo { + ($id:ident) => { + macro_rules! bar { + ($id2:tt) => { + #[cfg(any(target_feature = $id2, target_feature = $id2, target_feature = $id2, target_feature = $id2, target_feature = $id2))] + fn $id() {} + }; + } + }; +} + +fn main() {} diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index c3cfd34317a37..4c37100894f83 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -3,7 +3,7 @@ comment_width = 80 tab_spaces = 2 newline_style = "Unix" brace_style = "SameLineWhere" -fn_args_layout = "Tall" +fn_params_layout = "Tall" trailing_comma = "Vertical" indent_style = "Block" reorder_imports = false diff --git a/tests/mod-resolver/issue-5198/lib/c/d/explanation.txt b/tests/mod-resolver/issue-5198/lib/c/d/explanation.txt index 92c9e3021431f..254102ebabdc2 100644 --- a/tests/mod-resolver/issue-5198/lib/c/d/explanation.txt +++ b/tests/mod-resolver/issue-5198/lib/c/d/explanation.txt @@ -9,7 +9,7 @@ The directory name './lib/c/d/' conflicts with the './lib/c/d.rs' file name. * mod g; Module resolution will fail if we look for './lib/c/d/e.rs' or './lib/c/d/e/mod.rs', -so we should fall back to looking for './lib/c/e.rs', which correctly finds the modlue, that +so we should fall back to looking for './lib/c/e.rs', which correctly finds the module, that rustfmt should format. './lib/c/d/f.rs' and './lib/c/d/g/mod.rs' exist at the default submodule paths so we should be able diff --git a/tests/mod-resolver/issue-5198/lib/explanation.txt b/tests/mod-resolver/issue-5198/lib/explanation.txt index d436a8076cd71..90464def8ebcc 100644 --- a/tests/mod-resolver/issue-5198/lib/explanation.txt +++ b/tests/mod-resolver/issue-5198/lib/explanation.txt @@ -9,7 +9,7 @@ The directory name './lib' conflicts with the './lib.rs' file name. * mod c; Module resolution will fail if we look for './lib/a.rs' or './lib/a/mod.rs', -so we should fall back to looking for './a.rs', which correctly finds the modlue that +so we should fall back to looking for './a.rs', which correctly finds the module that rustfmt should format. './lib/b.rs' and './lib/c/mod.rs' exist at the default submodule paths so we should be able diff --git a/tests/rustfmt/main.rs b/tests/rustfmt/main.rs index 4c6d52726f3fe..7ff301e80195a 100644 --- a/tests/rustfmt/main.rs +++ b/tests/rustfmt/main.rs @@ -5,6 +5,8 @@ use std::fs::remove_file; use std::path::Path; use std::process::Command; +use rustfmt_config_proc_macro::rustfmt_only_ci_test; + /// Run the rustfmt executable and return its output. fn rustfmt(args: &[&str]) -> (String, String) { let mut bin_dir = env::current_exe().unwrap(); @@ -47,7 +49,7 @@ macro_rules! assert_that { }; } -#[ignore] +#[rustfmt_only_ci_test] #[test] fn print_config() { assert_that!( @@ -76,7 +78,7 @@ fn print_config() { remove_file("minimal-config").unwrap(); } -#[ignore] +#[rustfmt_only_ci_test] #[test] fn inline_config() { // single invocation @@ -157,3 +159,18 @@ fn mod_resolution_error_path_attribute_does_not_exist() { // The path attribute points to a file that does not exist assert!(stderr.contains("does_not_exist.rs does not exist")); } + +#[test] +fn rustfmt_emits_error_on_line_overflow_true() { + // See also https://github.com/rust-lang/rustfmt/issues/3164 + let args = [ + "--config", + "error_on_line_overflow=true", + "tests/cargo-fmt/source/issue_3164/src/main.rs", + ]; + + let (_stdout, stderr) = rustfmt(&args); + assert!(stderr.contains( + "line formatted, but exceeded maximum width (maximum: 100 (see `max_width` option)" + )) +} diff --git a/tests/source/cfg_if/detect/arch/x86.rs b/tests/source/cfg_if/detect/arch/x86.rs index d26f4ee894fad..131cbb855f163 100644 --- a/tests/source/cfg_if/detect/arch/x86.rs +++ b/tests/source/cfg_if/detect/arch/x86.rs @@ -329,7 +329,7 @@ pub enum Feature { tbm, /// POPCNT (Population Count) popcnt, - /// FXSR (Floating-point context fast save and restor) + /// FXSR (Floating-point context fast save and restore) fxsr, /// XSAVE (Save Processor Extended States) xsave, diff --git a/tests/source/comments_unicode.rs b/tests/source/comments_unicode.rs new file mode 100644 index 0000000000000..e65a245ba9343 --- /dev/null +++ b/tests/source/comments_unicode.rs @@ -0,0 +1,140 @@ +impl Default for WhitespaceCharacters { + fn default() -> Self { + Self { + space: '·', // U+00B7 + nbsp: '⍽', // U+237D + tab: '→', // U+2192 + newline: '⏎', // U+23CE + } + } +} + +const RAINBOWS: &[&str] = &[ + "rаinЬοѡ", // hue: 0 + "raіnЬοw", // hue: 2 + "rаіɴЬow", // hue: 2 + "raіɴЬoѡ", // hue: 8 + "ʀainЬow", // hue: 8 + "ʀaіɴboѡ", // hue: 8 + "ʀаіnbοw", // hue: 11 + "rainЬoѡ", // hue: 14 + "raіɴbow", // hue: 14 + "rаiɴЬow", // hue: 20 + "raіnЬow", // hue: 26 + "ʀaiɴbοw", // hue: 32 + "raіɴboѡ", // hue: 35 + "rаiɴbow", // hue: 35 + "rаіnbοw", // hue: 38 + "rаinЬow", // hue: 47 + "ʀaіnboѡ", // hue: 47 + "ʀaіnЬoѡ", // hue: 47 + "ʀаіɴbοw", // hue: 53 + "ʀaіnЬοѡ", // hue: 57 + "raiɴЬoѡ", // hue: 68 + "ʀainbοѡ", // hue: 68 + "ʀаinboѡ", // hue: 68 + "ʀаiɴbοw", // hue: 68 + "ʀаіnbow", // hue: 68 + "rаіnЬοѡ", // hue: 69 + "ʀainЬοw", // hue: 71 + "raiɴbow", // hue: 73 + "raіnЬoѡ", // hue: 74 + "rаіɴbοw", // hue: 77 + "raіnЬοѡ", // hue: 81 + "raiɴЬow", // hue: 83 + "ʀainbοw", // hue: 83 + "ʀаinbow", // hue: 83 + "ʀаiɴbοѡ", // hue: 83 + "ʀаіnboѡ", // hue: 83 + "ʀаіɴЬοѡ", // hue: 84 + "rainЬow", // hue: 85 + "ʀаiɴЬοw", // hue: 86 + "ʀаіnbοѡ", // hue: 89 + "ʀаіnЬοw", // hue: 92 + "rаiɴbοw", // hue: 95 + "ʀаіɴbοѡ", // hue: 98 + "ʀаiɴЬοѡ", // hue: 99 + "raіnbοw", // hue: 101 + "ʀаіɴЬοw", // hue: 101 + "ʀaiɴboѡ", // hue: 104 + "ʀаinbοѡ", // hue: 104 + "rаiɴbοѡ", // hue: 107 + "ʀаinЬοw", // hue: 107 + "rаiɴЬοw", // hue: 110 + "rаіnboѡ", // hue: 110 + "rаіnbοѡ", // hue: 113 + "ʀainЬοѡ", // hue: 114 + "rаіnЬοw", // hue: 116 + "ʀaіɴЬow", // hue: 116 + "rаinbοw", // hue: 122 + "ʀаіɴboѡ", // hue: 125 + "rаinbοѡ", // hue: 131 + "rainbow", // hue: 134 + "rаinЬοw", // hue: 134 + "ʀаiɴboѡ", // hue: 140 + "rainЬοѡ", // hue: 141 + "raіɴЬow", // hue: 143 + "ʀainЬoѡ", // hue: 143 + "ʀaіɴbow", // hue: 143 + "ʀainbow", // hue: 148 + "rаіɴboѡ", // hue: 149 + "ʀainboѡ", // hue: 155 + "ʀaіnbow", // hue: 155 + "ʀaіnЬow", // hue: 155 + "raiɴbοw", // hue: 158 + "ʀаiɴЬoѡ", // hue: 158 + "rainbοw", // hue: 160 + "rаinbow", // hue: 160 + "ʀaіɴbοѡ", // hue: 164 + "ʀаiɴbow", // hue: 164 + "ʀаіnЬoѡ", // hue: 164 + "ʀaiɴЬοѡ", // hue: 165 + "rаiɴboѡ", // hue: 167 + "ʀaіɴЬοw", // hue: 167 + "ʀaіɴЬοѡ", // hue: 171 + "raіnboѡ", // hue: 173 + "ʀаіɴЬoѡ", // hue: 173 + "rаіɴbοѡ", // hue: 176 + "ʀаinЬow", // hue: 176 + "rаiɴЬοѡ", // hue: 177 + "rаіɴЬοw", // hue: 179 + "ʀаinЬoѡ", // hue: 179 + "ʀаіɴbow", // hue: 179 + "rаiɴЬoѡ", // hue: 182 + "raіɴbοѡ", // hue: 188 + "rаіnЬoѡ", // hue: 188 + "raiɴЬοѡ", // hue: 189 + "raіɴЬοw", // hue: 191 + "ʀaіɴbοw", // hue: 191 + "ʀаіnЬow", // hue: 191 + "rainbοѡ", // hue: 194 + "rаinboѡ", // hue: 194 + "rаіnbow", // hue: 194 + "rainЬοw", // hue: 197 + "rаinЬoѡ", // hue: 206 + "rаіɴbow", // hue: 206 + "rаіɴЬοѡ", // hue: 210 + "ʀaiɴЬow", // hue: 212 + "raіɴbοw", // hue: 218 + "rаіnЬow", // hue: 218 + "ʀaiɴbοѡ", // hue: 221 + "ʀaiɴЬοw", // hue: 224 + "ʀaіnbοѡ", // hue: 227 + "raiɴboѡ", // hue: 230 + "ʀaіnbοw", // hue: 230 + "ʀaіnЬοw", // hue: 230 + "ʀаinЬοѡ", // hue: 231 + "rainboѡ", // hue: 232 + "raіnbow", // hue: 232 + "ʀаіɴЬow", // hue: 233 + "ʀaіɴЬoѡ", // hue: 239 + "ʀаіnЬοѡ", // hue: 246 + "raiɴbοѡ", // hue: 248 + "ʀаiɴЬow", // hue: 248 + "raіɴЬοѡ", // hue: 249 + "raiɴЬοw", // hue: 251 + "rаіɴЬoѡ", // hue: 251 + "ʀaiɴbow", // hue: 251 + "ʀаinbοw", // hue: 251 + "raіnbοѡ", // hue: 254 +]; diff --git a/tests/source/configs/fn_args_layout/compressed.rs b/tests/source/configs/fn_params_layout/compressed.rs similarity index 92% rename from tests/source/configs/fn_args_layout/compressed.rs rename to tests/source/configs/fn_params_layout/compressed.rs index 66a371c259f0c..eb573d3121f57 100644 --- a/tests/source/configs/fn_args_layout/compressed.rs +++ b/tests/source/configs/fn_params_layout/compressed.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Compressed +// rustfmt-fn_params_layout: Compressed // Function arguments density trait Lorem { diff --git a/tests/source/configs/fn_args_layout/tall.rs b/tests/source/configs/fn_params_layout/tall.rs similarity index 93% rename from tests/source/configs/fn_args_layout/tall.rs rename to tests/source/configs/fn_params_layout/tall.rs index f11e86fd3139c..4be34f0fe4ac1 100644 --- a/tests/source/configs/fn_args_layout/tall.rs +++ b/tests/source/configs/fn_params_layout/tall.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Tall +// rustfmt-fn_params_layout: Tall // Function arguments density trait Lorem { diff --git a/tests/source/configs/fn_args_layout/vertical.rs b/tests/source/configs/fn_params_layout/vertical.rs similarity index 92% rename from tests/source/configs/fn_args_layout/vertical.rs rename to tests/source/configs/fn_params_layout/vertical.rs index a23cc025225fb..674968023f997 100644 --- a/tests/source/configs/fn_args_layout/vertical.rs +++ b/tests/source/configs/fn_params_layout/vertical.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Vertical +// rustfmt-fn_params_layout: Vertical // Function arguments density trait Lorem { diff --git a/tests/source/enum.rs b/tests/source/enum.rs index 0ed9651abe722..a7b9616929cb0 100644 --- a/tests/source/enum.rs +++ b/tests/source/enum.rs @@ -36,7 +36,7 @@ enum StructLikeVariants { Normal(u32, String, ), StructLike { x: i32, // Test comment // Pre-comment - #[Attr50] y: SomeType, // Aanother Comment + #[Attr50] y: SomeType, // Another Comment }, SL { a: A } } diff --git a/tests/source/fn-custom-7.rs b/tests/source/fn-custom-7.rs index d5330196bf795..3ecd8701727ad 100644 --- a/tests/source/fn-custom-7.rs +++ b/tests/source/fn-custom-7.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-fn_args_layout: Vertical +// rustfmt-fn_params_layout: Vertical // rustfmt-brace_style: AlwaysNextLine // Case with only one variable. diff --git a/tests/source/fn-custom.rs b/tests/source/fn-custom.rs index 77ced4c5e0e10..64ef0ecfaae49 100644 --- a/tests/source/fn-custom.rs +++ b/tests/source/fn-custom.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Compressed +// rustfmt-fn_params_layout: Compressed // Test some of the ways function signatures can be customised. // Test compressed layout of args. diff --git a/tests/source/fn_args_layout-vertical.rs b/tests/source/fn_args_layout-vertical.rs index 759bc83d01570..fd6e3f0442ec1 100644 --- a/tests/source/fn_args_layout-vertical.rs +++ b/tests/source/fn_args_layout-vertical.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Vertical +// rustfmt-fn_params_layout: Vertical // Empty list should stay on one line. fn do_bar( diff --git a/tests/source/issue-3987/format_macro_bodies_true.rs b/tests/source/issue-3987/format_macro_bodies_true.rs new file mode 100644 index 0000000000000..9af114fbe574d --- /dev/null +++ b/tests/source/issue-3987/format_macro_bodies_true.rs @@ -0,0 +1,26 @@ +// rustfmt-format_macro_bodies: true + +// with comments +macro_rules! macros { + () => {{ + Struct { + field: ( + 42 + //comment 1 + 42 + //comment 2 + ), + }; + }}; +} + +// without comments +macro_rules! macros { + () => {{ + Struct { + field: ( + 42 + + 42 + ), + }; + }}; +} diff --git a/tests/source/issue-4643.rs b/tests/source/issue-4643.rs new file mode 100644 index 0000000000000..382072d9004bf --- /dev/null +++ b/tests/source/issue-4643.rs @@ -0,0 +1,23 @@ +// output doesn't get corrupted when using comments within generic type parameters of a trait + +pub trait Something< + A, + // some comment + B, + C +> { + fn a(&self, x: A) -> i32; + fn b(&self, x: B) -> i32; + fn c(&self, x: C) -> i32; +} + +pub trait SomethingElse< + A, + /* some comment */ + B, + C +> { + fn a(&self, x: A) -> i32; + fn b(&self, x: B) -> i32; + fn c(&self, x: C) -> i32; +} diff --git a/tests/source/issue-4689/one.rs b/tests/source/issue-4689/one.rs new file mode 100644 index 0000000000000..d048eb10fb15c --- /dev/null +++ b/tests/source/issue-4689/one.rs @@ -0,0 +1,149 @@ +// rustfmt-version: One + +// Based on the issue description +pub trait PrettyPrinter<'tcx>: +Printer< +'tcx, +Error = fmt::Error, +Path = Self, +Region = Self, +Type = Self, +DynExistential = Self, +Const = Self, +> +{ +// +} +pub trait PrettyPrinter<'tcx>: +Printer< +'tcx, +Error = fmt::Error, +Path = Self, +Region = Self, +Type = Self, +DynExistential = Self, +Const = Self, +> + fmt::Write +{ +// +} +pub trait PrettyPrinter<'tcx>: +Printer< +'tcx, +Error = fmt::Error, +Path = Self, +Region = Self, +Type = Self, +DynExistential = Self, +Const = Self, +> + fmt::Write1 + fmt::Write2 +{ +// +} +pub trait PrettyPrinter<'tcx>: +fmt::Write + Printer< +'tcx, +Error = fmt::Error, +Path = Self, +Region = Self, +Type = Self, +DynExistential = Self, +Const = Self, +> +{ +// +} +pub trait PrettyPrinter<'tcx>: +fmt::Write + Printer1< +'tcx, +Error = fmt::Error, +Path = Self, +Region = Self, +Type = Self, +DynExistential = Self, +Const = Self, +> + Printer2< +'tcx, +Error = fmt::Error, +Path = Self, +Region = Self, +Type = Self, +DynExistential = Self, +Const = Self, +> +{ +// +} + +// Some test cases to ensure other cases formatting were not changed +fn f() -> Box< +FnMut() -> Thing< +WithType = LongItemName, +Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger, +>, +> { +} +fn f() -> Box< +FnMut() -> Thing< +WithType = LongItemName, +Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger, +> + fmt::Write1 ++ fmt::Write2, +> { +} + +fn foo(foo2: F) +where +F: Fn( +// this comment is deleted +) +{ +} +fn foo(foo2: F) +where +F: Fn( +// this comment is deleted +) + fmt::Write +{ +} + +fn elaborate_bounds(mut mk_cand: F) +where +F: for<> FnMut( +&mut ProbeContext<>, +ty::PolyTraitRefffffffffffffffffffffffffffffffff<>, +tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem, +), +{ +} +fn elaborate_bounds(mut mk_cand: F) +where +F: for<> FnMut( +&mut ProbeContext<>, +ty::PolyTraitRefffffffffffffffffffffffffffffffff<>, +tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem, +) + fmt::Write, +{ +} + +fn build_sorted_static_get_entry_names( +mut entries: entryyyyyyyy, +) -> ( +impl Fn( +AlphabeticalTraversal, +Seconddddddddddddddddddddddddddddddddddd +) -> Parammmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm ++ Sendddddddddddddddddddddddddddddddddddddddddddd +) { +} + +pub trait SomeTrait: +Cloneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee ++ Eqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq +{ +} + +trait B = where +for<'b> &'b Self: Send ++ Cloneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee ++ Copyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy; diff --git a/tests/source/issue-4689/two.rs b/tests/source/issue-4689/two.rs new file mode 100644 index 0000000000000..ea7feda825d46 --- /dev/null +++ b/tests/source/issue-4689/two.rs @@ -0,0 +1,149 @@ +// rustfmt-version: Two + +// Based on the issue description +pub trait PrettyPrinter<'tcx>: +Printer< +'tcx, +Error = fmt::Error, +Path = Self, +Region = Self, +Type = Self, +DynExistential = Self, +Const = Self, +> +{ +// +} +pub trait PrettyPrinter<'tcx>: +Printer< +'tcx, +Error = fmt::Error, +Path = Self, +Region = Self, +Type = Self, +DynExistential = Self, +Const = Self, +> + fmt::Write +{ +// +} +pub trait PrettyPrinter<'tcx>: +Printer< +'tcx, +Error = fmt::Error, +Path = Self, +Region = Self, +Type = Self, +DynExistential = Self, +Const = Self, +> + fmt::Write1 + fmt::Write2 +{ +// +} +pub trait PrettyPrinter<'tcx>: +fmt::Write + Printer< +'tcx, +Error = fmt::Error, +Path = Self, +Region = Self, +Type = Self, +DynExistential = Self, +Const = Self, +> +{ +// +} +pub trait PrettyPrinter<'tcx>: +fmt::Write + Printer1< +'tcx, +Error = fmt::Error, +Path = Self, +Region = Self, +Type = Self, +DynExistential = Self, +Const = Self, +> + Printer2< +'tcx, +Error = fmt::Error, +Path = Self, +Region = Self, +Type = Self, +DynExistential = Self, +Const = Self, +> +{ +// +} + +// Some test cases to ensure other cases formatting were not changed +fn f() -> Box< +FnMut() -> Thing< +WithType = LongItemName, +Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger, +>, +> { +} +fn f() -> Box< +FnMut() -> Thing< +WithType = LongItemName, +Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger, +> + fmt::Write1 ++ fmt::Write2, +> { +} + +fn foo(foo2: F) +where +F: Fn( +// this comment is deleted +) +{ +} +fn foo(foo2: F) +where +F: Fn( +// this comment is deleted +) + fmt::Write +{ +} + +fn elaborate_bounds(mut mk_cand: F) +where +F: for<> FnMut( +&mut ProbeContext<>, +ty::PolyTraitRefffffffffffffffffffffffffffffffff<>, +tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem, +), +{ +} +fn elaborate_bounds(mut mk_cand: F) +where +F: for<> FnMut( +&mut ProbeContext<>, +ty::PolyTraitRefffffffffffffffffffffffffffffffff<>, +tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem, +) + fmt::Write, +{ +} + +fn build_sorted_static_get_entry_names( +mut entries: entryyyyyyyy, +) -> ( +impl Fn( +AlphabeticalTraversal, +Seconddddddddddddddddddddddddddddddddddd +) -> Parammmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm ++ Sendddddddddddddddddddddddddddddddddddddddddddd +) { +} + +pub trait SomeTrait: +Cloneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee ++ Eqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq +{ +} + +trait B = where +for<'b> &'b Self: Send ++ Cloneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee ++ Copyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy; diff --git a/tests/source/issue_1306.rs b/tests/source/issue_1306.rs new file mode 100644 index 0000000000000..03b78e34108cc --- /dev/null +++ b/tests/source/issue_1306.rs @@ -0,0 +1,29 @@ +// rustfmt-max_width: 160 +// rustfmt-fn_call_width: 96 +// rustfmt-fn_args_layout: Compressed +// rustfmt-trailing_comma: Always +// rustfmt-wrap_comments: true + +fn foo() { + for elem in try!(gen_epub_book::ops::parse_descriptor_file(&mut try!(File::open(&opts.source_file.1).map_err(|_| { + gen_epub_book::Error::Io { + desc: "input file", + op: "open", + more: None, + } + })), + "input file")) { + println!("{}", elem); + } +} + +fn write_content() { + io::copy(try!(File::open(in_f).map_err(|_| { + Error::Io { + desc: "Content", + op: "open", + more: None, + } + })), + w); +} diff --git a/tests/source/issue_3245.rs b/tests/source/issue_3245.rs new file mode 100644 index 0000000000000..0279246ed6ac4 --- /dev/null +++ b/tests/source/issue_3245.rs @@ -0,0 +1,4 @@ +fn main() { + let x = 1; + ;let y = 3; +} diff --git a/tests/source/issue_3561.rs b/tests/source/issue_3561.rs new file mode 100644 index 0000000000000..8f6cd8f9fbce5 --- /dev/null +++ b/tests/source/issue_3561.rs @@ -0,0 +1,6 @@ +fn main() {;7 +} + +fn main() { + ;7 +} diff --git a/tests/source/skip_macro_invocations/all.rs b/tests/source/skip_macro_invocations/all.rs new file mode 100644 index 0000000000000..d0437ee10fd15 --- /dev/null +++ b/tests/source/skip_macro_invocations/all.rs @@ -0,0 +1,11 @@ +// rustfmt-skip_macro_invocations: ["*"] + +// Should skip this invocation +items!( + const _: u8 = 0; +); + +// Should skip this invocation +renamed_items!( + const _: u8 = 0; +); diff --git a/tests/source/skip_macro_invocations/all_and_name.rs b/tests/source/skip_macro_invocations/all_and_name.rs new file mode 100644 index 0000000000000..1f6722344fe3b --- /dev/null +++ b/tests/source/skip_macro_invocations/all_and_name.rs @@ -0,0 +1,11 @@ +// rustfmt-skip_macro_invocations: ["*","items"] + +// Should skip this invocation +items!( + const _: u8 = 0; +); + +// Should also skip this invocation, as the wildcard covers it +renamed_items!( + const _: u8 = 0; +); diff --git a/tests/source/skip_macro_invocations/empty.rs b/tests/source/skip_macro_invocations/empty.rs new file mode 100644 index 0000000000000..f3dd89dc4db33 --- /dev/null +++ b/tests/source/skip_macro_invocations/empty.rs @@ -0,0 +1,11 @@ +// rustfmt-skip_macro_invocations: [] + +// Should not skip this invocation +items!( + const _: u8 = 0; +); + +// Should not skip this invocation +renamed_items!( + const _: u8 = 0; +); diff --git a/tests/source/skip_macro_invocations/name.rs b/tests/source/skip_macro_invocations/name.rs new file mode 100644 index 0000000000000..7fa5d3a6f715a --- /dev/null +++ b/tests/source/skip_macro_invocations/name.rs @@ -0,0 +1,11 @@ +// rustfmt-skip_macro_invocations: ["items"] + +// Should skip this invocation +items!( + const _: u8 = 0; +); + +// Should not skip this invocation +renamed_items!( + const _: u8 = 0; +); diff --git a/tests/source/skip_macro_invocations/name_unknown.rs b/tests/source/skip_macro_invocations/name_unknown.rs new file mode 100644 index 0000000000000..d56695325240d --- /dev/null +++ b/tests/source/skip_macro_invocations/name_unknown.rs @@ -0,0 +1,6 @@ +// rustfmt-skip_macro_invocations: ["unknown"] + +// Should not skip this invocation +items!( + const _: u8 = 0; +); diff --git a/tests/source/skip_macro_invocations/names.rs b/tests/source/skip_macro_invocations/names.rs new file mode 100644 index 0000000000000..a920381a4552c --- /dev/null +++ b/tests/source/skip_macro_invocations/names.rs @@ -0,0 +1,16 @@ +// rustfmt-skip_macro_invocations: ["foo","bar"] + +// Should skip this invocation +foo!( + const _: u8 = 0; +); + +// Should skip this invocation +bar!( + const _: u8 = 0; +); + +// Should not skip this invocation +baz!( + const _: u8 = 0; +); diff --git a/tests/source/skip_macro_invocations/path_qualified_invocation_mismatch.rs b/tests/source/skip_macro_invocations/path_qualified_invocation_mismatch.rs new file mode 100644 index 0000000000000..61296869a5065 --- /dev/null +++ b/tests/source/skip_macro_invocations/path_qualified_invocation_mismatch.rs @@ -0,0 +1,6 @@ +// rustfmt-skip_macro_invocations: ["items"] + +// Should not skip this invocation +self::items!( + const _: u8 = 0; +); diff --git a/tests/source/skip_macro_invocations/path_qualified_match.rs b/tests/source/skip_macro_invocations/path_qualified_match.rs new file mode 100644 index 0000000000000..9398918a9e11e --- /dev/null +++ b/tests/source/skip_macro_invocations/path_qualified_match.rs @@ -0,0 +1,6 @@ +// rustfmt-skip_macro_invocations: ["self::items"] + +// Should skip this invocation +self::items!( + const _: u8 = 0; +); diff --git a/tests/source/skip_macro_invocations/path_qualified_name_mismatch.rs b/tests/source/skip_macro_invocations/path_qualified_name_mismatch.rs new file mode 100644 index 0000000000000..4e3eb542dbea4 --- /dev/null +++ b/tests/source/skip_macro_invocations/path_qualified_name_mismatch.rs @@ -0,0 +1,6 @@ +// rustfmt-skip_macro_invocations: ["self::items"] + +// Should not skip this invocation +items!( + const _: u8 = 0; +); diff --git a/tests/source/skip_macro_invocations/use_alias_examples.rs b/tests/source/skip_macro_invocations/use_alias_examples.rs new file mode 100644 index 0000000000000..43cb8015de58a --- /dev/null +++ b/tests/source/skip_macro_invocations/use_alias_examples.rs @@ -0,0 +1,32 @@ +// rustfmt-skip_macro_invocations: ["aaa","ccc"] + +// These tests demonstrate a realistic use case with use aliases. +// The use statements should not impact functionality in any way. + +use crate::{aaa, bbb, ddd}; + +// No use alias, invocation in list +// Should skip this invocation +aaa!( + const _: u8 = 0; +); + +// Use alias, invocation in list +// Should skip this invocation +use crate::bbb as ccc; +ccc!( + const _: u8 = 0; +); + +// Use alias, invocation not in list +// Should not skip this invocation +use crate::ddd as eee; +eee!( + const _: u8 = 0; +); + +// No use alias, invocation not in list +// Should not skip this invocation +fff!( + const _: u8 = 0; +); diff --git a/tests/source/tuple.rs b/tests/source/tuple.rs index 9a0f979fbca38..5189a7454f3a7 100644 --- a/tests/source/tuple.rs +++ b/tests/source/tuple.rs @@ -1,4 +1,4 @@ -// Test tuple litterals +// Test tuple literals fn foo() { let a = (a, a, a, a, a); diff --git a/tests/source/wrap_comments_should_not_imply_format_doc_comments.rs b/tests/source/wrap_comments_should_not_imply_format_doc_comments.rs index 78b3ce146f289..56064e4a4cccf 100644 --- a/tests/source/wrap_comments_should_not_imply_format_doc_comments.rs +++ b/tests/source/wrap_comments_should_not_imply_format_doc_comments.rs @@ -11,6 +11,6 @@ /// fn foo() {} -/// A long commment for wrapping +/// A long comment for wrapping /// This is a long long long long long long long long long long long long long long long long long long long long sentence. fn bar() {} diff --git a/tests/target/cfg_if/detect/arch/x86.rs b/tests/target/cfg_if/detect/arch/x86.rs index 02d5eed1c2923..47210cae2aaa0 100644 --- a/tests/target/cfg_if/detect/arch/x86.rs +++ b/tests/target/cfg_if/detect/arch/x86.rs @@ -314,7 +314,7 @@ pub enum Feature { tbm, /// POPCNT (Population Count) popcnt, - /// FXSR (Floating-point context fast save and restor) + /// FXSR (Floating-point context fast save and restore) fxsr, /// XSAVE (Save Processor Extended States) xsave, diff --git a/tests/target/comments_unicode.rs b/tests/target/comments_unicode.rs new file mode 100644 index 0000000000000..3e1b6b0a28fe4 --- /dev/null +++ b/tests/target/comments_unicode.rs @@ -0,0 +1,140 @@ +impl Default for WhitespaceCharacters { + fn default() -> Self { + Self { + space: '·', // U+00B7 + nbsp: '⍽', // U+237D + tab: '→', // U+2192 + newline: '⏎', // U+23CE + } + } +} + +const RAINBOWS: &[&str] = &[ + "rаinЬοѡ", // hue: 0 + "raіnЬοw", // hue: 2 + "rаіɴЬow", // hue: 2 + "raіɴЬoѡ", // hue: 8 + "ʀainЬow", // hue: 8 + "ʀaіɴboѡ", // hue: 8 + "ʀаіnbοw", // hue: 11 + "rainЬoѡ", // hue: 14 + "raіɴbow", // hue: 14 + "rаiɴЬow", // hue: 20 + "raіnЬow", // hue: 26 + "ʀaiɴbοw", // hue: 32 + "raіɴboѡ", // hue: 35 + "rаiɴbow", // hue: 35 + "rаіnbοw", // hue: 38 + "rаinЬow", // hue: 47 + "ʀaіnboѡ", // hue: 47 + "ʀaіnЬoѡ", // hue: 47 + "ʀаіɴbοw", // hue: 53 + "ʀaіnЬοѡ", // hue: 57 + "raiɴЬoѡ", // hue: 68 + "ʀainbοѡ", // hue: 68 + "ʀаinboѡ", // hue: 68 + "ʀаiɴbοw", // hue: 68 + "ʀаіnbow", // hue: 68 + "rаіnЬοѡ", // hue: 69 + "ʀainЬοw", // hue: 71 + "raiɴbow", // hue: 73 + "raіnЬoѡ", // hue: 74 + "rаіɴbοw", // hue: 77 + "raіnЬοѡ", // hue: 81 + "raiɴЬow", // hue: 83 + "ʀainbοw", // hue: 83 + "ʀаinbow", // hue: 83 + "ʀаiɴbοѡ", // hue: 83 + "ʀаіnboѡ", // hue: 83 + "ʀаіɴЬοѡ", // hue: 84 + "rainЬow", // hue: 85 + "ʀаiɴЬοw", // hue: 86 + "ʀаіnbοѡ", // hue: 89 + "ʀаіnЬοw", // hue: 92 + "rаiɴbοw", // hue: 95 + "ʀаіɴbοѡ", // hue: 98 + "ʀаiɴЬοѡ", // hue: 99 + "raіnbοw", // hue: 101 + "ʀаіɴЬοw", // hue: 101 + "ʀaiɴboѡ", // hue: 104 + "ʀаinbοѡ", // hue: 104 + "rаiɴbοѡ", // hue: 107 + "ʀаinЬοw", // hue: 107 + "rаiɴЬοw", // hue: 110 + "rаіnboѡ", // hue: 110 + "rаіnbοѡ", // hue: 113 + "ʀainЬοѡ", // hue: 114 + "rаіnЬοw", // hue: 116 + "ʀaіɴЬow", // hue: 116 + "rаinbοw", // hue: 122 + "ʀаіɴboѡ", // hue: 125 + "rаinbοѡ", // hue: 131 + "rainbow", // hue: 134 + "rаinЬοw", // hue: 134 + "ʀаiɴboѡ", // hue: 140 + "rainЬοѡ", // hue: 141 + "raіɴЬow", // hue: 143 + "ʀainЬoѡ", // hue: 143 + "ʀaіɴbow", // hue: 143 + "ʀainbow", // hue: 148 + "rаіɴboѡ", // hue: 149 + "ʀainboѡ", // hue: 155 + "ʀaіnbow", // hue: 155 + "ʀaіnЬow", // hue: 155 + "raiɴbοw", // hue: 158 + "ʀаiɴЬoѡ", // hue: 158 + "rainbοw", // hue: 160 + "rаinbow", // hue: 160 + "ʀaіɴbοѡ", // hue: 164 + "ʀаiɴbow", // hue: 164 + "ʀаіnЬoѡ", // hue: 164 + "ʀaiɴЬοѡ", // hue: 165 + "rаiɴboѡ", // hue: 167 + "ʀaіɴЬοw", // hue: 167 + "ʀaіɴЬοѡ", // hue: 171 + "raіnboѡ", // hue: 173 + "ʀаіɴЬoѡ", // hue: 173 + "rаіɴbοѡ", // hue: 176 + "ʀаinЬow", // hue: 176 + "rаiɴЬοѡ", // hue: 177 + "rаіɴЬοw", // hue: 179 + "ʀаinЬoѡ", // hue: 179 + "ʀаіɴbow", // hue: 179 + "rаiɴЬoѡ", // hue: 182 + "raіɴbοѡ", // hue: 188 + "rаіnЬoѡ", // hue: 188 + "raiɴЬοѡ", // hue: 189 + "raіɴЬοw", // hue: 191 + "ʀaіɴbοw", // hue: 191 + "ʀаіnЬow", // hue: 191 + "rainbοѡ", // hue: 194 + "rаinboѡ", // hue: 194 + "rаіnbow", // hue: 194 + "rainЬοw", // hue: 197 + "rаinЬoѡ", // hue: 206 + "rаіɴbow", // hue: 206 + "rаіɴЬοѡ", // hue: 210 + "ʀaiɴЬow", // hue: 212 + "raіɴbοw", // hue: 218 + "rаіnЬow", // hue: 218 + "ʀaiɴbοѡ", // hue: 221 + "ʀaiɴЬοw", // hue: 224 + "ʀaіnbοѡ", // hue: 227 + "raiɴboѡ", // hue: 230 + "ʀaіnbοw", // hue: 230 + "ʀaіnЬοw", // hue: 230 + "ʀаinЬοѡ", // hue: 231 + "rainboѡ", // hue: 232 + "raіnbow", // hue: 232 + "ʀаіɴЬow", // hue: 233 + "ʀaіɴЬoѡ", // hue: 239 + "ʀаіnЬοѡ", // hue: 246 + "raiɴbοѡ", // hue: 248 + "ʀаiɴЬow", // hue: 248 + "raіɴЬοѡ", // hue: 249 + "raiɴЬοw", // hue: 251 + "rаіɴЬoѡ", // hue: 251 + "ʀaiɴbow", // hue: 251 + "ʀаinbοw", // hue: 251 + "raіnbοѡ", // hue: 254 +]; diff --git a/tests/target/configs/fn_args_layout/compressed.rs b/tests/target/configs/fn_params_layout/compressed.rs similarity index 92% rename from tests/target/configs/fn_args_layout/compressed.rs rename to tests/target/configs/fn_params_layout/compressed.rs index f189446e25d44..ff32f0f1d5868 100644 --- a/tests/target/configs/fn_args_layout/compressed.rs +++ b/tests/target/configs/fn_params_layout/compressed.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Compressed +// rustfmt-fn_params_layout: Compressed // Function arguments density trait Lorem { diff --git a/tests/target/configs/fn_args_layout/tall.rs b/tests/target/configs/fn_params_layout/tall.rs similarity index 94% rename from tests/target/configs/fn_args_layout/tall.rs rename to tests/target/configs/fn_params_layout/tall.rs index 20f308973acbc..25a86799af0d8 100644 --- a/tests/target/configs/fn_args_layout/tall.rs +++ b/tests/target/configs/fn_params_layout/tall.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Tall +// rustfmt-fn_params_layout: Tall // Function arguments density trait Lorem { diff --git a/tests/target/configs/fn_args_layout/vertical.rs b/tests/target/configs/fn_params_layout/vertical.rs similarity index 94% rename from tests/target/configs/fn_args_layout/vertical.rs rename to tests/target/configs/fn_params_layout/vertical.rs index 6c695a75df9a2..7a0e42415f3b9 100644 --- a/tests/target/configs/fn_args_layout/vertical.rs +++ b/tests/target/configs/fn_params_layout/vertical.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Vertical +// rustfmt-fn_params_layout: Vertical // Function arguments density trait Lorem { diff --git a/tests/target/enum.rs b/tests/target/enum.rs index 9a25126b44ecb..70fc8ab376ccd 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -43,7 +43,7 @@ enum StructLikeVariants { x: i32, // Test comment // Pre-comment #[Attr50] - y: SomeType, // Aanother Comment + y: SomeType, // Another Comment }, SL { a: A, diff --git a/tests/target/fn-custom-7.rs b/tests/target/fn-custom-7.rs index 2c20ac5a75249..f6a1a90c3fc68 100644 --- a/tests/target/fn-custom-7.rs +++ b/tests/target/fn-custom-7.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-fn_args_layout: Vertical +// rustfmt-fn_params_layout: Vertical // rustfmt-brace_style: AlwaysNextLine // Case with only one variable. diff --git a/tests/target/fn-custom.rs b/tests/target/fn-custom.rs index 2eb2a973d243d..506d9de34370b 100644 --- a/tests/target/fn-custom.rs +++ b/tests/target/fn-custom.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Compressed +// rustfmt-fn_params_layout: Compressed // Test some of the ways function signatures can be customised. // Test compressed layout of args. diff --git a/tests/target/fn_args_layout-vertical.rs b/tests/target/fn_args_layout-vertical.rs index da0ac981d872d..bfeca15c967ed 100644 --- a/tests/target/fn_args_layout-vertical.rs +++ b/tests/target/fn_args_layout-vertical.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Vertical +// rustfmt-fn_params_layout: Vertical // Empty list should stay on one line. fn do_bar() -> u8 { diff --git a/tests/target/issue-2534/format_macro_matchers_false.rs b/tests/target/issue-2534/format_macro_matchers_false.rs new file mode 100644 index 0000000000000..2038ed7f1d014 --- /dev/null +++ b/tests/target/issue-2534/format_macro_matchers_false.rs @@ -0,0 +1,6 @@ +// rustfmt-format_macro_matchers: false + +macro_rules! foo { + ($a:ident : $b:ty) => {}; + ($a:ident $b:ident $c:ident) => {}; +} diff --git a/tests/target/issue-2534/format_macro_matchers_true.rs b/tests/target/issue-2534/format_macro_matchers_true.rs new file mode 100644 index 0000000000000..01d939add4dc2 --- /dev/null +++ b/tests/target/issue-2534/format_macro_matchers_true.rs @@ -0,0 +1,6 @@ +// rustfmt-format_macro_matchers: true + +macro_rules! foo { + ($a:ident : $b:ty) => {}; + ($a:ident $b:ident $c:ident) => {}; +} diff --git a/tests/target/issue-3987/format_macro_bodies_false.rs b/tests/target/issue-3987/format_macro_bodies_false.rs new file mode 100644 index 0000000000000..1352b762e4509 --- /dev/null +++ b/tests/target/issue-3987/format_macro_bodies_false.rs @@ -0,0 +1,26 @@ +// rustfmt-format_macro_bodies: false + +// with comments +macro_rules! macros { + () => {{ + Struct { + field: ( + 42 + //comment 1 + 42 + //comment 2 + ), + }; + }}; +} + +// without comments +macro_rules! macros { + () => {{ + Struct { + field: ( + 42 + + 42 + ), + }; + }}; +} diff --git a/tests/target/issue-3987/format_macro_bodies_true.rs b/tests/target/issue-3987/format_macro_bodies_true.rs new file mode 100644 index 0000000000000..88d57159c859f --- /dev/null +++ b/tests/target/issue-3987/format_macro_bodies_true.rs @@ -0,0 +1,21 @@ +// rustfmt-format_macro_bodies: true + +// with comments +macro_rules! macros { + () => {{ + Struct { + field: ( + 42 + //comment 1 + 42 + //comment 2 + ), + }; + }}; +} + +// without comments +macro_rules! macros { + () => {{ + Struct { field: (42 + 42) }; + }}; +} diff --git a/tests/target/issue-4643.rs b/tests/target/issue-4643.rs new file mode 100644 index 0000000000000..ef99e4db382cb --- /dev/null +++ b/tests/target/issue-4643.rs @@ -0,0 +1,19 @@ +// output doesn't get corrupted when using comments within generic type parameters of a trait + +pub trait Something< + A, + // some comment + B, + C, +> +{ + fn a(&self, x: A) -> i32; + fn b(&self, x: B) -> i32; + fn c(&self, x: C) -> i32; +} + +pub trait SomethingElse { + fn a(&self, x: A) -> i32; + fn b(&self, x: B) -> i32; + fn c(&self, x: C) -> i32; +} diff --git a/tests/target/issue-4689/one.rs b/tests/target/issue-4689/one.rs new file mode 100644 index 0000000000000..7735e34f3b5ed --- /dev/null +++ b/tests/target/issue-4689/one.rs @@ -0,0 +1,150 @@ +// rustfmt-version: One + +// Based on the issue description +pub trait PrettyPrinter<'tcx>: + Printer< + 'tcx, + Error = fmt::Error, + Path = Self, + Region = Self, + Type = Self, + DynExistential = Self, + Const = Self, +> +{ + // +} +pub trait PrettyPrinter<'tcx>: + Printer< + 'tcx, + Error = fmt::Error, + Path = Self, + Region = Self, + Type = Self, + DynExistential = Self, + Const = Self, + > + fmt::Write +{ + // +} +pub trait PrettyPrinter<'tcx>: + Printer< + 'tcx, + Error = fmt::Error, + Path = Self, + Region = Self, + Type = Self, + DynExistential = Self, + Const = Self, + > + fmt::Write1 + + fmt::Write2 +{ + // +} +pub trait PrettyPrinter<'tcx>: + fmt::Write + + Printer< + 'tcx, + Error = fmt::Error, + Path = Self, + Region = Self, + Type = Self, + DynExistential = Self, + Const = Self, + > +{ + // +} +pub trait PrettyPrinter<'tcx>: + fmt::Write + + Printer1< + 'tcx, + Error = fmt::Error, + Path = Self, + Region = Self, + Type = Self, + DynExistential = Self, + Const = Self, + > + Printer2< + 'tcx, + Error = fmt::Error, + Path = Self, + Region = Self, + Type = Self, + DynExistential = Self, + Const = Self, + > +{ + // +} + +// Some test cases to ensure other cases formatting were not changed +fn f() -> Box< + FnMut() -> Thing< + WithType = LongItemName, + Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger, + >, +> { +} +fn f() -> Box< + FnMut() -> Thing< + WithType = LongItemName, + Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger, + > + fmt::Write1 + + fmt::Write2, +> { +} + +fn foo(foo2: F) +where + F: Fn( + // this comment is deleted + ), +{ +} +fn foo(foo2: F) +where + F: Fn( + // this comment is deleted + ) + fmt::Write, +{ +} + +fn elaborate_bounds(mut mk_cand: F) +where + F: FnMut( + &mut ProbeContext, + ty::PolyTraitRefffffffffffffffffffffffffffffffff, + tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem, + ), +{ +} +fn elaborate_bounds(mut mk_cand: F) +where + F: FnMut( + &mut ProbeContext, + ty::PolyTraitRefffffffffffffffffffffffffffffffff, + tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem, + ) + fmt::Write, +{ +} + +fn build_sorted_static_get_entry_names( + mut entries: entryyyyyyyy, +) -> (impl Fn( + AlphabeticalTraversal, + Seconddddddddddddddddddddddddddddddddddd, +) -> Parammmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm + + Sendddddddddddddddddddddddddddddddddddddddddddd) { +} + +pub trait SomeTrait: + Cloneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee + + Eqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq +{ +} + +trait B = where + for<'b> &'b Self: Send + + Cloneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee + + Copyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy; diff --git a/tests/target/issue-4689/two.rs b/tests/target/issue-4689/two.rs new file mode 100644 index 0000000000000..e3b5cd22810ba --- /dev/null +++ b/tests/target/issue-4689/two.rs @@ -0,0 +1,152 @@ +// rustfmt-version: Two + +// Based on the issue description +pub trait PrettyPrinter<'tcx>: + Printer< + 'tcx, + Error = fmt::Error, + Path = Self, + Region = Self, + Type = Self, + DynExistential = Self, + Const = Self, + > +{ + // +} +pub trait PrettyPrinter<'tcx>: + Printer< + 'tcx, + Error = fmt::Error, + Path = Self, + Region = Self, + Type = Self, + DynExistential = Self, + Const = Self, + > + fmt::Write +{ + // +} +pub trait PrettyPrinter<'tcx>: + Printer< + 'tcx, + Error = fmt::Error, + Path = Self, + Region = Self, + Type = Self, + DynExistential = Self, + Const = Self, + > + fmt::Write1 + + fmt::Write2 +{ + // +} +pub trait PrettyPrinter<'tcx>: + fmt::Write + + Printer< + 'tcx, + Error = fmt::Error, + Path = Self, + Region = Self, + Type = Self, + DynExistential = Self, + Const = Self, + > +{ + // +} +pub trait PrettyPrinter<'tcx>: + fmt::Write + + Printer1< + 'tcx, + Error = fmt::Error, + Path = Self, + Region = Self, + Type = Self, + DynExistential = Self, + Const = Self, + > + Printer2< + 'tcx, + Error = fmt::Error, + Path = Self, + Region = Self, + Type = Self, + DynExistential = Self, + Const = Self, + > +{ + // +} + +// Some test cases to ensure other cases formatting were not changed +fn f() -> Box< + FnMut() -> Thing< + WithType = LongItemName, + Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger, + >, +> { +} +fn f() -> Box< + FnMut() -> Thing< + WithType = LongItemName, + Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger, + > + fmt::Write1 + + fmt::Write2, +> { +} + +fn foo(foo2: F) +where + F: Fn( + // this comment is deleted + ), +{ +} +fn foo(foo2: F) +where + F: Fn( + // this comment is deleted + ) + fmt::Write, +{ +} + +fn elaborate_bounds(mut mk_cand: F) +where + F: FnMut( + &mut ProbeContext, + ty::PolyTraitRefffffffffffffffffffffffffffffffff, + tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem, + ), +{ +} +fn elaborate_bounds(mut mk_cand: F) +where + F: FnMut( + &mut ProbeContext, + ty::PolyTraitRefffffffffffffffffffffffffffffffff, + tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem, + ) + fmt::Write, +{ +} + +fn build_sorted_static_get_entry_names( + mut entries: entryyyyyyyy, +) -> ( + impl Fn( + AlphabeticalTraversal, + Seconddddddddddddddddddddddddddddddddddd, + ) -> Parammmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm + + Sendddddddddddddddddddddddddddddddddddddddddddd +) { +} + +pub trait SomeTrait: + Cloneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee + + Eqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq +{ +} + +trait B = where + for<'b> &'b Self: Send + + Cloneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee + + Copyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy; diff --git a/tests/target/issue-4791/issue_4928.rs b/tests/target/issue-4791/issue_4928.rs index 588656b535fa1..29f6bda90631b 100644 --- a/tests/target/issue-4791/issue_4928.rs +++ b/tests/target/issue-4791/issue_4928.rs @@ -1,7 +1,7 @@ // rustfmt-brace_style: SameLineWhere // rustfmt-comment_width: 100 // rustfmt-edition: 2018 -// rustfmt-fn_args_layout: Compressed +// rustfmt-fn_params_layout: Compressed // rustfmt-hard_tabs: false // rustfmt-match_block_trailing_comma: true // rustfmt-max_width: 100 diff --git a/tests/target/issue-5358.rs b/tests/target/issue-5358.rs new file mode 100644 index 0000000000000..d4bf4909ad76f --- /dev/null +++ b/tests/target/issue-5358.rs @@ -0,0 +1,4 @@ +// Test /* comment */ inside trait generics does not get duplicated. +trait Test {} + +trait TestTwo {} diff --git a/tests/target/issue_1306.rs b/tests/target/issue_1306.rs new file mode 100644 index 0000000000000..6bb514cdfe550 --- /dev/null +++ b/tests/target/issue_1306.rs @@ -0,0 +1,33 @@ +// rustfmt-max_width: 160 +// rustfmt-fn_call_width: 96 +// rustfmt-fn_args_layout: Compressed +// rustfmt-trailing_comma: Always +// rustfmt-wrap_comments: true + +fn foo() { + for elem in try!(gen_epub_book::ops::parse_descriptor_file( + &mut try!(File::open(&opts.source_file.1).map_err(|_| { + gen_epub_book::Error::Io { + desc: "input file", + op: "open", + more: None, + } + })), + "input file" + )) { + println!("{}", elem); + } +} + +fn write_content() { + io::copy( + try!(File::open(in_f).map_err(|_| { + Error::Io { + desc: "Content", + op: "open", + more: None, + } + })), + w, + ); +} diff --git a/tests/target/issue_3033.rs b/tests/target/issue_3033.rs new file mode 100644 index 0000000000000..e12249a6da6f3 --- /dev/null +++ b/tests/target/issue_3033.rs @@ -0,0 +1,2 @@ +use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerBinding:: + BluetoothRemoteGATTServerMethods; diff --git a/tests/target/issue_3245.rs b/tests/target/issue_3245.rs new file mode 100644 index 0000000000000..8f442f1181a59 --- /dev/null +++ b/tests/target/issue_3245.rs @@ -0,0 +1,4 @@ +fn main() { + let x = 1; + let y = 3; +} diff --git a/tests/target/issue_3561.rs b/tests/target/issue_3561.rs new file mode 100644 index 0000000000000..846a14d86a5ff --- /dev/null +++ b/tests/target/issue_3561.rs @@ -0,0 +1,7 @@ +fn main() { + 7 +} + +fn main() { + 7 +} diff --git a/tests/target/issue_4350.rs b/tests/target/issue_4350.rs new file mode 100644 index 0000000000000..a94c5c32188d2 --- /dev/null +++ b/tests/target/issue_4350.rs @@ -0,0 +1,13 @@ +//rustfmt-format_macro_bodies: true + +macro_rules! mto_text_left { + ($buf:ident, $n:ident, $pos:ident, $state:ident) => {{ + let cursor = loop { + state = match iter.next() { + None if $pos == DP::Start => break last_char_idx($buf), + None /*some comment */ => break 0, + }; + }; + Ok(saturate_cursor($buf, cursor)) + }}; +} diff --git a/tests/target/issue_5668.rs b/tests/target/issue_5668.rs new file mode 100644 index 0000000000000..bbd9a530b81c0 --- /dev/null +++ b/tests/target/issue_5668.rs @@ -0,0 +1,8 @@ +type Foo = impl Send; +struct Struct< + const C: usize = { + let _: Foo = (); + //~^ ERROR: mismatched types + 0 + }, +>; diff --git a/tests/target/skip_macro_invocations/all.rs b/tests/target/skip_macro_invocations/all.rs new file mode 100644 index 0000000000000..d0437ee10fd15 --- /dev/null +++ b/tests/target/skip_macro_invocations/all.rs @@ -0,0 +1,11 @@ +// rustfmt-skip_macro_invocations: ["*"] + +// Should skip this invocation +items!( + const _: u8 = 0; +); + +// Should skip this invocation +renamed_items!( + const _: u8 = 0; +); diff --git a/tests/target/skip_macro_invocations/all_and_name.rs b/tests/target/skip_macro_invocations/all_and_name.rs new file mode 100644 index 0000000000000..1f6722344fe3b --- /dev/null +++ b/tests/target/skip_macro_invocations/all_and_name.rs @@ -0,0 +1,11 @@ +// rustfmt-skip_macro_invocations: ["*","items"] + +// Should skip this invocation +items!( + const _: u8 = 0; +); + +// Should also skip this invocation, as the wildcard covers it +renamed_items!( + const _: u8 = 0; +); diff --git a/tests/target/skip_macro_invocations/empty.rs b/tests/target/skip_macro_invocations/empty.rs new file mode 100644 index 0000000000000..4a398cc59c6ee --- /dev/null +++ b/tests/target/skip_macro_invocations/empty.rs @@ -0,0 +1,11 @@ +// rustfmt-skip_macro_invocations: [] + +// Should not skip this invocation +items!( + const _: u8 = 0; +); + +// Should not skip this invocation +renamed_items!( + const _: u8 = 0; +); diff --git a/tests/target/skip_macro_invocations/name.rs b/tests/target/skip_macro_invocations/name.rs new file mode 100644 index 0000000000000..c4d577269c6f0 --- /dev/null +++ b/tests/target/skip_macro_invocations/name.rs @@ -0,0 +1,11 @@ +// rustfmt-skip_macro_invocations: ["items"] + +// Should skip this invocation +items!( + const _: u8 = 0; +); + +// Should not skip this invocation +renamed_items!( + const _: u8 = 0; +); diff --git a/tests/target/skip_macro_invocations/name_unknown.rs b/tests/target/skip_macro_invocations/name_unknown.rs new file mode 100644 index 0000000000000..7ab1440395c32 --- /dev/null +++ b/tests/target/skip_macro_invocations/name_unknown.rs @@ -0,0 +1,6 @@ +// rustfmt-skip_macro_invocations: ["unknown"] + +// Should not skip this invocation +items!( + const _: u8 = 0; +); diff --git a/tests/target/skip_macro_invocations/names.rs b/tests/target/skip_macro_invocations/names.rs new file mode 100644 index 0000000000000..c6b41ff93d79d --- /dev/null +++ b/tests/target/skip_macro_invocations/names.rs @@ -0,0 +1,16 @@ +// rustfmt-skip_macro_invocations: ["foo","bar"] + +// Should skip this invocation +foo!( + const _: u8 = 0; +); + +// Should skip this invocation +bar!( + const _: u8 = 0; +); + +// Should not skip this invocation +baz!( + const _: u8 = 0; +); diff --git a/tests/target/skip_macro_invocations/path_qualified_invocation_mismatch.rs b/tests/target/skip_macro_invocations/path_qualified_invocation_mismatch.rs new file mode 100644 index 0000000000000..6e372c726952a --- /dev/null +++ b/tests/target/skip_macro_invocations/path_qualified_invocation_mismatch.rs @@ -0,0 +1,6 @@ +// rustfmt-skip_macro_invocations: ["items"] + +// Should not skip this invocation +self::items!( + const _: u8 = 0; +); diff --git a/tests/target/skip_macro_invocations/path_qualified_match.rs b/tests/target/skip_macro_invocations/path_qualified_match.rs new file mode 100644 index 0000000000000..9398918a9e11e --- /dev/null +++ b/tests/target/skip_macro_invocations/path_qualified_match.rs @@ -0,0 +1,6 @@ +// rustfmt-skip_macro_invocations: ["self::items"] + +// Should skip this invocation +self::items!( + const _: u8 = 0; +); diff --git a/tests/target/skip_macro_invocations/path_qualified_name_mismatch.rs b/tests/target/skip_macro_invocations/path_qualified_name_mismatch.rs new file mode 100644 index 0000000000000..aa57a2a655c4a --- /dev/null +++ b/tests/target/skip_macro_invocations/path_qualified_name_mismatch.rs @@ -0,0 +1,6 @@ +// rustfmt-skip_macro_invocations: ["self::items"] + +// Should not skip this invocation +items!( + const _: u8 = 0; +); diff --git a/tests/target/skip_macro_invocations/use_alias_examples.rs b/tests/target/skip_macro_invocations/use_alias_examples.rs new file mode 100644 index 0000000000000..799dd8c08af15 --- /dev/null +++ b/tests/target/skip_macro_invocations/use_alias_examples.rs @@ -0,0 +1,32 @@ +// rustfmt-skip_macro_invocations: ["aaa","ccc"] + +// These tests demonstrate a realistic use case with use aliases. +// The use statements should not impact functionality in any way. + +use crate::{aaa, bbb, ddd}; + +// No use alias, invocation in list +// Should skip this invocation +aaa!( + const _: u8 = 0; +); + +// Use alias, invocation in list +// Should skip this invocation +use crate::bbb as ccc; +ccc!( + const _: u8 = 0; +); + +// Use alias, invocation not in list +// Should not skip this invocation +use crate::ddd as eee; +eee!( + const _: u8 = 0; +); + +// No use alias, invocation not in list +// Should not skip this invocation +fff!( + const _: u8 = 0; +); diff --git a/tests/target/tuple.rs b/tests/target/tuple.rs index 68bb2f3bc2850..24fcf8cfd7cf3 100644 --- a/tests/target/tuple.rs +++ b/tests/target/tuple.rs @@ -1,4 +1,4 @@ -// Test tuple litterals +// Test tuple literals fn foo() { let a = (a, a, a, a, a); diff --git a/tests/target/wrap_comments_should_not_imply_format_doc_comments.rs b/tests/target/wrap_comments_should_not_imply_format_doc_comments.rs index d61d4d7c216a3..6ccecc7e0bbe6 100644 --- a/tests/target/wrap_comments_should_not_imply_format_doc_comments.rs +++ b/tests/target/wrap_comments_should_not_imply_format_doc_comments.rs @@ -10,7 +10,7 @@ /// ``` fn foo() {} -/// A long commment for wrapping +/// A long comment for wrapping /// This is a long long long long long long long long long long long long long /// long long long long long long long sentence. fn bar() {} From 567bd977230f3fe64781e9946b9f692919d30d38 Mon Sep 17 00:00:00 2001 From: Arthur Carcano <53921575+krtab@users.noreply.github.com> Date: Sat, 28 Jan 2023 22:16:46 +0100 Subject: [PATCH 05/58] Document which comments are excluded from wrapping (#5637) * Document which comments are excluded from wrapping Cf: https://github.com/rust-lang/rustfmt/issues/5634 * Add examples in wrap_commments doc * fix failling tests --- Configurations.md | 20 ++++++++++++++++++++ src/comment.rs | 2 ++ 2 files changed, 22 insertions(+) diff --git a/Configurations.md b/Configurations.md index 49e7e4e64892a..ac638ff91e6d4 100644 --- a/Configurations.md +++ b/Configurations.md @@ -2997,6 +2997,10 @@ See also [`brace_style`](#brace_style), [`control_brace_style`](#control_brace_s Break comments to fit on the line +Note that no wrapping will happen if: +1. The comment is the start of a markdown header doc comment +2. An URL was found in the comment + - **Default value**: `false` - **Possible values**: `true`, `false` - **Stable**: No (tracking issue: [#3347](https://github.com/rust-lang/rustfmt/issues/3347)) @@ -3011,6 +3015,11 @@ Break comments to fit on the line // commodo consequat. // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + +// Information on the lorem ipsum can be found at the following url: https://en.wikipedia.org/wiki/Lorem_ipsum. Its text is: lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + +/// # This doc comment is a very long header (it starts with a '#'). Had it not been a header it would have been wrapped. But because it is a header, it will not be. That is because wrapping a markdown header breaks it. +struct Foo {} ``` #### `true`: @@ -3021,6 +3030,17 @@ Break comments to fit on the line // magna aliqua. Ut enim ad minim veniam, quis nostrud // exercitation ullamco laboris nisi ut aliquip ex ea // commodo consequat. + +// Lorem ipsum dolor sit amet, consectetur adipiscing elit, +// sed do eiusmod tempor incididunt ut labore et dolore +// magna aliqua. Ut enim ad minim veniam, quis nostrud +// exercitation ullamco laboris nisi ut aliquip ex ea +// commodo consequat. + +// Information on the lorem ipsum can be found at the following url: https://en.wikipedia.org/wiki/Lorem_ipsum. Its text is: lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + +/// # This doc comment is a very long header (it starts with a '#'). Had it not been a header it would have been wrapped. But because it is a header, it will not be. That is because wrapping a markdown header breaks it. +struct Foo {} ``` # Internal Options diff --git a/src/comment.rs b/src/comment.rs index 4d565afc1e026..261fa5e93d843 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -801,6 +801,8 @@ impl<'a> CommentRewrite<'a> { // 2) The comment is not the start of a markdown header doc comment // 3) The comment width exceeds the shape's width // 4) No URLS were found in the comment + // If this changes, the documentation in ../Configurations.md#wrap_comments + // should be changed accordingly. let should_wrap_comment = self.fmt.config.wrap_comments() && !is_markdown_header_doc_comment && unicode_str_width(line) > self.fmt.shape.width From bcfc57ec8a8fb1120b9b447df21cd07aac6c228d Mon Sep 17 00:00:00 2001 From: amab8901 <83634595+amab8901@users.noreply.github.com> Date: Sat, 28 Jan 2023 22:18:52 +0100 Subject: [PATCH 06/58] added tests (#5619) --- tests/source/issue-5586.rs | 164 ++++++++++++++++++++++++++++++++++ tests/target/issue-5586.rs | 177 +++++++++++++++++++++++++++++++++++++ 2 files changed, 341 insertions(+) create mode 100644 tests/source/issue-5586.rs create mode 100644 tests/target/issue-5586.rs diff --git a/tests/source/issue-5586.rs b/tests/source/issue-5586.rs new file mode 100644 index 0000000000000..9cf6c1d58ddc6 --- /dev/null +++ b/tests/source/issue-5586.rs @@ -0,0 +1,164 @@ +// rustfmt-version: Two +fn main() { + // sample 1 + { + { + { + { + { + let push_ident = + if let Some(&node_id) = subgraph_nodes.get(pull_to_push_idx) { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." +); + send_ports[0].clone() + }; + } + } + } + } + } + + // sample 2 + { + { + { + { + { + let push_ident = if let Some(&node_id) = + subgraph_nodes.get(pull_to_push_idx) + { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + } + } + } + } + } + + // sample 3 + { + { + { + { + { + let push_ident = + if let Some(&node_id) = subgraph_nodes.get(pull_to_push_idx) { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + } + } + } + } + } + + // sample 4 + {{{{{ + let push_ident = + if let Some(&node_id) = subgraph_nodes.get(pull_to_push_idx) { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + }}}}} + + // sample 5 + { + { + { + { + { + let push_ident = + if let Some(&node_id) = subgraph_nodes.get(pull_to_push_idx) { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + } + } + } + } + } + + // sample 6 + { + { + { + { + { + let push_ident = if let Some(&node_id) = + subgraph_nodes.get(pull_to_push_idx) + { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + } + } + } + } + } + + // sample 7 + { + { + { + { + { + let push_ident = + if let Some(&node_id) = subgraph_nodes.get(pull_to_push_idx) { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + } + } + } + } + } +} diff --git a/tests/target/issue-5586.rs b/tests/target/issue-5586.rs new file mode 100644 index 0000000000000..7033ae975b3b5 --- /dev/null +++ b/tests/target/issue-5586.rs @@ -0,0 +1,177 @@ +// rustfmt-version: Two +fn main() { + // sample 1 + { + { + { + { + { + let push_ident = if let Some(&node_id) = + subgraph_nodes.get(pull_to_push_idx) + { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + } + } + } + } + } + + // sample 2 + { + { + { + { + { + let push_ident = if let Some(&node_id) = + subgraph_nodes.get(pull_to_push_idx) + { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + } + } + } + } + } + + // sample 3 + { + { + { + { + { + let push_ident = if let Some(&node_id) = + subgraph_nodes.get(pull_to_push_idx) + { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + } + } + } + } + } + + // sample 4 + { + { + { + { + { + let push_ident = if let Some(&node_id) = + subgraph_nodes.get(pull_to_push_idx) + { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + } + } + } + } + } + + // sample 5 + { + { + { + { + { + let push_ident = if let Some(&node_id) = + subgraph_nodes.get(pull_to_push_idx) + { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + } + } + } + } + } + + // sample 6 + { + { + { + { + { + let push_ident = if let Some(&node_id) = + subgraph_nodes.get(pull_to_push_idx) + { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + } + } + } + } + } + + // sample 7 + { + { + { + { + { + let push_ident = if let Some(&node_id) = + subgraph_nodes.get(pull_to_push_idx) + { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + } + } + } + } + } +} From b08130c59070bb9c95128341d712c0e02bba58d9 Mon Sep 17 00:00:00 2001 From: David Bar-On <61089727+davidBar-On@users.noreply.github.com> Date: Sun, 29 Jan 2023 20:55:14 +0200 Subject: [PATCH 07/58] Fix #5234 - handling of empty code block (#5601) --- src/comment.rs | 2 +- tests/source/issue-5234.rs | 51 ++++++++++++++++++++++++++++++++++++++ tests/target/issue-5234.rs | 47 +++++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 tests/source/issue-5234.rs create mode 100644 tests/target/issue-5234.rs diff --git a/src/comment.rs b/src/comment.rs index 261fa5e93d843..0677fdc2b8994 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -726,7 +726,7 @@ impl<'a> CommentRewrite<'a> { let code_block = match self.code_block_attr.as_ref().unwrap() { CodeBlockAttribute::Rust if self.fmt.config.format_code_in_doc_comments() - && !self.code_block_buffer.is_empty() => + && !self.code_block_buffer.trim().is_empty() => { let mut config = self.fmt.config.clone(); config.set().wrap_comments(false); diff --git a/tests/source/issue-5234.rs b/tests/source/issue-5234.rs new file mode 100644 index 0000000000000..67266f485d3bf --- /dev/null +++ b/tests/source/issue-5234.rs @@ -0,0 +1,51 @@ +// rustfmt-format_code_in_doc_comments: true + +/// ``` +/// ``` +fn foo() {} + +/// ``` +///Something +/// ``` +fn foo() {} + +/// ``` +/// +/// ``` +fn foo() {} + + +/// /// ``` +fn foo() {} + +/// /// ``` +/// ``` +/// +/// ``` +/// ``` +fn foo() {} + +fn foo() { +/// ``` +/// +/// ``` +struct bar {} +} + +/// ``` +/// fn com(){ +/// let i = 5; +/// +/// let j = 6; +/// } +/// ``` +fn foo() {} + +fn foo() { +/// ``` +///fn com(){ +///let i = 5; +///} +/// ``` +struct bar {} +} diff --git a/tests/target/issue-5234.rs b/tests/target/issue-5234.rs new file mode 100644 index 0000000000000..7ee9e46d1efa7 --- /dev/null +++ b/tests/target/issue-5234.rs @@ -0,0 +1,47 @@ +// rustfmt-format_code_in_doc_comments: true + +/// ``` +/// ``` +fn foo() {} + +/// ``` +/// Something +/// ``` +fn foo() {} + +/// ``` +/// ``` +fn foo() {} + +/// /// ``` +fn foo() {} + +/// /// ``` +/// ``` +/// ``` +/// ``` +fn foo() {} + +fn foo() { + /// ``` + /// ``` + struct bar {} +} + +/// ``` +/// fn com() { +/// let i = 5; +/// +/// let j = 6; +/// } +/// ``` +fn foo() {} + +fn foo() { + /// ``` + /// fn com() { + /// let i = 5; + /// } + /// ``` + struct bar {} +} From 61d82acf53c62d19d366c47bead15b8fc67028bc Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Sun, 29 Jan 2023 22:43:40 +0000 Subject: [PATCH 08/58] refactor: fix typo in comment (#5581) --- src/bin/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/main.rs b/src/bin/main.rs index be64559e87745..8f5d980f561de 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -75,7 +75,7 @@ pub enum OperationError { #[error("{0}")] IoError(IoError), /// Attempt to use --emit with a mode which is not currently - /// supported with stdandard input. + /// supported with standard input. #[error("Emit mode {0} not supported with standard output.")] StdinBadEmit(EmitMode), } From 9cc0af54070f023fb52961160157313a09c55fb8 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 30 Jan 2023 07:44:58 +0900 Subject: [PATCH 09/58] Remove old CI config (#5572) * Remove old CI config Signed-off-by: Yuki Okushi * Replace outdated badges Signed-off-by: Yuki Okushi --------- Signed-off-by: Yuki Okushi --- .editorconfig | 3 -- .travis.yml | 77 --------------------------------------------------- README.md | 6 ++-- 3 files changed, 2 insertions(+), 84 deletions(-) delete mode 100644 .travis.yml diff --git a/.editorconfig b/.editorconfig index 5bb92df3e0432..ed6894e5c273d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -21,6 +21,3 @@ indent_size = unset indent_style = unset trim_trailing_whitespace = unset insert_final_newline = unset - -[appveyor.yml] -end_of_line = unset diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index d699bd842eecc..0000000000000 --- a/.travis.yml +++ /dev/null @@ -1,77 +0,0 @@ -sudo: false -language: rust -rust: nightly -os: linux -cache: - directories: - - $HOME/.cargo - -addons: - apt: - packages: - - libcurl4-openssl-dev - - libelf-dev - - libdw-dev - -matrix: - include: - - env: DEPLOY=LINUX - - env: CFG_RELEASE_CHANNEL=beta - - os: osx - - env: INTEGRATION=bitflags - - env: INTEGRATION=chalk - - env: INTEGRATION=crater - - env: INTEGRATION=error-chain - - env: INTEGRATION=glob - - env: INTEGRATION=log - - env: INTEGRATION=mdbook - - env: INTEGRATION=packed_simd - - env: INTEGRATION=rust-semverver - - env: INTEGRATION=stdsimd TARGET=x86_64-unknown-linux-gnu - - env: INTEGRATION=tempdir - - env: INTEGRATION=futures-rs - allow_failures: - # Using old configuration option - - env: INTEGRATION=rand - # Doesn't build - keep this in allow_failures as it's fragile to breaking changes of rustc. - - env: INTEGRATION=rust-clippy - # Doesn't build - seems to be because of an option - - env: INTEGRATION=packed_simd - # Doesn't build - a temporal build failure due to breaking changes in the nightly compilre - - env: INTEGRATION=rust-semverver - # can be moved back to include section after https://github.com/rust-lang-nursery/failure/pull/298 is merged - - env: INTEGRATION=failure - # `cargo test` doesn't finish - disabling for now. - # - env: INTEGRATION=cargo - -script: - - | - if [ -z ${INTEGRATION} ]; then - export CFG_RELEASE_CHANNEL=nightly - export CFG_RELEASE=nightly - cargo build - cargo test - cargo test -- --ignored - else - ./ci/integration.sh - fi - -after_success: -- if [ -z ${INTEGRATION} ]; then travis-cargo coveralls --no-sudo; fi - -before_deploy: - # TODO: cross build - - cargo build --release --target=x86_64-unknown-linux-gnu - - tar czf rustfmt-x86_64-unknown-linux-gnu.tar.gz Contributing.md Design.md README.md -C target/x86_64-unknown-linux-gnu/release/rustfmt rustfmt - -deploy: - provider: releases - api_key: - secure: "your own encrypted key" - file: - - rustfmt-x86_64-unknown-linux-gnu.tar.gz - on: - repo: nrc/rustfmt - tags: true - condition: "$DEPLOY = LINUX" - skip_cleanup: true diff --git a/README.md b/README.md index 0f9652aecf9c2..ef835371b02a8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# rustfmt [![Build Status](https://travis-ci.com/rust-lang/rustfmt.svg?branch=master)](https://travis-ci.com/rust-lang/rustfmt) [![Build Status](https://ci.appveyor.com/api/projects/status/github/rust-lang/rustfmt?svg=true)](https://ci.appveyor.com/project/rust-lang-libs/rustfmt) [![crates.io](https://img.shields.io/crates/v/rustfmt-nightly.svg)](https://crates.io/crates/rustfmt-nightly) [![Travis Configuration Status](https://img.shields.io/travis/davidalber/rustfmt-travis.svg?label=travis%20example)](https://travis-ci.org/davidalber/rustfmt-travis) +# rustfmt [![linux](https://github.com/rust-lang/rustfmt/actions/workflows/linux.yml/badge.svg?event=push)](https://github.com/rust-lang/rustfmt/actions/workflows/linux.yml) [![mac](https://github.com/rust-lang/rustfmt/actions/workflows/mac.yml/badge.svg?event=push)](https://github.com/rust-lang/rustfmt/actions/workflows/mac.yml) [![windows](https://github.com/rust-lang/rustfmt/actions/workflows/windows.yml/badge.svg?event=push)](https://github.com/rust-lang/rustfmt/actions/workflows/windows.yml) [![crates.io](https://img.shields.io/crates/v/rustfmt-nightly.svg)](https://crates.io/crates/rustfmt-nightly) A tool for formatting Rust code according to style guidelines. @@ -7,9 +7,7 @@ If you'd like to help out (and you should, it's a fun project!), see Conduct](CODE_OF_CONDUCT.md). You can use rustfmt in Travis CI builds. We provide a minimal Travis CI -configuration (see [here](#checking-style-on-a-ci-server)) and verify its status -using another repository. The status of that repository's build is reported by -the "travis example" badge above. +configuration (see [here](#checking-style-on-a-ci-server)). ## Quick start From fb1a223eba3f31242f266b4936a8fe956b9d0e08 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 30 Jan 2023 07:45:26 +0900 Subject: [PATCH 10/58] Remove use of actions-rs (#5571) Signed-off-by: Yuki Okushi --- .github/workflows/upload-assets.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/upload-assets.yml b/.github/workflows/upload-assets.yml index 25699234a1ec3..7dfaa4b9204c2 100644 --- a/.github/workflows/upload-assets.yml +++ b/.github/workflows/upload-assets.yml @@ -46,10 +46,7 @@ jobs: shell: bash - name: Build release binaries - uses: actions-rs/cargo@v1 - with: - command: build - args: --release + run: cargo build --release - name: Build archive shell: bash From 846662cdb36b5e0663d2be533f5e4178705c982b Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Sat, 30 May 2020 09:36:44 -0700 Subject: [PATCH 11/58] Don't wrap comments that are part of a table Closes #4210 --- src/comment.rs | 15 ++++++++++++++- tests/target/issue-4210.rs | 15 +++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 tests/target/issue-4210.rs diff --git a/src/comment.rs b/src/comment.rs index 0677fdc2b8994..7167783872f9f 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -806,7 +806,8 @@ impl<'a> CommentRewrite<'a> { let should_wrap_comment = self.fmt.config.wrap_comments() && !is_markdown_header_doc_comment && unicode_str_width(line) > self.fmt.shape.width - && !has_url(line); + && !has_url(line) + && !is_table_item(line); if should_wrap_comment { match rewrite_string(line, &self.fmt, self.max_width) { @@ -941,6 +942,18 @@ fn has_url(s: &str) -> bool { || REFERENCE_LINK_URL.is_match(s) } +/// Returns true if the given string may be part of a Markdown talble. +fn is_table_item(mut s: &str) -> bool { + // This function may return false positive, but should get its job done in most cases (i.e. + // markdown tables with two column delimiters). + s = s.trim_start(); + return s.starts_with('|') + && match s.rfind('|') { + Some(0) | None => false, + _ => true, + }; +} + /// Given the span, rewrite the missing comment inside it if available. /// Note that the given span must only include comments (or leading/trailing whitespaces). pub(crate) fn rewrite_missing_comment( diff --git a/tests/target/issue-4210.rs b/tests/target/issue-4210.rs new file mode 100644 index 0000000000000..e96ba1b3fd053 --- /dev/null +++ b/tests/target/issue-4210.rs @@ -0,0 +1,15 @@ +// rustfmt-wrap_comments: true + +/// Table that is > 80 symbols: +/// +/// | table | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | +/// |-------|-----------------------------------------------------------------------------| +/// | val | x | +pub struct Item; + +/// Table that is > 80 symbols: +/// +/// | table | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +/// |-------|----------------------------------------------------------------------------- +/// | val | x +pub struct Item; From 368a63305cea7a472fec37757bf962cdfc12be26 Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Sat, 10 Sep 2022 13:30:41 +0200 Subject: [PATCH 12/58] Fix typo --- src/comment.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/comment.rs b/src/comment.rs index 7167783872f9f..17b4af1717d8d 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -942,7 +942,7 @@ fn has_url(s: &str) -> bool { || REFERENCE_LINK_URL.is_match(s) } -/// Returns true if the given string may be part of a Markdown talble. +/// Returns true if the given string may be part of a Markdown table. fn is_table_item(mut s: &str) -> bool { // This function may return false positive, but should get its job done in most cases (i.e. // markdown tables with two column delimiters). From cdd0b56071cbc9247461bbd2e0551b46e653162f Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Sat, 10 Sep 2022 13:31:08 +0200 Subject: [PATCH 13/58] Test that both table headers and values are not wrapped --- tests/target/issue-4210.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/target/issue-4210.rs b/tests/target/issue-4210.rs index e96ba1b3fd053..3fd9663908260 100644 --- a/tests/target/issue-4210.rs +++ b/tests/target/issue-4210.rs @@ -7,9 +7,9 @@ /// | val | x | pub struct Item; -/// Table that is > 80 symbols: +/// Table value that is > 80 symbols: /// -/// | table | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -/// |-------|----------------------------------------------------------------------------- -/// | val | x -pub struct Item; +/// | table | heading +/// |----------|----------------------------------------------------------------------------- +/// | long val | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +pub struct Item2; From 3f36c997bf45eb7b6f101885241ae59ce00e72d9 Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Sat, 10 Sep 2022 13:31:26 +0200 Subject: [PATCH 14/58] Test that with all comment wrapping disabled table comments are not wrapped --- tests/target/issue-4210-disabled.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 tests/target/issue-4210-disabled.rs diff --git a/tests/target/issue-4210-disabled.rs b/tests/target/issue-4210-disabled.rs new file mode 100644 index 0000000000000..3ba87aab8c543 --- /dev/null +++ b/tests/target/issue-4210-disabled.rs @@ -0,0 +1,15 @@ +// rustfmt-wrap_comments: false + +/// Table that is > 80 symbols: +/// +/// | table | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | +/// |-------|-----------------------------------------------------------------------------| +/// | val | x | +pub struct Item; + +/// Table value that is > 80 symbols: +/// +/// | table | heading +/// |----------|----------------------------------------------------------------------------- +/// | long val | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +pub struct Item2; From e2996a807b411218bb3dca0f2a0e420839cd3875 Mon Sep 17 00:00:00 2001 From: Thaqib <65588695+thaqibm@users.noreply.github.com> Date: Wed, 1 Feb 2023 22:26:12 -0500 Subject: [PATCH 15/58] Lists doc comments fix4041 (#5560) * add + start of an itemized line * add test * fix format * fix tests * update doc comment --- src/comment.rs | 5 +++-- tests/source/issue-4041.rs | 5 +++++ tests/target/issue-4041.rs | 6 ++++++ 3 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 tests/source/issue-4041.rs create mode 100644 tests/target/issue-4041.rs diff --git a/src/comment.rs b/src/comment.rs index 17b4af1717d8d..bc0e8774f4949 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -432,7 +432,7 @@ impl CodeBlockAttribute { /// Block that is formatted as an item. /// -/// An item starts with either a star `*` a dash `-` or a greater-than `>`. +/// An item starts with either a star `*` a dash `-` a greater-than `>` or a plus '+'. /// Different level of indentation are handled by shrinking the shape accordingly. struct ItemizedBlock { /// the lines that are identified as part of an itemized block @@ -449,7 +449,8 @@ impl ItemizedBlock { /// Returns `true` if the line is formatted as an item fn is_itemized_line(line: &str) -> bool { let trimmed = line.trim_start(); - trimmed.starts_with("* ") || trimmed.starts_with("- ") || trimmed.starts_with("> ") + let itemized_start = ["* ", "- ", "> ", "+ "]; + itemized_start.iter().any(|s| trimmed.starts_with(s)) } /// Creates a new ItemizedBlock described with the given line. diff --git a/tests/source/issue-4041.rs b/tests/source/issue-4041.rs new file mode 100644 index 0000000000000..274b80f1bc5da --- /dev/null +++ b/tests/source/issue-4041.rs @@ -0,0 +1,5 @@ +// rustfmt-wrap_comments: true +//! List: +//! - Sub list: +//! + very long #1 blah blah blah blah blah blah blah blah blah blah blah blah foo baar baxxxxxxxx long line 1231421230912i3091238192038 +//! + very long #2 blah blah blah blah blah blah blah blah blah blah blah blah diff --git a/tests/target/issue-4041.rs b/tests/target/issue-4041.rs new file mode 100644 index 0000000000000..e9c693836f2c6 --- /dev/null +++ b/tests/target/issue-4041.rs @@ -0,0 +1,6 @@ +// rustfmt-wrap_comments: true +//! List: +//! - Sub list: +//! + very long #1 blah blah blah blah blah blah blah blah blah blah blah blah +//! foo baar baxxxxxxxx long line 1231421230912i3091238192038 +//! + very long #2 blah blah blah blah blah blah blah blah blah blah blah blah From 5391847ea5a12262704657a0708b1674fb344403 Mon Sep 17 00:00:00 2001 From: Rajiv Sharma Date: Sun, 28 Aug 2022 00:36:16 +0100 Subject: [PATCH 16/58] Fix #5488 - prevent shorthand init for tuple struct Closes #5488 Fix for #5488. Before applying shorthand initialization for structs, check if identifier is a literal (e.g. tuple struct). If yes, then do not apply short hand initialization. Added test case to validate the changes for the fix. --- src/expr.rs | 6 ++++-- tests/source/issue-5488.rs | 17 +++++++++++++++++ tests/target/issue-5488.rs | 17 +++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 tests/source/issue-5488.rs create mode 100644 tests/target/issue-5488.rs diff --git a/src/expr.rs b/src/expr.rs index 0be4c3cf168cc..91f3cc81bae9a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1723,9 +1723,11 @@ pub(crate) fn rewrite_field( let overhead = name.len() + separator.len(); let expr_shape = shape.offset_left(overhead)?; let expr = field.expr.rewrite(context, expr_shape); - + let is_lit = matches!(field.expr.kind, ast::ExprKind::Lit(_)); match expr { - Some(ref e) if e.as_str() == name && context.config.use_field_init_shorthand() => { + Some(ref e) + if !is_lit && e.as_str() == name && context.config.use_field_init_shorthand() => + { Some(attrs_str + name) } Some(e) => Some(format!("{}{}{}{}", attrs_str, name, separator, e)), diff --git a/tests/source/issue-5488.rs b/tests/source/issue-5488.rs new file mode 100644 index 0000000000000..d361632e29efd --- /dev/null +++ b/tests/source/issue-5488.rs @@ -0,0 +1,17 @@ +// rustfmt-use_field_init_shorthand: true + +struct MyStruct(u32); +struct AnotherStruct { + a: u32, +} + +fn main() { + // Since MyStruct is a tuple struct, it should not be shorthanded to + // MyStruct { 0 } even if use_field_init_shorthand is enabled. + let instance = MyStruct { 0: 0 }; + + // Since AnotherStruct is not a tuple struct, the shorthand should + // apply. + let a = 10; + let instance = AnotherStruct { a: a }; +} diff --git a/tests/target/issue-5488.rs b/tests/target/issue-5488.rs new file mode 100644 index 0000000000000..0cb37c56f393f --- /dev/null +++ b/tests/target/issue-5488.rs @@ -0,0 +1,17 @@ +// rustfmt-use_field_init_shorthand: true + +struct MyStruct(u32); +struct AnotherStruct { + a: u32, +} + +fn main() { + // Since MyStruct is a tuple struct, it should not be shorthanded to + // MyStruct { 0 } even if use_field_init_shorthand is enabled. + let instance = MyStruct { 0: 0 }; + + // Since AnotherStruct is not a tuple struct, the shorthand should + // apply. + let a = 10; + let instance = AnotherStruct { a }; +} From c6b822d85546f830f568bc4ff9b1d761d26964c1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 1 Feb 2023 12:58:04 +1100 Subject: [PATCH 17/58] Rename `Cursor`/`CursorRef` as `TokenTreeCursor`/`RefTokenTreeCursor`. This makes it clear they return token trees, and makes for a nice comparison against `TokenCursor` which returns tokens. --- src/macros.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index d58f7547fefb3..7978d8cba9541 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -13,7 +13,7 @@ use std::collections::HashMap; use std::panic::{catch_unwind, AssertUnwindSafe}; use rustc_ast::token::{BinOpToken, Delimiter, Token, TokenKind}; -use rustc_ast::tokenstream::{Cursor, TokenStream, TokenTree}; +use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor}; use rustc_ast::{ast, ptr}; use rustc_ast_pretty::pprust; use rustc_span::{ @@ -736,7 +736,7 @@ impl MacroArgParser { self.buf.clear(); } - fn add_meta_variable(&mut self, iter: &mut Cursor) -> Option<()> { + fn add_meta_variable(&mut self, iter: &mut TokenTreeCursor) -> Option<()> { match iter.next() { Some(TokenTree::Token( Token { @@ -768,7 +768,7 @@ impl MacroArgParser { &mut self, inner: Vec, delim: Delimiter, - iter: &mut Cursor, + iter: &mut TokenTreeCursor, ) -> Option<()> { let mut buffer = String::new(); let mut first = true; @@ -1121,7 +1121,7 @@ pub(crate) fn macro_style(mac: &ast::MacCall, context: &RewriteContext<'_>) -> D // Currently we do not attempt to parse any further than that. #[derive(new)] struct MacroParser { - toks: Cursor, + toks: TokenTreeCursor, } impl MacroParser { From 24f4ecec2595ab504994766d8cc60d2c11eaa369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 9 Feb 2023 10:16:00 +0000 Subject: [PATCH 18/58] Introduce `-Zterminal-urls` to use OSC8 for error codes Terminals supporting the OSC8 Hyperlink Extension can support inline anchors where the text is user defineable but clicking on it opens a browser to a specified URLs, just like `` does in HTML. https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda --- src/parse/session.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/parse/session.rs b/src/parse/session.rs index 6bfec79cd7030..9014026b0aa4a 100644 --- a/src/parse/session.rs +++ b/src/parse/session.rs @@ -4,7 +4,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; use rustc_data_structures::sync::{Lrc, Send}; use rustc_errors::emitter::{Emitter, EmitterWriter}; use rustc_errors::translation::Translate; -use rustc_errors::{ColorConfig, Diagnostic, Handler, Level as DiagnosticLevel}; +use rustc_errors::{ColorConfig, Diagnostic, Handler, Level as DiagnosticLevel, TerminalUrl}; use rustc_session::parse::ParseSess as RawParseSess; use rustc_span::{ source_map::{FilePathMapping, SourceMap}, @@ -135,6 +135,7 @@ fn default_handler( None, false, false, + TerminalUrl::No, )) }; Handler::with_emitter( From 34f9ca28f2f4ae3ac462c6dcd862b513e107e459 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Wed, 15 Feb 2023 22:24:03 -0600 Subject: [PATCH 19/58] fix: use correct span for struct generics --- src/items.rs | 2 +- tests/target/issue_5691.rs | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 tests/target/issue_5691.rs diff --git a/src/items.rs b/src/items.rs index 25e8a024857ce..3c5293b6bf5a7 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1278,7 +1278,7 @@ pub(crate) fn format_struct_struct( let header_hi = struct_parts.ident.span.hi(); let body_lo = if let Some(generics) = struct_parts.generics { // Adjust the span to start at the end of the generic arguments before searching for the '{' - let span = span.with_lo(generics.span.hi()); + let span = span.with_lo(generics.where_clause.span.hi()); context.snippet_provider.span_after(span, "{") } else { context.snippet_provider.span_after(span, "{") diff --git a/tests/target/issue_5691.rs b/tests/target/issue_5691.rs new file mode 100644 index 0000000000000..e3aad15db0d5b --- /dev/null +++ b/tests/target/issue_5691.rs @@ -0,0 +1,16 @@ +struct S +where + [(); { num_slots!(C) }]:, { + /* An asterisk-based, or a double-slash-prefixed, comment here is + required to trigger the fmt bug. + + A single-line triple-slash-prefixed comment (with a field following it) is not enough - it will not trigger the fmt bug. + + Side note: If you have a combination of two, or all three of the + above mentioned types of comments here, some of them disappear + after `cargo fmt`. + + The bug gets triggered even if a field definition following the + (asterisk-based, or a double-slash-prefixed) comment, too. + */ +} From af75a2f7f10001da3f9d5fbda2d9cce458b7959d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 23 Nov 2022 11:55:16 +1100 Subject: [PATCH 20/58] Use `ThinVec` in various AST types. This commit changes the sequence parsers to produce `ThinVec`, which triggers numerous conversions. --- src/chains.rs | 4 +++- src/lib.rs | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/chains.rs b/src/chains.rs index 39b8d6878097d..cbe523c6c3ca9 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -74,6 +74,8 @@ use crate::utils::{ rewrite_ident, trimmed_last_line_width, wrap_str, }; +use thin_vec::ThinVec; + /// Provides the original input contents from the span /// of a chain element with trailing spaces trimmed. fn format_overflow_style(span: Span, context: &RewriteContext<'_>) -> Option { @@ -168,7 +170,7 @@ enum ChainItemKind { MethodCall( ast::PathSegment, Vec, - Vec>, + ThinVec>, ), StructField(symbol::Ident), TupleField(symbol::Ident, bool), diff --git a/src/lib.rs b/src/lib.rs index 0c27bcacfb83c..b27405efdb700 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,6 +23,7 @@ extern crate rustc_expand; extern crate rustc_parse; extern crate rustc_session; extern crate rustc_span; +extern crate thin_vec; // Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta // files. From 23007fc9e4ad5666c65e8a598e2942c8329def0e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 30 Jan 2023 14:13:27 +1100 Subject: [PATCH 21/58] Use `ThinVec` in `ast::Block`. --- src/closures.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/closures.rs b/src/closures.rs index 8fd0fcf8f5c2c..340113866c4e2 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -1,5 +1,6 @@ use rustc_ast::{ast, ptr}; use rustc_span::Span; +use thin_vec::thin_vec; use crate::attr::get_attrs_from_stmt; use crate::config::lists::*; @@ -150,7 +151,7 @@ fn rewrite_closure_with_block( } let block = ast::Block { - stmts: vec![ast::Stmt { + stmts: thin_vec![ast::Stmt { id: ast::NodeId::root(), kind: ast::StmtKind::Expr(ptr::P(body.clone())), span: body.span, From 01ed9ddf0ef7a754235b6c1f92689e6f048282d0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 30 Jan 2023 15:39:22 +1100 Subject: [PATCH 22/58] Use `ThinVec` in a few more AST types. --- src/modules.rs | 13 +++++++------ src/parse/parser.rs | 3 ++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/modules.rs b/src/modules.rs index 7a0d1736c59a6..af9a154a6aea6 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -6,6 +6,7 @@ use rustc_ast::ast; use rustc_ast::visit::Visitor; use rustc_span::symbol::{self, sym, Symbol}; use rustc_span::Span; +use thin_vec::ThinVec; use thiserror::Error; use crate::attr::MetaVisitor; @@ -25,7 +26,7 @@ type FileModMap<'ast> = BTreeMap>; #[derive(Debug, Clone)] pub(crate) struct Module<'a> { ast_mod_kind: Option>, - pub(crate) items: Cow<'a, Vec>>, + pub(crate) items: Cow<'a, ThinVec>>, inner_attr: ast::AttrVec, pub(crate) span: Span, } @@ -34,7 +35,7 @@ impl<'a> Module<'a> { pub(crate) fn new( mod_span: Span, ast_mod_kind: Option>, - mod_items: Cow<'a, Vec>>, + mod_items: Cow<'a, ThinVec>>, mod_attrs: Cow<'a, ast::AttrVec>, ) -> Self { let inner_attr = mod_attrs @@ -157,7 +158,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { Module::new( module_item.item.span, Some(Cow::Owned(sub_mod_kind.clone())), - Cow::Owned(vec![]), + Cow::Owned(ThinVec::new()), Cow::Owned(ast::AttrVec::new()), ), )?; @@ -169,7 +170,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { /// Visit modules defined inside macro calls. fn visit_mod_outside_ast( &mut self, - items: Vec>, + items: ThinVec>, ) -> Result<(), ModuleResolutionError> { for item in items { if is_cfg_if(&item) { @@ -184,7 +185,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { Module::new( span, Some(Cow::Owned(sub_mod_kind.clone())), - Cow::Owned(vec![]), + Cow::Owned(ThinVec::new()), Cow::Owned(ast::AttrVec::new()), ), )?; @@ -210,7 +211,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { Module::new( span, Some(Cow::Borrowed(sub_mod_kind)), - Cow::Owned(vec![]), + Cow::Owned(ThinVec::new()), Cow::Borrowed(&item.attrs), ), )?; diff --git a/src/parse/parser.rs b/src/parse/parser.rs index e0bd065518b3d..7ab042506bd29 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -6,6 +6,7 @@ use rustc_ast::{ast, ptr}; use rustc_errors::Diagnostic; use rustc_parse::{new_parser_from_file, parser::Parser as RawParser}; use rustc_span::{sym, Span}; +use thin_vec::ThinVec; use crate::attr::first_attr_value_str_by_name; use crate::parse::session::ParseSess; @@ -109,7 +110,7 @@ impl<'a> Parser<'a> { sess: &'a ParseSess, path: &Path, span: Span, - ) -> Result<(ast::AttrVec, Vec>, Span), ParserError> { + ) -> Result<(ast::AttrVec, ThinVec>, Span), ParserError> { let result = catch_unwind(AssertUnwindSafe(|| { let mut parser = new_parser_from_file(sess.inner(), path, Some(span)); match parser.parse_mod(&TokenKind::Eof) { From 8b7f8116d62e53cfd2b700155e6851c026529819 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 13 Oct 2022 10:13:02 +0100 Subject: [PATCH 23/58] errors: generate typed identifiers in each crate Instead of loading the Fluent resources for every crate in `rustc_error_messages`, each crate generates typed identifiers for its own diagnostics and creates a static which are pulled together in the `rustc_driver` crate and provided to the diagnostic emitter. Signed-off-by: David Wood --- src/parse/session.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parse/session.rs b/src/parse/session.rs index 9014026b0aa4a..a7a363d47ba6a 100644 --- a/src/parse/session.rs +++ b/src/parse/session.rs @@ -124,7 +124,7 @@ fn default_handler( silent_emitter() } else { let fallback_bundle = - rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false); + rustc_errors::fallback_fluent_bundle(rustc_driver::DEFAULT_LOCALE_RESOURCES, false); Box::new(EmitterWriter::stderr( color_cfg, Some(source_map.clone()), From 386ea3770f39e41c8e3be7a05527484b11e23769 Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 17 Oct 2022 14:11:26 +0100 Subject: [PATCH 24/58] various: translation resources from cg backend Extend `CodegenBackend` trait with a function returning the translation resources from the codegen backend, which can be added to the complete list of resources provided to the emitter. Signed-off-by: David Wood --- src/parse/session.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/parse/session.rs b/src/parse/session.rs index a7a363d47ba6a..a64963db6a7d0 100644 --- a/src/parse/session.rs +++ b/src/parse/session.rs @@ -123,8 +123,10 @@ fn default_handler( let emitter = if hide_parse_errors { silent_emitter() } else { - let fallback_bundle = - rustc_errors::fallback_fluent_bundle(rustc_driver::DEFAULT_LOCALE_RESOURCES, false); + let fallback_bundle = rustc_errors::fallback_fluent_bundle( + rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), + false, + ); Box::new(EmitterWriter::stderr( color_cfg, Some(source_map.clone()), From a5ba6e025f9c37dc3b9f0943355974288f0c4da9 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 27 Feb 2023 13:07:44 +0000 Subject: [PATCH 25/58] Remove uses of `box_syntax` in rustc and tools --- tests/source/expr.rs | 11 ----------- tests/target/configs/combine_control_expr/false.rs | 6 ------ tests/target/configs/combine_control_expr/true.rs | 6 ------ tests/target/expr.rs | 14 -------------- 4 files changed, 37 deletions(-) diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 21f8a4a43668a..879c551ea4909 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -3,7 +3,6 @@ // Test expressions fn foo() -> bool { - let boxed: Box = box 5; let referenced = &5 ; let very_long_variable_name = ( a + first + simple + test ); @@ -132,12 +131,6 @@ fn qux() { } } -fn issue227() { - { - let handler = box DocumentProgressHandler::new(addr, DocumentProgressTask::DOMContentLoaded); - } -} - fn issue184(source: &str) { for c in source.chars() { if index < 'a' { @@ -413,10 +406,6 @@ fn issue2704() { .concat(&requires1) .concat(&requires2) .distinct_total()); - let requires = requires.set(box requires0 - .concat(&requires1) - .concat(&requires2) - .distinct_total()); let requires = requires.set(requires0 .concat(&requires1) .concat(&requires2) diff --git a/tests/target/configs/combine_control_expr/false.rs b/tests/target/configs/combine_control_expr/false.rs index 5ada9b1dd1485..0ab8202493746 100644 --- a/tests/target/configs/combine_control_expr/false.rs +++ b/tests/target/configs/combine_control_expr/false.rs @@ -108,12 +108,6 @@ fn main() { bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, )); - // Box - foo(box Bar { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - }); - // Unary foo(!bar( aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, diff --git a/tests/target/configs/combine_control_expr/true.rs b/tests/target/configs/combine_control_expr/true.rs index 52acd26492add..aa41e021fb7ab 100644 --- a/tests/target/configs/combine_control_expr/true.rs +++ b/tests/target/configs/combine_control_expr/true.rs @@ -96,12 +96,6 @@ fn main() { bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, )); - // Box - foo(box Bar { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - }); - // Unary foo(!bar( aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 84df802bc70f9..187a1dc976a46 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -3,7 +3,6 @@ // Test expressions fn foo() -> bool { - let boxed: Box = box 5; let referenced = &5; let very_long_variable_name = (a + first + simple + test); @@ -179,13 +178,6 @@ fn qux() { } } -fn issue227() { - { - let handler = - box DocumentProgressHandler::new(addr, DocumentProgressTask::DOMContentLoaded); - } -} - fn issue184(source: &str) { for c in source.chars() { if index < 'a' { @@ -454,12 +446,6 @@ fn issue2704() { .concat(&requires2) .distinct_total(), ); - let requires = requires.set( - box requires0 - .concat(&requires1) - .concat(&requires2) - .distinct_total(), - ); let requires = requires.set( requires0 .concat(&requires1) From 4e658cc01ef5190445016ea951e21a2d0ae02a33 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 27 Feb 2023 13:17:29 +0000 Subject: [PATCH 26/58] Remove `box_syntax` from AST and use in tools --- src/closures.rs | 2 -- src/expr.rs | 5 ----- src/matches.rs | 1 - src/utils.rs | 1 - 4 files changed, 9 deletions(-) diff --git a/src/closures.rs b/src/closures.rs index 340113866c4e2..c95e9a97b43d3 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -195,7 +195,6 @@ fn rewrite_closure_expr( | ast::ExprKind::Struct(..) => true, ast::ExprKind::AddrOf(_, _, ref expr) - | ast::ExprKind::Box(ref expr) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Unary(_, ref expr) | ast::ExprKind::Cast(ref expr, _) => allow_multi_line(expr), @@ -441,7 +440,6 @@ fn is_block_closure_forced_inner(expr: &ast::Expr, version: Version) -> bool { ast::ExprKind::If(..) | ast::ExprKind::While(..) | ast::ExprKind::ForLoop(..) => true, ast::ExprKind::Loop(..) if version == Version::Two => true, ast::ExprKind::AddrOf(_, _, ref expr) - | ast::ExprKind::Box(ref expr) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Unary(_, ref expr) | ast::ExprKind::Cast(ref expr, _) => is_block_closure_forced_inner(expr, version), diff --git a/src/expr.rs b/src/expr.rs index 3f0f217f8907d..7273402ec760f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -236,7 +236,6 @@ pub(crate) fn format_expr( ast::ExprKind::Yeet(Some(ref expr)) => { rewrite_unary_prefix(context, "do yeet ", &**expr, shape) } - ast::ExprKind::Box(ref expr) => rewrite_unary_prefix(context, "box ", &**expr, shape), ast::ExprKind::AddrOf(borrow_kind, mutability, ref expr) => { rewrite_expr_addrof(context, borrow_kind, mutability, expr, shape) } @@ -1299,7 +1298,6 @@ pub(crate) fn is_simple_expr(expr: &ast::Expr) -> bool { ast::ExprKind::Lit(..) => true, ast::ExprKind::Path(ref qself, ref path) => qself.is_none() && path.segments.len() <= 1, ast::ExprKind::AddrOf(_, _, ref expr) - | ast::ExprKind::Box(ref expr) | ast::ExprKind::Cast(ref expr, _) | ast::ExprKind::Field(ref expr, _) | ast::ExprKind::Try(ref expr) @@ -1361,7 +1359,6 @@ pub(crate) fn can_be_overflowed_expr( // Handle unary-like expressions ast::ExprKind::AddrOf(_, _, ref expr) - | ast::ExprKind::Box(ref expr) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Unary(_, ref expr) | ast::ExprKind::Cast(ref expr, _) => can_be_overflowed_expr(context, expr, args_len), @@ -1373,7 +1370,6 @@ pub(crate) fn is_nested_call(expr: &ast::Expr) -> bool { match expr.kind { ast::ExprKind::Call(..) | ast::ExprKind::MacCall(..) => true, ast::ExprKind::AddrOf(_, _, ref expr) - | ast::ExprKind::Box(ref expr) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Unary(_, ref expr) | ast::ExprKind::Cast(ref expr, _) => is_nested_call(expr), @@ -2133,7 +2129,6 @@ pub(crate) fn is_method_call(expr: &ast::Expr) -> bool { match expr.kind { ast::ExprKind::MethodCall(..) => true, ast::ExprKind::AddrOf(_, _, ref expr) - | ast::ExprKind::Box(ref expr) | ast::ExprKind::Cast(ref expr, _) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Unary(_, ref expr) => is_method_call(expr), diff --git a/src/matches.rs b/src/matches.rs index 85d9c5d2b9bbf..aac5e59b8603a 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -592,7 +592,6 @@ fn can_flatten_block_around_this(body: &ast::Expr) -> bool { | ast::ExprKind::Struct(..) | ast::ExprKind::Tup(..) => true, ast::ExprKind::AddrOf(_, _, ref expr) - | ast::ExprKind::Box(ref expr) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Unary(_, ref expr) | ast::ExprKind::Index(ref expr, _) diff --git a/src/utils.rs b/src/utils.rs index 1e89f3ae75f81..a26375ee64384 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -492,7 +492,6 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr | ast::ExprKind::Assign(..) | ast::ExprKind::AssignOp(..) | ast::ExprKind::Await(..) - | ast::ExprKind::Box(..) | ast::ExprKind::Break(..) | ast::ExprKind::Cast(..) | ast::ExprKind::Continue(..) From 3ef194c14cda52c36110a02d7b812371d7b99884 Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Tue, 31 Jan 2023 22:13:25 +0100 Subject: [PATCH 27/58] Remove the `NodeId` of `ast::ExprKind::Async` --- src/expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/expr.rs b/src/expr.rs index 7273402ec760f..ac96bedf2fe86 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -366,7 +366,7 @@ pub(crate) fn format_expr( )) } } - ast::ExprKind::Async(capture_by, _node_id, ref block) => { + ast::ExprKind::Async(capture_by, ref block) => { let mover = if capture_by == ast::CaptureBy::Value { "move " } else { From 809dd77b8001f69bd5202f73d016f9ac8426b69e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 19 Mar 2023 21:32:34 +0400 Subject: [PATCH 28/58] rustc: Remove unused `Session` argument from some attribute functions --- src/attr.rs | 16 +--------------- src/parse/parser.rs | 5 ++--- src/reorder.rs | 4 ++-- 3 files changed, 5 insertions(+), 20 deletions(-) diff --git a/src/attr.rs b/src/attr.rs index 5648e1254ed7c..22e45082a9f71 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -2,7 +2,7 @@ use rustc_ast::ast; use rustc_ast::HasAttrs; -use rustc_span::{symbol::sym, Span, Symbol}; +use rustc_span::{symbol::sym, Span}; use self::doc_comment::DocCommentFormatter; use crate::comment::{contains_comment, rewrite_doc_comment, CommentStyle}; @@ -19,20 +19,6 @@ use crate::utils::{count_newlines, mk_sp}; mod doc_comment; -pub(crate) fn contains_name(attrs: &[ast::Attribute], name: Symbol) -> bool { - attrs.iter().any(|attr| attr.has_name(name)) -} - -pub(crate) fn first_attr_value_str_by_name( - attrs: &[ast::Attribute], - name: Symbol, -) -> Option { - attrs - .iter() - .find(|attr| attr.has_name(name)) - .and_then(|attr| attr.value_str()) -} - /// Returns attributes on the given statement. pub(crate) fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] { stmt.attrs() diff --git a/src/parse/parser.rs b/src/parse/parser.rs index 7ab042506bd29..6bc53159b38ba 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -2,13 +2,12 @@ use std::panic::{catch_unwind, AssertUnwindSafe}; use std::path::{Path, PathBuf}; use rustc_ast::token::TokenKind; -use rustc_ast::{ast, ptr}; +use rustc_ast::{ast, attr, ptr}; use rustc_errors::Diagnostic; use rustc_parse::{new_parser_from_file, parser::Parser as RawParser}; use rustc_span::{sym, Span}; use thin_vec::ThinVec; -use crate::attr::first_attr_value_str_by_name; use crate::parse::session::ParseSess; use crate::Input; @@ -93,7 +92,7 @@ pub(crate) enum ParserError { impl<'a> Parser<'a> { pub(crate) fn submod_path_from_attr(attrs: &[ast::Attribute], path: &Path) -> Option { - let path_sym = first_attr_value_str_by_name(attrs, sym::path)?; + let path_sym = attr::first_attr_value_str_by_name(attrs, sym::path)?; let path_str = path_sym.as_str(); // On windows, the base path might have the form diff --git a/src/reorder.rs b/src/reorder.rs index 9e4a668aa4930..3bddf4c1b6a41 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -8,7 +8,7 @@ use std::cmp::{Ord, Ordering}; -use rustc_ast::ast; +use rustc_ast::{ast, attr}; use rustc_span::{symbol::sym, Span}; use crate::config::{Config, GroupImportsTactic}; @@ -167,7 +167,7 @@ fn rewrite_reorderable_or_regroupable_items( } fn contains_macro_use_attr(item: &ast::Item) -> bool { - crate::attr::contains_name(&item.attrs, sym::macro_use) + attr::contains_name(&item.attrs, sym::macro_use) } /// Divides imports into three groups, corresponding to standard, external From 475396a03c767a4a3a7e7d3be62f91751c2ba85e Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Thu, 30 Mar 2023 13:00:18 -0400 Subject: [PATCH 29/58] Prevent ICE when calling parse_attribute in parse_cfg_if_inner Fixes 5728 Previously we were ignoring the diagnostic error, which lead to the ICE. Now we properly cancel the error. --- src/parse/macros/cfg_if.rs | 5 ++++- tests/rustfmt/main.rs | 12 ++++++++++++ tests/target/issue_5728.rs | 5 +++++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 tests/target/issue_5728.rs diff --git a/src/parse/macros/cfg_if.rs b/src/parse/macros/cfg_if.rs index ace1a76b3fe7d..ac03409a7844b 100644 --- a/src/parse/macros/cfg_if.rs +++ b/src/parse/macros/cfg_if.rs @@ -44,7 +44,10 @@ fn parse_cfg_if_inner<'a>( // See also https://github.com/rust-lang/rust/pull/79433 parser .parse_attribute(rustc_parse::parser::attr::InnerAttrPolicy::Permitted) - .map_err(|_| "Failed to parse attributes")?; + .map_err(|e| { + e.cancel(); + "Failed to parse attributes" + })?; } if !parser.eat(&TokenKind::OpenDelim(Delimiter::Brace)) { diff --git a/tests/rustfmt/main.rs b/tests/rustfmt/main.rs index 7ff301e80195a..f00b0e09604fe 100644 --- a/tests/rustfmt/main.rs +++ b/tests/rustfmt/main.rs @@ -174,3 +174,15 @@ fn rustfmt_emits_error_on_line_overflow_true() { "line formatted, but exceeded maximum width (maximum: 100 (see `max_width` option)" )) } + +#[test] +#[allow(non_snake_case)] +fn dont_emit_ICE() { + let files = ["tests/target/issue_5728.rs"]; + + for file in files { + let args = [file]; + let (_stdout, stderr) = rustfmt(&args); + assert!(!stderr.contains("thread 'main' panicked")); + } +} diff --git a/tests/target/issue_5728.rs b/tests/target/issue_5728.rs new file mode 100644 index 0000000000000..e1355416faf43 --- /dev/null +++ b/tests/target/issue_5728.rs @@ -0,0 +1,5 @@ +cfg_if::cfg_if! { + if #[cfg(windows)] { + } else if #(&cpus) { + } else [libc::CTL_HW, libc::HW_NCPU, 0, 0] +} From a3b2bfc2db33ec3bed266404e6391c145e000df0 Mon Sep 17 00:00:00 2001 From: Greg Jandl Date: Mon, 27 Mar 2023 12:02:02 -0500 Subject: [PATCH 30/58] Honor --color option when emitting errors Fixes issue 5717. --- src/parse/session.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/parse/session.rs b/src/parse/session.rs index 6bfec79cd7030..1956e1b8cd74f 100644 --- a/src/parse/session.rs +++ b/src/parse/session.rs @@ -12,6 +12,7 @@ use rustc_span::{ }; use crate::config::file_lines::LineRange; +use crate::config::options::Color; use crate::ignore_path::IgnorePathSet; use crate::parse::parser::{ModError, ModulePathSuccess}; use crate::source_map::LineRangeUtils; @@ -107,15 +108,26 @@ impl Emitter for SilentOnIgnoredFilesEmitter { } } +impl From for ColorConfig { + fn from(color: Color) -> Self { + match color { + Color::Auto => ColorConfig::Auto, + Color::Always => ColorConfig::Always, + Color::Never => ColorConfig::Never, + } + } +} + fn default_handler( source_map: Lrc, ignore_path_set: Lrc, can_reset: Lrc, hide_parse_errors: bool, + color: Color, ) -> Handler { let supports_color = term::stderr().map_or(false, |term| term.supports_color()); - let color_cfg = if supports_color { - ColorConfig::Auto + let emit_color = if supports_color { + ColorConfig::from(color) } else { ColorConfig::Never }; @@ -126,7 +138,7 @@ fn default_handler( let fallback_bundle = rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false); Box::new(EmitterWriter::stderr( - color_cfg, + emit_color, Some(source_map.clone()), None, fallback_bundle, @@ -164,6 +176,7 @@ impl ParseSess { Lrc::clone(&ignore_path_set), Lrc::clone(&can_reset_errors), config.hide_parse_errors(), + config.color(), ); let parse_sess = RawParseSess::with_span_handler(handler, source_map); From c2890ec2d7f1cd7d8af262ffe9177094756f84b0 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 29 Mar 2023 08:37:47 +0000 Subject: [PATCH 31/58] rust-analyzer guided enum variant structification --- src/items.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/items.rs b/src/items.rs index 25e8a024857ce..520bb5278001f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1805,7 +1805,7 @@ 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(ref ty, mutability, ref expr) => { + ast::ItemKind::Static(ast::Static(ref ty, mutability, ref expr)) => { (None, "static", ty, mutability, expr) } ast::ItemKind::Const(defaultness, ref ty, ref expr) => { From ced3cd8d40b7dcb5756c246309598e309b4fdbcd Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 29 Mar 2023 08:50:04 +0000 Subject: [PATCH 32/58] rust-analyzer guided tuple field to named field --- src/items.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/items.rs b/src/items.rs index 520bb5278001f..6cbe68ae39848 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1805,7 +1805,7 @@ 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(ast::Static(ref ty, mutability, ref expr)) => { + ast::ItemKind::Static(ast::Static { ref ty, mutability, ref expr}) => { (None, "static", ty, mutability, expr) } ast::ItemKind::Const(defaultness, ref ty, ref expr) => { From 3ecb9ed53c3cc50f5e7ec6d03b2998bf69adea11 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 29 Mar 2023 09:20:45 +0000 Subject: [PATCH 33/58] Split out ast::ItemKind::Const into its own struct --- src/items.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/items.rs b/src/items.rs index 6cbe68ae39848..0dc8a4e937f2a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1808,7 +1808,7 @@ impl<'a> StaticParts<'a> { ast::ItemKind::Static(ast::Static { ref ty, mutability, ref expr}) => { (None, "static", ty, mutability, expr) } - ast::ItemKind::Const(defaultness, ref ty, ref expr) => { + ast::ItemKind::Const(ast::ConstItem { defaultness, ref ty, ref expr}) => { (Some(defaultness), "const", ty, ast::Mutability::Not, expr) } _ => unreachable!(), @@ -1827,8 +1827,8 @@ impl<'a> StaticParts<'a> { pub(crate) fn from_trait_item(ti: &'a ast::AssocItem) -> Self { let (defaultness, ty, expr_opt) = match ti.kind { - ast::AssocItemKind::Const(defaultness, ref ty, ref expr_opt) => { - (defaultness, ty, expr_opt) + ast::AssocItemKind::Const(ast::ConstItem {defaultness, ref ty, ref expr}) => { + (defaultness, ty, expr) } _ => unreachable!(), }; @@ -1846,7 +1846,7 @@ impl<'a> StaticParts<'a> { pub(crate) fn from_impl_item(ii: &'a ast::AssocItem) -> Self { let (defaultness, ty, expr) = match ii.kind { - ast::AssocItemKind::Const(defaultness, ref ty, ref expr) => (defaultness, ty, expr), + ast::AssocItemKind::Const(ast::ConstItem { defaultness, ref ty, ref expr}) => (defaultness, ty, expr), _ => unreachable!(), }; StaticParts { From f1781396bf125b46b679d3bf9499c0b9278607f9 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 29 Mar 2023 12:34:05 +0000 Subject: [PATCH 34/58] box a bunch of large types --- src/items.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/items.rs b/src/items.rs index 0dc8a4e937f2a..43779cfaecd3a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1804,13 +1804,15 @@ 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(ast::Static { ref ty, mutability, ref expr}) => { - (None, "static", ty, mutability, expr) - } - ast::ItemKind::Const(ast::ConstItem { defaultness, ref ty, ref expr}) => { - (Some(defaultness), "const", ty, ast::Mutability::Not, expr) - } + let (defaultness, prefix, ty, mutability, expr) = match &item.kind { + ast::ItemKind::Static(s) => (None, "static", &s.ty, s.mutability, &s.expr), + ast::ItemKind::Const(c) => ( + Some(c.defaultness), + "const", + &c.ty, + ast::Mutability::Not, + &c.expr, + ), _ => unreachable!(), }; StaticParts { @@ -1826,10 +1828,8 @@ impl<'a> StaticParts<'a> { } pub(crate) fn from_trait_item(ti: &'a ast::AssocItem) -> Self { - let (defaultness, ty, expr_opt) = match ti.kind { - ast::AssocItemKind::Const(ast::ConstItem {defaultness, ref ty, ref expr}) => { - (defaultness, ty, expr) - } + let (defaultness, ty, expr_opt) = match &ti.kind { + ast::AssocItemKind::Const(c) => (c.defaultness, &c.ty, &c.expr), _ => unreachable!(), }; StaticParts { @@ -1845,8 +1845,8 @@ impl<'a> StaticParts<'a> { } pub(crate) fn from_impl_item(ii: &'a ast::AssocItem) -> Self { - let (defaultness, ty, expr) = match ii.kind { - ast::AssocItemKind::Const(ast::ConstItem { defaultness, ref ty, ref expr}) => (defaultness, ty, expr), + let (defaultness, ty, expr) = match &ii.kind { + ast::AssocItemKind::Const(c) => (c.defaultness, &c.ty, &c.expr), _ => unreachable!(), }; StaticParts { From 84385bff42c9f823e83e64c3c9c61311feee608c Mon Sep 17 00:00:00 2001 From: DrMeepster <19316085+DrMeepster@users.noreply.github.com> Date: Sun, 11 Sep 2022 00:37:49 -0700 Subject: [PATCH 35/58] offset_of --- src/expr.rs | 1 + src/utils.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/expr.rs b/src/expr.rs index ac96bedf2fe86..b76e3a2a87c99 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -345,6 +345,7 @@ pub(crate) fn format_expr( // Style Guide RFC for InlineAsm variant pending // https://github.com/rust-dev-tools/fmt-rfcs/issues/152 ast::ExprKind::InlineAsm(..) => Some(context.snippet(expr.span).to_owned()), + ast::ExprKind::OffsetOf(..) => Some(context.snippet(expr.span).to_owned()), ast::ExprKind::TryBlock(ref block) => { if let rw @ Some(_) = rewrite_single_line_block(context, "try ", block, Some(&expr.attrs), None, shape) diff --git a/src/utils.rs b/src/utils.rs index a26375ee64384..ca1716574071b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -499,6 +499,7 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr | ast::ExprKind::Field(..) | ast::ExprKind::IncludedBytes(..) | ast::ExprKind::InlineAsm(..) + | ast::ExprKind::OffsetOf(..) | ast::ExprKind::Let(..) | ast::ExprKind::Path(..) | ast::ExprKind::Range(..) From ecfdec44df08f118c641c4076238f07a7f437fe6 Mon Sep 17 00:00:00 2001 From: DrMeepster <19316085+DrMeepster@users.noreply.github.com> Date: Fri, 21 Apr 2023 01:44:17 -0700 Subject: [PATCH 36/58] minor tweaks --- src/expr.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/expr.rs b/src/expr.rs index b76e3a2a87c99..a0882eff707f2 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -345,7 +345,6 @@ pub(crate) fn format_expr( // Style Guide RFC for InlineAsm variant pending // https://github.com/rust-dev-tools/fmt-rfcs/issues/152 ast::ExprKind::InlineAsm(..) => Some(context.snippet(expr.span).to_owned()), - ast::ExprKind::OffsetOf(..) => Some(context.snippet(expr.span).to_owned()), ast::ExprKind::TryBlock(ref block) => { if let rw @ Some(_) = rewrite_single_line_block(context, "try ", block, Some(&expr.attrs), None, shape) @@ -400,7 +399,7 @@ pub(crate) fn format_expr( } } ast::ExprKind::Underscore => Some("_".to_owned()), - ast::ExprKind::FormatArgs(..) | ast::ExprKind::IncludedBytes(..) => { + ast::ExprKind::FormatArgs(..) | ast::ExprKind::IncludedBytes(..) | ast::ExprKind::OffsetOf(..) => { // These do not occur in the AST because macros aren't expanded. unreachable!() } From f4c9b4c26f7d28416031129f300b9a9bb5e68641 Mon Sep 17 00:00:00 2001 From: DrMeepster <19316085+DrMeepster@users.noreply.github.com> Date: Fri, 21 Apr 2023 08:59:30 -0700 Subject: [PATCH 37/58] rustfmt fmt --- src/expr.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/expr.rs b/src/expr.rs index a0882eff707f2..824e42191364f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -399,7 +399,9 @@ pub(crate) fn format_expr( } } ast::ExprKind::Underscore => Some("_".to_owned()), - ast::ExprKind::FormatArgs(..) | ast::ExprKind::IncludedBytes(..) | ast::ExprKind::OffsetOf(..) => { + ast::ExprKind::FormatArgs(..) + | ast::ExprKind::IncludedBytes(..) + | ast::ExprKind::OffsetOf(..) => { // These do not occur in the AST because macros aren't expanded. unreachable!() } From 6b9c151686baf6705b4bcfb6ce3db86bc817a9b3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 25 Apr 2023 18:59:16 +0000 Subject: [PATCH 38/58] Tweak await span --- src/chains.rs | 4 ++-- src/expr.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/chains.rs b/src/chains.rs index cbe523c6c3ca9..0afce7cf65962 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -232,7 +232,7 @@ impl ChainItemKind { let span = mk_sp(nested.span.hi(), field.span.hi()); (kind, span) } - ast::ExprKind::Await(ref nested) => { + ast::ExprKind::Await(ref nested, _) => { let span = mk_sp(nested.span.hi(), expr.span.hi()); (ChainItemKind::Await, span) } @@ -459,7 +459,7 @@ impl Chain { ast::ExprKind::MethodCall(ref call) => Some(Self::convert_try(&call.receiver, context)), ast::ExprKind::Field(ref subexpr, _) | ast::ExprKind::Try(ref subexpr) - | ast::ExprKind::Await(ref subexpr) => Some(Self::convert_try(subexpr, context)), + | ast::ExprKind::Await(ref subexpr, _) => Some(Self::convert_try(subexpr, context)), _ => None, } } diff --git a/src/expr.rs b/src/expr.rs index 824e42191364f..5dc628adb0c6f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -218,7 +218,7 @@ pub(crate) fn format_expr( ast::ExprKind::Try(..) | ast::ExprKind::Field(..) | ast::ExprKind::MethodCall(..) - | ast::ExprKind::Await(_) => rewrite_chain(expr, context, shape), + | ast::ExprKind::Await(_, _) => rewrite_chain(expr, context, shape), ast::ExprKind::MacCall(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { wrap_str( @@ -1889,7 +1889,7 @@ impl<'ast> RhsAssignKind<'ast> { ast::ExprKind::Try(..) | ast::ExprKind::Field(..) | ast::ExprKind::MethodCall(..) - | ast::ExprKind::Await(_) + | ast::ExprKind::Await(_, _) ) } _ => false, From a44c7ea5923caa8f908ae0fdd6563033a7ad88da Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Thu, 27 Apr 2023 20:20:18 +0200 Subject: [PATCH 39/58] fix broken markdown --- src/config/options.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/options.rs b/src/config/options.rs index 257a17b2703a9..408017d2432c9 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -18,7 +18,7 @@ pub enum NewlineStyle { Auto, /// Force CRLF (`\r\n`). Windows, - /// Force CR (`\n). + /// Force CR (`\n`). Unix, /// `\r\n` in Windows, `\n` on other platforms. Native, From a74d2d7440003ada5c88fc75c4eb468335afa618 Mon Sep 17 00:00:00 2001 From: yukang Date: Wed, 15 Mar 2023 07:10:59 +0800 Subject: [PATCH 40/58] fix tests --- tests/source/type-ascription.rs | 10 ++++----- .../configs/format_macro_bodies/true.rs | 8 ++----- .../configs/format_macro_matchers/false.rs | 8 ++----- .../configs/format_macro_matchers/true.rs | 8 ++----- tests/target/macros.rs | 22 ++++++++----------- tests/target/type-ascription.rs | 11 +++++----- tests/target/type.rs | 2 +- 7 files changed, 27 insertions(+), 42 deletions(-) diff --git a/tests/source/type-ascription.rs b/tests/source/type-ascription.rs index 4874094ccc4c4..fbdde272cb62f 100644 --- a/tests/source/type-ascription.rs +++ b/tests/source/type-ascription.rs @@ -1,10 +1,10 @@ - +// #101728, we remove type ascription, so this test case is changed to `var as ty` fn main() { - let xxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy : SomeTrait; + let xxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy as SomeTrait; - let xxxxxxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + let xxxxxxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy as AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww): AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww) as AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - x : u32 - 1u32 / 10f32 : u32 + let _ = x as u32 - 1u32 / (10f32 as u32); } diff --git a/tests/target/configs/format_macro_bodies/true.rs b/tests/target/configs/format_macro_bodies/true.rs index 9dc2524c38961..17ac1498c932c 100644 --- a/tests/target/configs/format_macro_bodies/true.rs +++ b/tests/target/configs/format_macro_bodies/true.rs @@ -1,10 +1,6 @@ // rustfmt-format_macro_bodies: true macro_rules! foo { - ($a: ident : $b: ty) => { - $a(42): $b; - }; - ($a: ident $b: ident $c: ident) => { - $a = $b + $c; - }; + ($a: ident : $b: ty) => { $a(42): $b; }; + ($a: ident $b: ident $c: ident) => { $a=$b+$c; }; } diff --git a/tests/target/configs/format_macro_matchers/false.rs b/tests/target/configs/format_macro_matchers/false.rs index 3966d21be7563..01ecac9879d69 100644 --- a/tests/target/configs/format_macro_matchers/false.rs +++ b/tests/target/configs/format_macro_matchers/false.rs @@ -1,10 +1,6 @@ // rustfmt-format_macro_matchers: false macro_rules! foo { - ($a: ident : $b: ty) => { - $a(42): $b; - }; - ($a: ident $b: ident $c: ident) => { - $a = $b + $c; - }; + ($a: ident : $b: ty) => { $a(42): $b; }; + ($a: ident $b: ident $c: ident) => { $a=$b+$c; }; } diff --git a/tests/target/configs/format_macro_matchers/true.rs b/tests/target/configs/format_macro_matchers/true.rs index e113af96f26be..fa0442e228ac8 100644 --- a/tests/target/configs/format_macro_matchers/true.rs +++ b/tests/target/configs/format_macro_matchers/true.rs @@ -1,10 +1,6 @@ // rustfmt-format_macro_matchers: true macro_rules! foo { - ($a:ident : $b:ty) => { - $a(42): $b; - }; - ($a:ident $b:ident $c:ident) => { - $a = $b + $c; - }; + ($a: ident : $b: ty) => { $a(42): $b; }; + ($a: ident $b: ident $c: ident) => { $a=$b+$c; }; } diff --git a/tests/target/macros.rs b/tests/target/macros.rs index e930b5037d930..7b4574349df3e 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -122,7 +122,7 @@ fn main() { 20, 21, 22); // #1092 - chain!(input, a: take!(max_size), || []); + chain!(input, a:take!(max_size), || []); // #2727 foo!("bar"); @@ -156,17 +156,13 @@ fn issue1178() { } fn issue1739() { - sql_function!( - add_rss_item, - add_rss_item_t, - ( - a: types::Integer, - b: types::Timestamptz, - c: types::Text, - d: types::Text, - e: types::Text - ) - ); + sql_function!(add_rss_item, + add_rss_item_t, + (a: types::Integer, + b: types::Timestamptz, + c: types::Text, + d: types::Text, + e: types::Text)); w.slice_mut(s![ .., @@ -232,7 +228,7 @@ fn issue_3174() { "debugMessage": debug.message, }) } else { - json!({ "errorKind": format!("{:?}", error.err_kind()) }) + json!({"errorKind": format!("{:?}", error.err_kind())}) }; } diff --git a/tests/target/type-ascription.rs b/tests/target/type-ascription.rs index a2f082ba4b497..99dc033686478 100644 --- a/tests/target/type-ascription.rs +++ b/tests/target/type-ascription.rs @@ -1,12 +1,13 @@ +// #101728, we remove type ascription, so this test case is changed to `var as ty` fn main() { let xxxxxxxxxxx = - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: SomeTrait; + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy as SomeTrait; let xxxxxxxxxxxxxxx = - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy as AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww): - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww) + as AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - x: u32 - 1u32 / 10f32: u32 + let _ = x as u32 - 1u32 / (10f32 as u32); } diff --git a/tests/target/type.rs b/tests/target/type.rs index 38cf909c2587a..c789ecb055a7d 100644 --- a/tests/target/type.rs +++ b/tests/target/type.rs @@ -129,7 +129,7 @@ fn issue3117() { fn issue3139() { assert_eq!( to_json_value(&None::).unwrap(), - json!({ "test": None:: }) + json!( { "test": None :: } ) ); } From 9d20134a781b4b61b45276ab6f104c3dcbe9dc82 Mon Sep 17 00:00:00 2001 From: yukang Date: Tue, 4 Apr 2023 11:41:53 +0800 Subject: [PATCH 41/58] remove rustfmt testcase for type ascription --- tests/source/type-ascription.rs | 10 ---------- tests/target/type-ascription.rs | 13 ------------- 2 files changed, 23 deletions(-) delete mode 100644 tests/source/type-ascription.rs delete mode 100644 tests/target/type-ascription.rs diff --git a/tests/source/type-ascription.rs b/tests/source/type-ascription.rs deleted file mode 100644 index fbdde272cb62f..0000000000000 --- a/tests/source/type-ascription.rs +++ /dev/null @@ -1,10 +0,0 @@ -// #101728, we remove type ascription, so this test case is changed to `var as ty` -fn main() { - let xxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy as SomeTrait; - - let xxxxxxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy as AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - - let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww) as AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - - let _ = x as u32 - 1u32 / (10f32 as u32); -} diff --git a/tests/target/type-ascription.rs b/tests/target/type-ascription.rs deleted file mode 100644 index 99dc033686478..0000000000000 --- a/tests/target/type-ascription.rs +++ /dev/null @@ -1,13 +0,0 @@ -// #101728, we remove type ascription, so this test case is changed to `var as ty` -fn main() { - let xxxxxxxxxxx = - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy as SomeTrait; - - let xxxxxxxxxxxxxxx = - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy as AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - - let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww) - as AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - - let _ = x as u32 - 1u32 / (10f32 as u32); -} From 34a71f67d1e28fe0bf13593e26b682d097678875 Mon Sep 17 00:00:00 2001 From: jyn Date: Sat, 29 Apr 2023 06:29:07 -0500 Subject: [PATCH 42/58] Make the BUG_REPORT_URL configurable by tools This greatly simplifies how hard it is to set a custom bug report url; previously tools had to copy the entire hook implementation. - Switch clippy to the new hook This also adds a `extra_info` callback so clippy can include its own version number, which differs from rustc's. - Call `install_ice_hook` in rustfmt --- src/bin/main.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/bin/main.rs b/src/bin/main.rs index be64559e87745..47846424b06e4 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -1,3 +1,5 @@ +#![feature(rustc_private)] + use anyhow::{format_err, Result}; use io::Error as IoError; @@ -19,7 +21,14 @@ use crate::rustfmt::{ FormatReportFormatterBuilder, Input, Session, Verbosity, }; +const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rustfmt/issues/new?labels=bug"; + +// N.B. these crates are loaded from the sysroot, so they need extern crate. +extern crate rustc_driver; + fn main() { + rustc_driver::install_ice_hook(BUG_REPORT_URL, |_| ()); + env_logger::Builder::from_env("RUSTFMT_LOG").init(); let opts = make_opts(); From 8e330f9d5bb92b24afde750480b5d70d6c892da5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 25 Apr 2023 06:02:49 +0000 Subject: [PATCH 43/58] Make tools happy --- src/types.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/types.rs b/src/types.rs index 01e2fb6e61e15..9ebe38cc25f7f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -552,6 +552,8 @@ impl Rewrite for ast::GenericBound { ast::TraitBoundModifier::MaybeConstMaybe => poly_trait_ref .rewrite(context, shape.offset_left(8)?) .map(|s| format!("~const ?{}", s)), + rustc_ast::TraitBoundModifier::Negative + | rustc_ast::TraitBoundModifier::MaybeConstNegative => None, }; rewrite.map(|s| if has_paren { format!("({})", s) } else { s }) } From 8ed5d5de3d4e2cf94ddd00cee922d8533d23c1dd Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 26 Apr 2023 22:37:36 +0000 Subject: [PATCH 44/58] Rustfmt support for negative bounds, test --- src/types.rs | 8 ++++++-- tests/target/negative-bounds.rs | 11 +++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 tests/target/negative-bounds.rs diff --git a/src/types.rs b/src/types.rs index 9ebe38cc25f7f..f548388ed8ba2 100644 --- a/src/types.rs +++ b/src/types.rs @@ -552,8 +552,12 @@ impl Rewrite for ast::GenericBound { ast::TraitBoundModifier::MaybeConstMaybe => poly_trait_ref .rewrite(context, shape.offset_left(8)?) .map(|s| format!("~const ?{}", s)), - rustc_ast::TraitBoundModifier::Negative - | rustc_ast::TraitBoundModifier::MaybeConstNegative => None, + ast::TraitBoundModifier::Negative => poly_trait_ref + .rewrite(context, shape.offset_left(1)?) + .map(|s| format!("!{}", s)), + ast::TraitBoundModifier::MaybeConstNegative => poly_trait_ref + .rewrite(context, shape.offset_left(8)?) + .map(|s| format!("~const !{}", s)), }; rewrite.map(|s| if has_paren { format!("({})", s) } else { s }) } diff --git a/tests/target/negative-bounds.rs b/tests/target/negative-bounds.rs new file mode 100644 index 0000000000000..4fb35cccf6684 --- /dev/null +++ b/tests/target/negative-bounds.rs @@ -0,0 +1,11 @@ +fn negative() +where + i32: !Copy, +{ +} + +fn maybe_const_negative() +where + i32: ~const !Copy, +{ +} From e903fcdaae20292d307605ee82ec793253adf4fa Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 4 Jun 2023 09:09:28 -0700 Subject: [PATCH 45/58] Remove rustc-workspace-hack --- Cargo.lock | 7 ------- Cargo.toml | 5 ----- 2 files changed, 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 24166d51c51fa..5b0fd5ae7352c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -468,12 +468,6 @@ version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" -[[package]] -name = "rustc-workspace-hack" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc71d2faa173b74b232dedc235e3ee1696581bb132fc116fa3626d6151a1a8fb" - [[package]] name = "rustfmt-config_proc_macro" version = "0.3.0" @@ -502,7 +496,6 @@ dependencies = [ "lazy_static", "log", "regex", - "rustc-workspace-hack", "rustfmt-config_proc_macro", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index 87ce59d0217e8..12ed65453e19e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,11 +59,6 @@ unicode_categories = "0.1" rustfmt-config_proc_macro = { version = "0.3", path = "config_proc_macro" } -# A noop dependency that changes in the Rust repository, it's a bit of a hack. -# See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` -# for more information. -rustc-workspace-hack = "1.0.0" - # Rustc dependencies are loaded from the sysroot, Cargo doesn't know about them. [package.metadata.rust-analyzer] From 5f9de6bfc9f1a3308d97bf6598acd56229cbe293 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 10 Jun 2023 17:27:24 +0000 Subject: [PATCH 46/58] Recover comments between attrs and generic param Fixes #5320. --- src/overflow.rs | 4 ++ src/types.rs | 76 +++++++++++++++++------------ tests/target/doc-of-generic-item.rs | 18 +++++++ 3 files changed, 67 insertions(+), 31 deletions(-) diff --git a/src/overflow.rs b/src/overflow.rs index af0b95430a197..d81bf24dbd1cd 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -589,6 +589,8 @@ impl<'a> Context<'a> { fn rewrite_items(&self) -> Option<(bool, String)> { let span = self.items_span(); + debug!("items: {:?}", self.items); + let items = itemize_list( self.context.snippet_provider, self.items.iter(), @@ -603,6 +605,8 @@ impl<'a> Context<'a> { ); let mut list_items: Vec<_> = items.collect(); + debug!("items: {list_items:?}"); + // Try letting the last argument overflow to the next line with block // indentation. If its first line fits on one line with the other arguments, // we format the function arguments horizontally. diff --git a/src/types.rs b/src/types.rs index 01e2fb6e61e15..b4be6546efbdb 100644 --- a/src/types.rs +++ b/src/types.rs @@ -572,49 +572,41 @@ impl Rewrite for ast::GenericBounds { impl Rewrite for ast::GenericParam { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - let mut result = String::with_capacity(128); // FIXME: If there are more than one attributes, this will force multiline. - match self.attrs.rewrite(context, shape) { - Some(ref rw) if !rw.is_empty() => { - result.push_str(rw); - // When rewriting generic params, an extra newline should be put - // if the attributes end with a doc comment - if let Some(true) = self.attrs.last().map(|a| a.is_doc_comment()) { - result.push_str(&shape.indent.to_string_with_newline(context.config)); - } else { - result.push(' '); - } - } - _ => (), - } + let mut result = self.attrs.rewrite(context, shape).unwrap_or(String::new()); + let has_attrs = !result.is_empty(); - if let ast::GenericParamKind::Const { + let mut param = String::with_capacity(128); + + let param_start = if let ast::GenericParamKind::Const { ref ty, - kw_span: _, + kw_span, default, } = &self.kind { - result.push_str("const "); - result.push_str(rewrite_ident(context, self.ident)); - result.push_str(": "); - result.push_str(&ty.rewrite(context, shape)?); + param.push_str("const "); + param.push_str(rewrite_ident(context, self.ident)); + param.push_str(": "); + param.push_str(&ty.rewrite(context, shape)?); if let Some(default) = default { let eq_str = match context.config.type_punctuation_density() { TypeDensity::Compressed => "=", TypeDensity::Wide => " = ", }; - result.push_str(eq_str); - let budget = shape.width.checked_sub(result.len())?; + param.push_str(eq_str); + let budget = shape.width.checked_sub(param.len())?; let rewrite = default.rewrite(context, Shape::legacy(budget, shape.indent))?; - result.push_str(&rewrite); + param.push_str(&rewrite); } + kw_span.lo() } else { - result.push_str(rewrite_ident(context, self.ident)); - } + param.push_str(rewrite_ident(context, self.ident)); + self.ident.span.lo() + }; if !self.bounds.is_empty() { - result.push_str(type_bound_colon(context)); - result.push_str(&self.bounds.rewrite(context, shape)?) + param.push_str(type_bound_colon(context)); + param.push_str(&self.bounds.rewrite(context, shape)?) } if let ast::GenericParamKind::Type { default: Some(ref def), @@ -624,11 +616,33 @@ impl Rewrite for ast::GenericParam { TypeDensity::Compressed => "=", TypeDensity::Wide => " = ", }; - result.push_str(eq_str); - let budget = shape.width.checked_sub(result.len())?; + param.push_str(eq_str); + let budget = shape.width.checked_sub(param.len())?; let rewrite = - def.rewrite(context, Shape::legacy(budget, shape.indent + result.len()))?; - result.push_str(&rewrite); + def.rewrite(context, Shape::legacy(budget, shape.indent + param.len()))?; + param.push_str(&rewrite); + } + + if let Some(last_attr) = self.attrs.last().filter(|last_attr| { + contains_comment(context.snippet(mk_sp(last_attr.span.hi(), param_start))) + }) { + result = combine_strs_with_missing_comments( + context, + &result, + ¶m, + mk_sp(last_attr.span.hi(), param_start), + shape, + !last_attr.is_doc_comment(), + )?; + } else { + // When rewriting generic params, an extra newline should be put + // if the attributes end with a doc comment + if let Some(true) = self.attrs.last().map(|a| a.is_doc_comment()) { + result.push_str(&shape.indent.to_string_with_newline(context.config)); + } else if has_attrs { + result.push(' '); + } + result.push_str(¶m); } Some(result) diff --git a/tests/target/doc-of-generic-item.rs b/tests/target/doc-of-generic-item.rs index 2efc5e09a3d34..80886e74f83e3 100644 --- a/tests/target/doc-of-generic-item.rs +++ b/tests/target/doc-of-generic-item.rs @@ -12,3 +12,21 @@ struct Foo< /// doc of N const N: item, >; + +// Non-doc pre-comment of Foo +/// doc of Foo +// Non-doc post-comment of Foo +struct Foo< + // Non-doc pre-comment of 'a + /// doc of 'a + // Non-doc post-comment of 'a + 'a, + // Non-doc pre-comment of T + /// doc of T + // Non-doc post-comment of T + T, + // Non-doc pre-comment of N + /// doc of N + // Non-doc post-comment of N + const N: item, +>; From 0441cc21e3b0ce457d030aedd2cc7776fef047c1 Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Wed, 26 Apr 2023 20:23:08 -0400 Subject: [PATCH 47/58] Add release notes for closed PRs with `release-notes` label --- CHANGELOG.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60f961fa12ac8..932fdc33d2428 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,41 @@ ## [Unreleased] +### Fixed + +- When formatting doc comments with `wrap_comments = true` rustfmt will no longer wrap markdown tables [#4210](https://github.com/rust-lang/rustfmt/issues/4210) +- rustfmt will no longer use shorthand initialization when rewriting a tuple struct even when `use_field_init_shorthand = true` as this lead to code that could no longer compile. + Take the following struct as an example `struct MyStruct(u64);`. rustfmt will no longer format `MyStruct { 0: 0 }` as `MyStruct { 0 }` [#5488](https://github.com/rust-lang/rustfmt/issues/5488) +- rustfmt no longer panics when formatting an empty code block in a doc comment with `format_code_in_doc_comments = true` [#5234](https://github.com/rust-lang/rustfmt/issues/5234). For example: + ```rust + /// ``` + /// + /// ``` + fn main() {} + ``` +- Use the correct span when rewriting struct generics. This prevents rustfmt from incorrectly duplicating where clause bounds when using const expression in where clause bounds with feature `#![feature(generic_const_exprs)]` [#5691](https://github.com/rust-lang/rustfmt/issues/5691). e.g.: + ```rust + struct S + where + [(); { num_slots!(C) }]:, { + // code ... + } + ``` + +### Changed + +- Users can now control whether rustc parser errors are displayed with color using rustfmt's `--color` option. To disable colored errors pass `--color=Never` to rustfmt [#5717](https://github.com/rust-lang/rustfmt/issues/5717) + + +### Added + +- rustfmt now recognises `+` as the start of a markdown list, and won't incorrectly wrap sublists that begin with `+` when formatting doc comments with `wrap_comments = true` [#5560](https://github.com/rust-lang/rustfmt/pull/5560) + +### Misc + +- Prevent ICE when parsing invalid attributes in `cfg_if!` macros [#5728](https://github.com/rust-lang/rustfmt/issues/5728) + + ## [1.5.2] 2023-01-24 ### Fixed @@ -56,6 +91,8 @@ - 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) + ### Fixed - Remove duplicate imports when `imports_granularity` is set to `Item` [#4725](https://github.com/rust-lang/rustfmt/issues/4725) From c9ebd6ce262ec37c46ff50ac3c56ba19a99254df Mon Sep 17 00:00:00 2001 From: xxchan Date: Mon, 19 Jun 2023 16:29:57 +0200 Subject: [PATCH 48/58] doc: remove installing from source also add "run from source" in contributing.md --- Contributing.md | 10 ++++++++++ README.md | 18 ------------------ 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/Contributing.md b/Contributing.md index 3073996019ee2..b986a887c92ff 100644 --- a/Contributing.md +++ b/Contributing.md @@ -91,6 +91,16 @@ Please try to avoid leaving `TODO`s in the code. There are a few around, but I wish there weren't. You can leave `FIXME`s, preferably with an issue number. +### Run Rustfmt from source code + +You may want to run a version of rustfmt from source code as part of a test or +hacking on the rustfmt codebase. It's strongly discouraged to install a version +of rustfmt from source. Instead, run it using `cargo run`, and `--manifest-path`. + +``` +cargo run --bin cargo-fmt -- --manifest-path path/to/project/you/want2test/Cargo.toml +``` + ### Version-gate formatting changes A change that introduces a different code-formatting should be gated on the diff --git a/README.md b/README.md index ef835371b02a8..c05184fbb04b8 100644 --- a/README.md +++ b/README.md @@ -71,24 +71,6 @@ because in the future Rustfmt might work on code where it currently does not): fixes to break our stability guarantees). -## Installation - -```sh -rustup component add rustfmt -``` - -## Installing from source - -To install from source (nightly required), first checkout to the tag or branch you want to install, then issue - -```sh -cargo install --path . -``` - -This will install `rustfmt` in your `~/.cargo/bin`. Make sure to add `~/.cargo/bin` directory to -your PATH variable. - - ## Running You can run Rustfmt by just typing `rustfmt filename` if you used `cargo From 8d95c269ed83da89c53cef4fd17cca88e7ab1aa8 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 12 Apr 2023 18:52:57 +0800 Subject: [PATCH 49/58] update config_proc_macro to use `syn` 2.0 --- config_proc_macro/Cargo.lock | 30 +++++++++++++++--------------- config_proc_macro/Cargo.toml | 4 ++-- config_proc_macro/src/attrs.rs | 18 +++++++++--------- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/config_proc_macro/Cargo.lock b/config_proc_macro/Cargo.lock index 49f2f72a8d219..7af746f0c9659 100644 --- a/config_proc_macro/Cargo.lock +++ b/config_proc_macro/Cargo.lock @@ -4,18 +4,18 @@ version = 3 [[package]] name = "proc-macro2" -version = "1.0.3" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e98a83a9f9b331f54b924e68a66acb1bb35cb01fb0a23645139967abefb697e8" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] name = "quote" -version = "1.0.2" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" dependencies = [ "proc-macro2", ] @@ -32,18 +32,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.99" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f" +checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.99" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4dc18c61206b08dc98216c98faa0232f4337e1e1b8574551d5bad29ea1b425" +checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" dependencies = [ "proc-macro2", "quote", @@ -52,17 +52,17 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.5" +version = "2.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" +checksum = "fcf316d5356ed6847742d036f8a39c3b8435cac10bd528a4bd461928a6ab34d5" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] -name = "unicode-xid" -version = "0.2.0" +name = "unicode-ident" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" diff --git a/config_proc_macro/Cargo.toml b/config_proc_macro/Cargo.toml index d10d0469cc401..34e8c237f5564 100644 --- a/config_proc_macro/Cargo.toml +++ b/config_proc_macro/Cargo.toml @@ -13,10 +13,10 @@ proc-macro = true [dependencies] proc-macro2 = "1.0" quote = "1.0" -syn = { version = "1.0", features = ["full", "visit"] } +syn = { version = "2.0", features = ["full", "visit"] } [dev-dependencies] -serde = { version = "1.0", features = ["derive"] } +serde = { version = "1.0.160", features = ["derive"] } [features] default = [] diff --git a/config_proc_macro/src/attrs.rs b/config_proc_macro/src/attrs.rs index dd18ff572cb1c..d8de9aae088d7 100644 --- a/config_proc_macro/src/attrs.rs +++ b/config_proc_macro/src/attrs.rs @@ -51,26 +51,26 @@ pub fn is_unstable_variant(attr: &syn::Attribute) -> bool { } fn is_attr_name_value(attr: &syn::Attribute, name: &str) -> bool { - attr.parse_meta().ok().map_or(false, |meta| match meta { - syn::Meta::NameValue(syn::MetaNameValue { ref path, .. }) if path.is_ident(name) => true, + match &attr.meta { + syn::Meta::NameValue(syn::MetaNameValue { path, .. }) if path.is_ident(name) => true, _ => false, - }) + } } fn is_attr_path(attr: &syn::Attribute, name: &str) -> bool { - attr.parse_meta().ok().map_or(false, |meta| match meta { + match &attr.meta { syn::Meta::Path(path) if path.is_ident(name) => true, _ => false, - }) + } } fn get_name_value_str_lit(attr: &syn::Attribute, name: &str) -> Option { - attr.parse_meta().ok().and_then(|meta| match meta { + match &attr.meta { syn::Meta::NameValue(syn::MetaNameValue { - ref path, - lit: syn::Lit::Str(ref lit_str), + path, + value: syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Str(lit_str), .. }), .. }) if path.is_ident(name) => Some(lit_str.value()), _ => None, - }) + } } From 7d48be355a6342690b48fc0675103ae822024e71 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 12 Apr 2023 18:54:32 +0800 Subject: [PATCH 50/58] bump deps to new versions that use syn 2.0 --- Cargo.toml | 6 +++--- src/cargo-fmt/main.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 12ed65453e19e..78b970c4c9836 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ annotate-snippets = { version = "0.9", features = ["color"] } anyhow = "1.0" bytecount = "0.6" cargo_metadata = "0.14" -clap = { version = "3.1", features = ["derive"] } +clap = { version = "4.2.1", features = ["derive"] } derive-new = "0.5" diff = "0.1" dirs = "4.0" @@ -48,10 +48,10 @@ itertools = "0.10" lazy_static = "1.4" log = "0.4" regex = "1.5" -serde = { version = "1.0", features = ["derive"] } +serde = { version = "1.0.160", features = ["derive"] } serde_json = "1.0" term = "0.7" -thiserror = "1.0" +thiserror = "1.0.40" toml = "0.5" unicode-segmentation = "1.9" unicode-width = "0.1" diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 2b714b68df00e..a106181ec7eb6 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -14,7 +14,7 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::str; -use clap::{AppSettings, CommandFactory, Parser}; +use clap::{CommandFactory, Parser}; #[path = "test/mod.rs"] #[cfg(test)] @@ -22,7 +22,7 @@ mod cargo_fmt_tests; #[derive(Parser)] #[clap( - global_setting(AppSettings::NoAutoVersion), + disable_version_flag = true, bin_name = "cargo fmt", about = "This utility formats all bin and lib files of \ the current crate using rustfmt." @@ -45,7 +45,7 @@ pub struct Opts { short = 'p', long = "package", value_name = "package", - multiple_values = true + num_args = 1.. )] packages: Vec, From a463f231f5410ceca88f3eb5dfb8a85b97a63b25 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 12 Apr 2023 18:55:07 +0800 Subject: [PATCH 51/58] remove `derive_new` dependency --- Cargo.lock | 422 +++++++++++++++++++++++++++++----------- Cargo.toml | 1 - src/attr/doc_comment.rs | 7 +- src/formatting.rs | 17 +- src/lib.rs | 2 - src/macros.rs | 5 +- src/pairs.rs | 9 +- 7 files changed, 346 insertions(+), 117 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5b0fd5ae7352c..8487dc58b4ed3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,6 +21,46 @@ dependencies = [ "yansi-term", ] +[[package]] +name = "anstream" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "342258dd14006105c2b75ab1bd7543a03bdf0cfc94383303ac212a04939dff6f" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-wincon", + "concolor-override", + "concolor-query", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23ea9e81bd02e310c216d080f6223c179012256e5151c41db88d12c88a1684d2" + +[[package]] +name = "anstyle-parse" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7d1bb534e9efed14f3e5f44e7dd1a4f709384023a4165199a4241e18dff0116" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-wincon" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3127af6145b149f3287bb9a0d10ad9c5692dba8c53ad48285e5bec4063834fa" +dependencies = [ + "anstyle", + "windows-sys 0.45.0", +] + [[package]] name = "anyhow" version = "1.0.56" @@ -33,17 +73,11 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - [[package]] name = "bitflags" version = "1.3.2" @@ -99,6 +133,12 @@ dependencies = [ "serde_json", ] +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + [[package]] name = "cfg-if" version = "1.0.0" @@ -107,53 +147,69 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "3.1.8" +version = "4.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71c47df61d9e16dc010b55dba1952a57d8c215dbb533fd13cdd13369aac73b1c" +checksum = "046ae530c528f252094e4a77886ee1374437744b2bff1497aa898bbddbbb29b3" dependencies = [ - "atty", - "bitflags", + "clap_builder", "clap_derive", - "indexmap", - "lazy_static", - "os_str_bytes", + "once_cell", +] + +[[package]] +name = "clap_builder" +version = "4.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "223163f58c9a40c3b0a43e1c4b50a9ce09f007ea2cb1ec258a687945b4b7929f" +dependencies = [ + "anstream", + "anstyle", + "bitflags", + "clap_lex", "strsim", - "termcolor", - "textwrap", ] [[package]] name = "clap_derive" -version = "3.1.7" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3aab4734e083b809aaf5794e14e756d1c798d2c69c7f7de7a09a2f5214993c1" +checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" dependencies = [ "heck", - "proc-macro-error", "proc-macro2", "quote", "syn", ] [[package]] -name = "crossbeam-utils" -version = "0.8.8" +name = "clap_lex" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" + +[[package]] +name = "concolor-override" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a855d4a1978dc52fb0536a04d384c2c0c1aa273597f08b77c8c4d3b2eec6037f" + +[[package]] +name = "concolor-query" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d11d52c3d7ca2e6d0040212be9e4dbbcd78b6447f535b6b561f449427944cf" dependencies = [ - "cfg-if", - "lazy_static", + "windows-sys 0.45.0", ] [[package]] -name = "derive-new" -version = "0.5.9" +name = "crossbeam-utils" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" dependencies = [ - "proc-macro2", - "quote", - "syn", + "cfg-if", + "lazy_static", ] [[package]] @@ -222,6 +278,27 @@ dependencies = [ "termcolor", ] +[[package]] +name = "errno" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "fnv" version = "1.0.7" @@ -261,12 +338,6 @@ dependencies = [ "regex", ] -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" - [[package]] name = "heck" version = "0.4.0" @@ -282,6 +353,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + [[package]] name = "humantime" version = "2.1.0" @@ -307,13 +384,26 @@ dependencies = [ ] [[package]] -name = "indexmap" -version = "1.8.1" +name = "io-lifetimes" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" +checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" dependencies = [ - "autocfg", - "hashbrown", + "hermit-abi 0.3.1", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "is-terminal" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +dependencies = [ + "hermit-abi 0.3.1", + "io-lifetimes", + "rustix", + "windows-sys 0.48.0", ] [[package]] @@ -339,9 +429,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.122" +version = "0.2.141" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec647867e2bf0772e28c8bcde4f0d19a9216916e890543b5a03ed8ef27b8f259" +checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" [[package]] name = "libm" @@ -349,6 +439,12 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" +[[package]] +name = "linux-raw-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" + [[package]] name = "log" version = "0.4.16" @@ -366,18 +462,9 @@ checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "once_cell" -version = "1.10.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" - -[[package]] -name = "os_str_bytes" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" -dependencies = [ - "memchr", -] +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "packed_simd_2" @@ -389,44 +476,20 @@ dependencies = [ "libm", ] -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - [[package]] name = "proc-macro2" -version = "1.0.37" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] name = "quote" -version = "1.0.17" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" dependencies = [ "proc-macro2", ] @@ -486,7 +549,6 @@ dependencies = [ "bytecount", "cargo_metadata", "clap", - "derive-new", "diff", "dirs", "env_logger", @@ -507,6 +569,20 @@ dependencies = [ "unicode_categories", ] +[[package]] +name = "rustix" +version = "0.37.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.48.0", +] + [[package]] name = "rustversion" version = "1.0.6" @@ -539,18 +615,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.136" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.136" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" dependencies = [ "proc-macro2", "quote", @@ -576,13 +652,13 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.91" +version = "2.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d" +checksum = "fcf316d5356ed6847742d036f8a39c3b8435cac10bd528a4bd461928a6ab34d5" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] @@ -605,26 +681,20 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "textwrap" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" - [[package]] name = "thiserror" -version = "1.0.30" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.30" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", @@ -649,6 +719,12 @@ dependencies = [ "serde", ] +[[package]] +name = "unicode-ident" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" + [[package]] name = "unicode-segmentation" version = "1.9.0" @@ -661,12 +737,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - [[package]] name = "unicode_categories" version = "0.1.1" @@ -674,10 +744,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" [[package]] -name = "version_check" -version = "0.9.4" +name = "utf8parse" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "walkdir" @@ -727,6 +797,138 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.0", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + [[package]] name = "yansi-term" version = "0.1.2" diff --git a/Cargo.toml b/Cargo.toml index 78b970c4c9836..0093b975e8628 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,6 @@ anyhow = "1.0" bytecount = "0.6" cargo_metadata = "0.14" clap = { version = "4.2.1", features = ["derive"] } -derive-new = "0.5" diff = "0.1" dirs = "4.0" env_logger = "0.9" diff --git a/src/attr/doc_comment.rs b/src/attr/doc_comment.rs index f653a12a8afeb..25c8158df8c50 100644 --- a/src/attr/doc_comment.rs +++ b/src/attr/doc_comment.rs @@ -2,12 +2,17 @@ use crate::comment::CommentStyle; use std::fmt::{self, Display}; /// Formats a string as a doc comment using the given [`CommentStyle`]. -#[derive(new)] pub(super) struct DocCommentFormatter<'a> { literal: &'a str, style: CommentStyle<'a>, } +impl<'a> DocCommentFormatter<'a> { + pub(super) const fn new(literal: &'a str, style: CommentStyle<'a>) -> Self { + Self { literal, style } + } +} + impl Display for DocCommentFormatter<'_> { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { let opener = self.style.opener().trim_end(); diff --git a/src/formatting.rs b/src/formatting.rs index 1dfd8a514f0bc..1f4ad6960e207 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -175,7 +175,6 @@ fn format_project( } // Used for formatting files. -#[derive(new)] struct FormatContext<'a, T: FormatHandler> { krate: &'a ast::Crate, report: FormatReport, @@ -185,6 +184,22 @@ struct FormatContext<'a, T: FormatHandler> { } impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { + fn new( + krate: &'a ast::Crate, + report: FormatReport, + parse_session: ParseSess, + config: &'a Config, + handler: &'a mut T, + ) -> Self { + FormatContext { + krate, + report, + parse_session, + config, + handler, + } + } + fn ignore_file(&self, path: &FileName) -> bool { self.parse_session.ignore_file(path) } diff --git a/src/lib.rs b/src/lib.rs index 487fcc3a0df1a..0f111f32a4a44 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,8 +4,6 @@ #![recursion_limit = "256"] #![allow(clippy::match_like_matches_macro)] -#[macro_use] -extern crate derive_new; #[cfg(test)] #[macro_use] extern crate lazy_static; diff --git a/src/macros.rs b/src/macros.rs index d58f7547fefb3..5e8bbee7722e9 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1119,12 +1119,15 @@ pub(crate) fn macro_style(mac: &ast::MacCall, context: &RewriteContext<'_>) -> D // A very simple parser that just parses a macros 2.0 definition into its branches. // Currently we do not attempt to parse any further than that. -#[derive(new)] struct MacroParser { toks: Cursor, } impl MacroParser { + const fn new(toks: Cursor) -> Self { + Self { toks } + } + // (`(` ... `)` `=>` `{` ... `}`)* fn parse(&mut self) -> Option { let mut branches = vec![]; diff --git a/src/pairs.rs b/src/pairs.rs index d1c75126ea4a7..d135da7e35919 100644 --- a/src/pairs.rs +++ b/src/pairs.rs @@ -9,7 +9,7 @@ use crate::utils::{ }; /// Sigils that decorate a binop pair. -#[derive(new, Clone, Copy)] +#[derive(Clone, Copy)] pub(crate) struct PairParts<'a> { prefix: &'a str, infix: &'a str, @@ -17,6 +17,13 @@ pub(crate) struct PairParts<'a> { } impl<'a> PairParts<'a> { + pub(crate) const fn new(prefix: &'a str, infix: &'a str, suffix: &'a str) -> Self { + Self { + prefix, + infix, + suffix, + } + } pub(crate) fn infix(infix: &'a str) -> PairParts<'a> { PairParts { prefix: "", From ac2ebd3a78246d2dab16aec39d2aaace618a17eb Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Thu, 30 Mar 2023 13:18:28 -0400 Subject: [PATCH 52/58] Prevent ICE when calling parse_attribute without an attribute Fixes 5729 `parse_attribute` will panic if the first token is not a `#`. To prevent this we return early instead of trying to parse an invalid attribute. --- src/parse/macros/cfg_if.rs | 5 +++++ tests/rustfmt/main.rs | 2 +- tests/target/issue_5729.rs | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 tests/target/issue_5729.rs diff --git a/src/parse/macros/cfg_if.rs b/src/parse/macros/cfg_if.rs index ac03409a7844b..cbc4c90b8f984 100644 --- a/src/parse/macros/cfg_if.rs +++ b/src/parse/macros/cfg_if.rs @@ -34,6 +34,11 @@ fn parse_cfg_if_inner<'a>( if !parser.eat_keyword(kw::If) { return Err("Expected `if`"); } + + if !matches!(parser.token.kind, TokenKind::Pound) { + return Err("Failed to parse attributes"); + } + // Inner attributes are not actually syntactically permitted here, but we don't // care about inner vs outer attributes in this position. Our purpose with this // special case parsing of cfg_if macros is to ensure we can correctly resolve diff --git a/tests/rustfmt/main.rs b/tests/rustfmt/main.rs index f00b0e09604fe..4936a7174636f 100644 --- a/tests/rustfmt/main.rs +++ b/tests/rustfmt/main.rs @@ -178,7 +178,7 @@ fn rustfmt_emits_error_on_line_overflow_true() { #[test] #[allow(non_snake_case)] fn dont_emit_ICE() { - let files = ["tests/target/issue_5728.rs"]; + let files = ["tests/target/issue_5728.rs", "tests/target/issue_5729.rs"]; for file in files { let args = [file]; diff --git a/tests/target/issue_5729.rs b/tests/target/issue_5729.rs new file mode 100644 index 0000000000000..d63c83e88f846 --- /dev/null +++ b/tests/target/issue_5729.rs @@ -0,0 +1,5 @@ +cfg_if::cfg_if! { + if { + } else if #(&cpus) { + } else [libc::CTL_HW, libc::HW_NCPU, 0, 0] +} From 2c30fa5a8292ab5d32a3b1129c9ab897897b1689 Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Tue, 7 Feb 2023 18:43:07 -0500 Subject: [PATCH 53/58] Adjust enum variant spans to exclude any explicit discriminant Fixes 5686 For reference, explicit discriminants were proposed in [RFC-2363]. `ast::Variant` spans extend to include explicit discriminants when they are present. Now we'll adjust the span of enum variants to exclude any explicit discriminant. [RFC-2363]: https://rust-lang.github.io/rfcs/2363-arbitrary-enum-discriminant.html --- src/items.rs | 25 ++++++++++++++++++++--- tests/source/issue_5686.rs | 40 ++++++++++++++++++++++++++++++++++++ tests/target/issue_5686.rs | 42 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 tests/source/issue_5686.rs create mode 100644 tests/target/issue_5686.rs diff --git a/src/items.rs b/src/items.rs index 3c5293b6bf5a7..714bcbc10b42e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -560,7 +560,7 @@ impl<'a> FmtVisitor<'a> { let variant_body = match field.data { ast::VariantData::Tuple(..) | ast::VariantData::Struct(..) => format_struct( &context, - &StructParts::from_variant(field), + &StructParts::from_variant(field, &context), self.block_indent, Some(one_line_width), )?, @@ -951,14 +951,14 @@ impl<'a> StructParts<'a> { format_header(context, self.prefix, self.ident, self.vis, offset) } - fn from_variant(variant: &'a ast::Variant) -> Self { + fn from_variant(variant: &'a ast::Variant, context: &RewriteContext<'_>) -> Self { StructParts { prefix: "", ident: variant.ident, vis: &DEFAULT_VISIBILITY, def: &variant.data, generics: None, - span: variant.span, + span: enum_variant_span(variant, context), } } @@ -979,6 +979,25 @@ impl<'a> StructParts<'a> { } } +fn enum_variant_span(variant: &ast::Variant, context: &RewriteContext<'_>) -> Span { + use ast::VariantData::*; + if let Some(ref anon_const) = variant.disr_expr { + let span_before_consts = variant.span.until(anon_const.value.span); + let hi = match &variant.data { + Struct(..) => context + .snippet_provider + .span_after_last(span_before_consts, "}"), + Tuple(..) => context + .snippet_provider + .span_after_last(span_before_consts, ")"), + Unit(..) => variant.ident.span.hi(), + }; + mk_sp(span_before_consts.lo(), hi) + } else { + variant.span + } +} + fn format_struct( context: &RewriteContext<'_>, struct_parts: &StructParts<'_>, diff --git a/tests/source/issue_5686.rs b/tests/source/issue_5686.rs new file mode 100644 index 0000000000000..3bf96f73b2cd9 --- /dev/null +++ b/tests/source/issue_5686.rs @@ -0,0 +1,40 @@ +#[repr(u8)] +enum MyEnum { + UnitWithExplicitDiscriminant = 0, + EmptyStructSingleLineBlockComment { + /* Comment */ + } = 1, + EmptyStructMultiLineBlockComment { + /* + * Comment + */ + } = 2, + EmptyStructLineComment { + // comment + } = 3, + EmptyTupleSingleLineBlockComment( + /* Comment */ + ) = 4, + EmptyTupleMultiLineBlockComment( + /* + * Comment + */ + ) = 5, + EmptyTupleLineComment( + // comment + ) = 6, +} + +enum Animal { + Dog(/* tuple variant closer in comment -> ) */) = 1, + #[hello(world)] + Cat(/* tuple variant close in leading attribute */) = 2, + Bee(/* tuple variant closer on associated field attribute */ #[hello(world)] usize) = 3, + Fox(/* tuple variant closer on const fn call */) = some_const_fn(), + Ant(/* tuple variant closer on macro call */) = some_macro!(), + Snake {/* stuct variant closer in comment -> } */} = 6, + #[hell{world}] + Cobra {/* struct variant close in leading attribute */} = 6, + Eagle {/* struct variant closer on associated field attribute */ #[hell{world}]value: Sting} = 7, + Koala {/* struct variant closer on macro call */} = some_macro!{} +} diff --git a/tests/target/issue_5686.rs b/tests/target/issue_5686.rs new file mode 100644 index 0000000000000..993f12b5316dc --- /dev/null +++ b/tests/target/issue_5686.rs @@ -0,0 +1,42 @@ +#[repr(u8)] +enum MyEnum { + UnitWithExplicitDiscriminant = 0, + EmptyStructSingleLineBlockComment {/* Comment */} = 1, + EmptyStructMultiLineBlockComment { + /* + * Comment + */ + } = 2, + EmptyStructLineComment { + // comment + } = 3, + EmptyTupleSingleLineBlockComment(/* Comment */) = 4, + EmptyTupleMultiLineBlockComment( + /* + * Comment + */ + ) = 5, + EmptyTupleLineComment( + // comment + ) = 6, +} + +enum Animal { + Dog(/* tuple variant closer in comment -> ) */) = 1, + #[hello(world)] + Cat(/* tuple variant close in leading attribute */) = 2, + Bee( + /* tuple variant closer on associated field attribute */ #[hello(world)] usize, + ) = 3, + Fox(/* tuple variant closer on const fn call */) = some_const_fn(), + Ant(/* tuple variant closer on macro call */) = some_macro!(), + Snake {/* stuct variant closer in comment -> } */} = 6, + #[hell{world}] + Cobra {/* struct variant close in leading attribute */} = 6, + Eagle { + /* struct variant closer on associated field attribute */ + #[hell{world}] + value: Sting, + } = 7, + Koala {/* struct variant closer on macro call */} = some_macro! {}, +} From 66b9951dcdc76bbda5e6c75b4a2974d21a9e747f Mon Sep 17 00:00:00 2001 From: KaDiWa Date: Wed, 1 Feb 2023 00:20:15 +0100 Subject: [PATCH 54/58] update some dependencies --- Cargo.lock | 98 +++++++++++++++++++++++++---------- Cargo.toml | 6 +-- src/cargo-fmt/main.rs | 7 +-- src/cargo-fmt/test/targets.rs | 22 ++++---- 4 files changed, 90 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8487dc58b4ed3..a59e0b6819bf7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -68,15 +68,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27" [[package]] -name = "atty" -version = "0.2.14" +name = "autocfg" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "bitflags" @@ -122,15 +117,16 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.14.2" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" +checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" dependencies = [ "camino", "cargo-platform", "semver", "serde", "serde_json", + "thiserror", ] [[package]] @@ -267,12 +263,12 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "env_logger" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" dependencies = [ - "atty", "humantime", + "is-terminal", "log", "regex", "termcolor", @@ -339,19 +335,16 @@ dependencies = [ ] [[package]] -name = "heck" -version = "0.4.0" +name = "hashbrown" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] -name = "hermit-abi" -version = "0.1.19" +name = "heck" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" [[package]] name = "hermit-abi" @@ -383,13 +376,23 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown", +] + [[package]] name = "io-lifetimes" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" dependencies = [ - "hermit-abi 0.3.1", + "hermit-abi", "libc", "windows-sys 0.48.0", ] @@ -400,7 +403,7 @@ version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" dependencies = [ - "hermit-abi 0.3.1", + "hermit-abi", "io-lifetimes", "rustix", "windows-sys 0.48.0", @@ -644,6 +647,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93107647184f6027e3b7dcb2e11034cf95ffa1e3a682c67951963ac69c1c007d" +dependencies = [ + "serde", +] + [[package]] name = "strsim" version = "0.10.0" @@ -712,11 +724,36 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.8" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6135d499e69981f9ff0ef2167955a5333c35e36f6937d382974566b3d5b94ec" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739" dependencies = [ + "indexmap", "serde", + "serde_spanned", + "toml_datetime", + "winnow", ] [[package]] @@ -929,6 +966,15 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +[[package]] +name = "winnow" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" +dependencies = [ + "memchr", +] + [[package]] name = "yansi-term" version = "0.1.2" diff --git a/Cargo.toml b/Cargo.toml index 0093b975e8628..5f483693a116e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,11 +36,11 @@ generic-simd = ["bytecount/generic-simd"] annotate-snippets = { version = "0.9", features = ["color"] } anyhow = "1.0" bytecount = "0.6" -cargo_metadata = "0.14" +cargo_metadata = "0.15.4" clap = { version = "4.2.1", features = ["derive"] } diff = "0.1" dirs = "4.0" -env_logger = "0.9" +env_logger = "0.10.0" getopts = "0.2" ignore = "0.4" itertools = "0.10" @@ -51,7 +51,7 @@ serde = { version = "1.0.160", features = ["derive"] } serde_json = "1.0" term = "0.7" thiserror = "1.0.40" -toml = "0.5" +toml = "0.7.4" unicode-segmentation = "1.9" unicode-width = "0.1" unicode_categories = "0.1" diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index a106181ec7eb6..bc9745275f20c 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -14,6 +14,7 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::str; +use cargo_metadata::Edition; use clap::{CommandFactory, Parser}; #[path = "test/mod.rs"] @@ -270,7 +271,7 @@ pub struct Target { /// A kind of target (e.g., lib, bin, example, ...). kind: String, /// Rust edition for this target. - edition: String, + edition: Edition, } impl Target { @@ -281,7 +282,7 @@ impl Target { Target { path: canonicalized, kind: target.kind[0].clone(), - edition: target.edition.clone(), + edition: target.edition, } } } @@ -506,7 +507,7 @@ fn run_rustfmt( let mut command = rustfmt_command() .stdout(stdout) .args(files) - .args(&["--edition", edition]) + .args(&["--edition", edition.as_str()]) .args(fmt_args) .spawn() .map_err(|e| match e.kind() { diff --git a/src/cargo-fmt/test/targets.rs b/src/cargo-fmt/test/targets.rs index b7e7fabdf7156..34accb2136a44 100644 --- a/src/cargo-fmt/test/targets.rs +++ b/src/cargo-fmt/test/targets.rs @@ -2,7 +2,7 @@ use super::*; struct ExpTarget { path: &'static str, - edition: &'static str, + edition: Edition, kind: &'static str, } @@ -26,7 +26,7 @@ mod all_targets { for target in exp_targets { assert!(targets.contains(&Target { path: get_path(target.path), - edition: target.edition.to_owned(), + edition: target.edition, kind: target.kind.to_owned(), })); } @@ -39,17 +39,17 @@ mod all_targets { let exp_targets = vec![ ExpTarget { path: "dependency-dir-name/subdep-dir-name/src/lib.rs", - edition: "2018", + edition: Edition::E2018, kind: "lib", }, ExpTarget { path: "dependency-dir-name/src/lib.rs", - edition: "2018", + edition: Edition::E2018, kind: "lib", }, ExpTarget { path: "src/main.rs", - edition: "2018", + edition: Edition::E2018, kind: "main", }, ]; @@ -79,32 +79,32 @@ mod all_targets { let exp_targets = vec![ ExpTarget { path: "ws/a/src/main.rs", - edition: "2018", + edition: Edition::E2018, kind: "bin", }, ExpTarget { path: "ws/b/src/main.rs", - edition: "2018", + edition: Edition::E2018, kind: "bin", }, ExpTarget { path: "ws/c/src/lib.rs", - edition: "2018", + edition: Edition::E2018, kind: "lib", }, ExpTarget { path: "ws/a/d/src/lib.rs", - edition: "2018", + edition: Edition::E2018, kind: "lib", }, ExpTarget { path: "e/src/main.rs", - edition: "2018", + edition: Edition::E2018, kind: "main", }, ExpTarget { path: "ws/a/d/f/src/lib.rs", - edition: "2018", + edition: Edition::E2018, kind: "lib", }, ]; From f4201ef2cb89c28bcdb82cab292720eb66b75695 Mon Sep 17 00:00:00 2001 From: Lukasz Anforowicz Date: Mon, 10 Oct 2022 16:33:31 +0000 Subject: [PATCH 55/58] Handling of numbered markdown lists. Fixes issue #5416 --- src/comment.rs | 174 +++++++++++++++++++++--- tests/source/itemized-blocks/no_wrap.rs | 36 ++++- tests/source/itemized-blocks/wrap.rs | 36 ++++- tests/target/itemized-blocks/no_wrap.rs | 36 ++++- tests/target/itemized-blocks/wrap.rs | 62 ++++++++- 5 files changed, 319 insertions(+), 25 deletions(-) diff --git a/src/comment.rs b/src/comment.rs index bc0e8774f4949..85918ecc11645 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -432,12 +432,18 @@ impl CodeBlockAttribute { /// Block that is formatted as an item. /// -/// An item starts with either a star `*` a dash `-` a greater-than `>` or a plus '+'. +/// An item starts with either a star `*`, a dash `-`, a greater-than `>`, a plus '+', or a number +/// `12.` or `34)` (with at most 2 digits). An item represents CommonMark's ["list +/// items"](https://spec.commonmark.org/0.30/#list-items) and/or ["block +/// quotes"](https://spec.commonmark.org/0.30/#block-quotes), but note that only a subset of +/// CommonMark is recognized - see the doc comment of [`ItemizedBlock::get_marker_length`] for more +/// details. +/// /// Different level of indentation are handled by shrinking the shape accordingly. struct ItemizedBlock { /// the lines that are identified as part of an itemized block lines: Vec, - /// the number of characters (typically whitespaces) up to the item sigil + /// the number of characters (typically whitespaces) up to the item marker indent: usize, /// the string that marks the start of an item opener: String, @@ -446,37 +452,70 @@ struct ItemizedBlock { } impl ItemizedBlock { - /// Returns `true` if the line is formatted as an item - fn is_itemized_line(line: &str) -> bool { - let trimmed = line.trim_start(); + /// Checks whether the `trimmed` line includes an item marker. Returns `None` if there is no + /// marker. Returns the length of the marker (in bytes) if one is present. Note that the length + /// includes the whitespace that follows the marker, for example the marker in `"* list item"` + /// has the length of 2. + /// + /// This function recognizes item markers that correspond to CommonMark's + /// ["bullet list marker"](https://spec.commonmark.org/0.30/#bullet-list-marker), + /// ["block quote marker"](https://spec.commonmark.org/0.30/#block-quote-marker), and/or + /// ["ordered list marker"](https://spec.commonmark.org/0.30/#ordered-list-marker). + /// + /// Compared to CommonMark specification, the number of digits that are allowed in an ["ordered + /// list marker"](https://spec.commonmark.org/0.30/#ordered-list-marker) is more limited (to at + /// most 2 digits). Limiting the length of the marker helps reduce the risk of recognizing + /// arbitrary numbers as markers. See also + /// which gives the + /// following example where a number (i.e. "1868") doesn't signify an ordered list: + /// ```md + /// The Captain died in + /// 1868. He wes buried in... + /// ``` + fn get_marker_length(trimmed: &str) -> Option { + // https://spec.commonmark.org/0.30/#bullet-list-marker or + // https://spec.commonmark.org/0.30/#block-quote-marker let itemized_start = ["* ", "- ", "> ", "+ "]; - itemized_start.iter().any(|s| trimmed.starts_with(s)) + if itemized_start.iter().any(|s| trimmed.starts_with(s)) { + return Some(2); // All items in `itemized_start` have length 2. + } + + // https://spec.commonmark.org/0.30/#ordered-list-marker, where at most 2 digits are + // allowed. + for suffix in [". ", ") "] { + if let Some((prefix, _)) = trimmed.split_once(suffix) { + if prefix.len() <= 2 && prefix.chars().all(|c| char::is_ascii_digit(&c)) { + return Some(prefix.len() + suffix.len()); + } + } + } + + None // No markers found. } - /// Creates a new ItemizedBlock described with the given line. - /// The `is_itemized_line` needs to be called first. - fn new(line: &str) -> ItemizedBlock { - let space_to_sigil = line.chars().take_while(|c| c.is_whitespace()).count(); - // +2 = '* ', which will add the appropriate amount of whitespace to keep itemized - // content formatted correctly. - let mut indent = space_to_sigil + 2; + /// Creates a new `ItemizedBlock` described with the given `line`. + /// Returns `None` if `line` doesn't start an item. + fn new(line: &str) -> Option { + let marker_length = ItemizedBlock::get_marker_length(line.trim_start())?; + let space_to_marker = line.chars().take_while(|c| c.is_whitespace()).count(); + let mut indent = space_to_marker + marker_length; let mut line_start = " ".repeat(indent); // Markdown blockquote start with a "> " 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 th new line_start. We update the indent because it effects the max width + // of the new line_start. We update the indent because it effects the max width // of each formatted line. line_start = itemized_block_quote_start(line, line_start, 2); indent = line_start.len(); } - ItemizedBlock { + Some(ItemizedBlock { lines: vec![line[indent..].to_string()], indent, opener: line[..indent].to_string(), line_start, - } + }) } /// Returns a `StringFormat` used for formatting the content of an item. @@ -495,7 +534,7 @@ impl ItemizedBlock { /// Returns `true` if the line is part of the current itemized block. /// If it is, then it is added to the internal lines list. fn add_line(&mut self, line: &str) -> bool { - if !ItemizedBlock::is_itemized_line(line) + if ItemizedBlock::get_marker_length(line.trim_start()).is_none() && self.indent <= line.chars().take_while(|c| c.is_whitespace()).count() { self.lines.push(line.to_string()); @@ -766,10 +805,11 @@ impl<'a> CommentRewrite<'a> { self.item_block = None; if let Some(stripped) = line.strip_prefix("```") { self.code_block_attr = Some(CodeBlockAttribute::new(stripped)) - } else if self.fmt.config.wrap_comments() && ItemizedBlock::is_itemized_line(line) { - let ib = ItemizedBlock::new(line); - self.item_block = Some(ib); - return false; + } else if self.fmt.config.wrap_comments() { + if let Some(ib) = ItemizedBlock::new(line) { + self.item_block = Some(ib); + return false; + } } if self.result == self.opener { @@ -2020,4 +2060,96 @@ fn main() { "#; assert_eq!(s, filter_normal_code(s_with_comment)); } + + #[test] + fn test_itemized_block_first_line_handling() { + fn run_test( + test_input: &str, + expected_line: &str, + expected_indent: usize, + expected_opener: &str, + expected_line_start: &str, + ) { + let block = ItemizedBlock::new(test_input).unwrap(); + assert_eq!(1, block.lines.len(), "test_input: {:?}", test_input); + assert_eq!( + expected_line, &block.lines[0], + "test_input: {:?}", + test_input + ); + assert_eq!( + expected_indent, block.indent, + "test_input: {:?}", + test_input + ); + assert_eq!( + expected_opener, &block.opener, + "test_input: {:?}", + test_input + ); + assert_eq!( + expected_line_start, &block.line_start, + "test_input: {:?}", + test_input + ); + } + + run_test("- foo", "foo", 2, "- ", " "); + run_test("* foo", "foo", 2, "* ", " "); + run_test("> foo", "foo", 2, "> ", "> "); + + run_test("1. foo", "foo", 3, "1. ", " "); + run_test("12. foo", "foo", 4, "12. ", " "); + run_test("1) foo", "foo", 3, "1) ", " "); + run_test("12) foo", "foo", 4, "12) ", " "); + + run_test(" - foo", "foo", 6, " - ", " "); + + // https://spec.commonmark.org/0.30 says: "A start number may begin with 0s": + run_test("0. foo", "foo", 3, "0. ", " "); + run_test("01. foo", "foo", 4, "01. ", " "); + } + + #[test] + fn test_itemized_block_nonobvious_markers_are_rejected() { + let test_inputs = vec![ + // Non-numeric item markers (e.g. `a.` or `iv.`) are not allowed by + // https://spec.commonmark.org/0.30/#ordered-list-marker. We also note that allowing + // them would risk misidentifying regular words as item markers. See also the + // discussion in https://talk.commonmark.org/t/blank-lines-before-lists-revisited/1990 + "word. rest of the paragraph.", + "a. maybe this is a list item? maybe not?", + "iv. maybe this is a list item? maybe not?", + // Numbers with 3 or more digits are not recognized as item markers, to avoid + // formatting the following example as a list: + // + // ``` + // The Captain died in + // 1868. He was buried in... + // ``` + "123. only 2-digit numbers are recognized as item markers.", + // Parens: + "123) giving some coverage to parens as well.", + "a) giving some coverage to parens as well.", + // https://spec.commonmark.org/0.30 says that "at least one space or tab is needed + // between the list marker and any following content": + "1.Not a list item.", + "1.2.3. Not a list item.", + "1)Not a list item.", + "-Not a list item.", + "+Not a list item.", + "+1 not a list item.", + // https://spec.commonmark.org/0.30 says: "A start number may not be negative": + "-1. Not a list item.", + "-1 Not a list item.", + ]; + for line in test_inputs.iter() { + let maybe_block = ItemizedBlock::new(line); + assert!( + maybe_block.is_none(), + "The following line shouldn't be classified as a list item: {}", + line + ); + } + } } diff --git a/tests/source/itemized-blocks/no_wrap.rs b/tests/source/itemized-blocks/no_wrap.rs index a7b6a10a01050..e5699e766848a 100644 --- a/tests/source/itemized-blocks/no_wrap.rs +++ b/tests/source/itemized-blocks/no_wrap.rs @@ -1,7 +1,7 @@ // rustfmt-normalize_comments: true // rustfmt-format_code_in_doc_comments: true -//! This is a list: +//! This is an itemized markdown list (see also issue #3224): //! * Outer //! * Outer //! * Inner @@ -13,6 +13,40 @@ //! - when the log level is info, the level name is green and the rest of the line is white //! - when the log level is debug, the whole line is white //! - when the log level is trace, the whole line is gray ("bright black") +//! +//! This is a numbered markdown list (see also issue #5416): +//! 1. Long long long long long long long long long long long long long long long long long line +//! 2. Another very long long long long long long long long long long long long long long long line +//! 3. Nested list +//! 1. Long long long long long long long long long long long long long long long long line +//! 2. Another very long long long long long long long long long long long long long long line +//! 4. Last item +//! +//! Using the ')' instead of '.' character after the number: +//! 1) Long long long long long long long long long long long long long long long long long line +//! 2) Another very long long long long long long long long long long long long long long long line +//! +//! Deep list that mixes various bullet and number formats: +//! 1. First level with a long long long long long long long long long long long long long long +//! long long long line +//! 2. First level with another very long long long long long long long long long long long long +//! long long long line +//! * Second level with a long long long long long long long long long long long long long +//! long long long line +//! * Second level with another very long long long long long long long long long long long +//! long long long line +//! 1) Third level with a long long long long long long long long long long long long long +//! long long long line +//! 2) Third level with another very long long long long long long long long long long +//! long long long long line +//! - Forth level with a long long long long long long long long long long long long +//! long long long long line +//! - Forth level with another very long long long long long long long long long long +//! long long long long line +//! 3) One more item at the third level +//! 4) Last item of the third level +//! * Last item of second level +//! 3. Last item of first level /// All the parameters ***except for `from_theater`*** should be inserted as sent by the remote /// theater, i.e., as passed to [`Theater::send`] on the remote actor: diff --git a/tests/source/itemized-blocks/wrap.rs b/tests/source/itemized-blocks/wrap.rs index 955cc698b79f2..768461a43f956 100644 --- a/tests/source/itemized-blocks/wrap.rs +++ b/tests/source/itemized-blocks/wrap.rs @@ -2,7 +2,7 @@ // rustfmt-format_code_in_doc_comments: true // rustfmt-max_width: 50 -//! This is a list: +//! This is an itemized markdown list (see also issue #3224): //! * Outer //! * Outer //! * Inner @@ -14,6 +14,40 @@ //! - when the log level is info, the level name is green and the rest of the line is white //! - when the log level is debug, the whole line is white //! - when the log level is trace, the whole line is gray ("bright black") +//! +//! This is a numbered markdown list (see also issue #5416): +//! 1. Long long long long long long long long long long long long long long long long long line +//! 2. Another very long long long long long long long long long long long long long long long line +//! 3. Nested list +//! 1. Long long long long long long long long long long long long long long long long line +//! 2. Another very long long long long long long long long long long long long long long line +//! 4. Last item +//! +//! Using the ')' instead of '.' character after the number: +//! 1) Long long long long long long long long long long long long long long long long long line +//! 2) Another very long long long long long long long long long long long long long long long line +//! +//! Deep list that mixes various bullet and number formats: +//! 1. First level with a long long long long long long long long long long long long long long +//! long long long line +//! 2. First level with another very long long long long long long long long long long long long +//! long long long line +//! * Second level with a long long long long long long long long long long long long long +//! long long long line +//! * Second level with another very long long long long long long long long long long long +//! long long long line +//! 1) Third level with a long long long long long long long long long long long long long +//! long long long line +//! 2) Third level with another very long long long long long long long long long long +//! long long long long line +//! - Forth level with a long long long long long long long long long long long long +//! long long long long line +//! - Forth level with another very long long long long long long long long long long +//! long long long long line +//! 3) One more item at the third level +//! 4) Last item of the third level +//! * Last item of second level +//! 3. Last item of first level // This example shows how to configure fern to output really nicely colored logs // - when the log level is error, the whole line is red diff --git a/tests/target/itemized-blocks/no_wrap.rs b/tests/target/itemized-blocks/no_wrap.rs index de88563827263..86818b4474591 100644 --- a/tests/target/itemized-blocks/no_wrap.rs +++ b/tests/target/itemized-blocks/no_wrap.rs @@ -1,7 +1,7 @@ // rustfmt-normalize_comments: true // rustfmt-format_code_in_doc_comments: true -//! This is a list: +//! This is an itemized markdown list (see also issue #3224): //! * Outer //! * Outer //! * Inner @@ -13,6 +13,40 @@ //! - when the log level is info, the level name is green and the rest of the line is white //! - when the log level is debug, the whole line is white //! - when the log level is trace, the whole line is gray ("bright black") +//! +//! This is a numbered markdown list (see also issue #5416): +//! 1. Long long long long long long long long long long long long long long long long long line +//! 2. Another very long long long long long long long long long long long long long long long line +//! 3. Nested list +//! 1. Long long long long long long long long long long long long long long long long line +//! 2. Another very long long long long long long long long long long long long long long line +//! 4. Last item +//! +//! Using the ')' instead of '.' character after the number: +//! 1) Long long long long long long long long long long long long long long long long long line +//! 2) Another very long long long long long long long long long long long long long long long line +//! +//! Deep list that mixes various bullet and number formats: +//! 1. First level with a long long long long long long long long long long long long long long +//! long long long line +//! 2. First level with another very long long long long long long long long long long long long +//! long long long line +//! * Second level with a long long long long long long long long long long long long long +//! long long long line +//! * Second level with another very long long long long long long long long long long long +//! long long long line +//! 1) Third level with a long long long long long long long long long long long long long +//! long long long line +//! 2) Third level with another very long long long long long long long long long long +//! long long long long line +//! - Forth level with a long long long long long long long long long long long long +//! long long long long line +//! - Forth level with another very long long long long long long long long long long +//! long long long long line +//! 3) One more item at the third level +//! 4) Last item of the third level +//! * Last item of second level +//! 3. Last item of first level /// All the parameters ***except for `from_theater`*** should be inserted as sent by the remote /// theater, i.e., as passed to [`Theater::send`] on the remote actor: diff --git a/tests/target/itemized-blocks/wrap.rs b/tests/target/itemized-blocks/wrap.rs index a4907303c9e1b..4826590ea59dd 100644 --- a/tests/target/itemized-blocks/wrap.rs +++ b/tests/target/itemized-blocks/wrap.rs @@ -2,7 +2,8 @@ // rustfmt-format_code_in_doc_comments: true // rustfmt-max_width: 50 -//! This is a list: +//! This is an itemized markdown list (see also +//! issue #3224): //! * Outer //! * Outer //! * Inner @@ -23,6 +24,65 @@ //! is white //! - when the log level is trace, the whole line //! is gray ("bright black") +//! +//! This is a numbered markdown list (see also +//! issue #5416): +//! 1. Long long long long long long long long +//! long long long long long long long long +//! long line +//! 2. Another very long long long long long long +//! long long long long long long long long +//! long line +//! 3. Nested list +//! 1. Long long long long long long long long +//! long long long long long long long long +//! line +//! 2. Another very long long long long long +//! long long long long long long long long +//! long line +//! 4. Last item +//! +//! Using the ')' instead of '.' character after +//! the number: +//! 1) Long long long long long long long long +//! long long long long long long long long +//! long line +//! 2) Another very long long long long long long +//! long long long long long long long long +//! long line +//! +//! Deep list that mixes various bullet and number +//! formats: +//! 1. First level with a long long long long long +//! long long long long long long long long +//! long long long long line +//! 2. First level with another very long long +//! long long long long long long long long +//! long long long long long line +//! * Second level with a long long long long +//! long long long long long long long long +//! long long long long line +//! * Second level with another very long long +//! long long long long long long long long +//! long long long long line +//! 1) Third level with a long long long +//! long long long long long long long +//! long long long long long long line +//! 2) Third level with another very long +//! long long long long long long long +//! long long long long long long line +//! - Forth level with a long long +//! long long long long long long +//! long long long long long long +//! long long line +//! - Forth level with another very +//! long long long long long long +//! long long long long long long +//! long long line +//! 3) One more item at the third level +//! 4) Last item of the third level +//! * Last item of second level +//! 3. Last item of first level // This example shows how to configure fern to // output really nicely colored logs From 0b17d7ea4605fcd3675c80069e0b5e82c4332b05 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Mon, 19 Jun 2023 21:29:15 -0500 Subject: [PATCH 56/58] chore: address merge and bump toolchain --- config_proc_macro/src/attrs.rs | 7 ------- rust-toolchain | 2 +- src/macros.rs | 2 +- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/config_proc_macro/src/attrs.rs b/config_proc_macro/src/attrs.rs index 2c01b9a1321e9..d8de9aae088d7 100644 --- a/config_proc_macro/src/attrs.rs +++ b/config_proc_macro/src/attrs.rs @@ -64,13 +64,6 @@ fn is_attr_path(attr: &syn::Attribute, name: &str) -> bool { } } -fn is_attr_path(attr: &syn::Attribute, name: &str) -> bool { - attr.parse_meta().ok().map_or(false, |meta| match meta { - syn::Meta::Path(path) if path.is_ident(name) => true, - _ => false, - }) -} - fn get_name_value_str_lit(attr: &syn::Attribute, name: &str) -> Option { match &attr.meta { syn::Meta::NameValue(syn::MetaNameValue { diff --git a/rust-toolchain b/rust-toolchain index 22283b3d62002..03b909cd80c79 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-01-24" +channel = "nightly-2023-06-19" components = ["llvm-tools", "rustc-dev"] diff --git a/src/macros.rs b/src/macros.rs index 9f4beae735054..e9a298a27693d 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1124,7 +1124,7 @@ struct MacroParser { } impl MacroParser { - const fn new(toks: Cursor) -> Self { + const fn new(toks: TokenTreeCursor) -> Self { Self { toks } } From 3f7c366fc0464e01ddcaefbd70647cb3da4202be Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Mon, 19 Jun 2023 22:23:11 -0500 Subject: [PATCH 57/58] chore: release v1.5.3 --- CHANGELOG.md | 40 ++++++++++------------------------------ Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 12 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd7d9f8d70b6a..0d4e057223d44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,14 @@ ## [Unreleased] +## [1.5.3] 2023-06-20 + ### Fixed - When formatting doc comments with `wrap_comments = true` rustfmt will no longer wrap markdown tables [#4210](https://github.com/rust-lang/rustfmt/issues/4210) -- rustfmt will no longer use shorthand initialization when rewriting a tuple struct even when `use_field_init_shorthand = true` as this lead to code that could no longer compile. +- Properly handle wrapping comments that include a numbered list in markdown [#5416](https://github.com/rust-lang/rustfmt/issues/5416) +- Properly handle markdown sublists that utilize a `+` [#4041](https://github.com/rust-lang/rustfmt/issues/4210) +- rustfmt will no longer use shorthand initialization when rewriting a tuple struct even when `use_field_init_shorthand = true` as this leads to code that could no longer compile. Take the following struct as an example `struct MyStruct(u64);`. rustfmt will no longer format `MyStruct { 0: 0 }` as `MyStruct { 0 }` [#5488](https://github.com/rust-lang/rustfmt/issues/5488) - rustfmt no longer panics when formatting an empty code block in a doc comment with `format_code_in_doc_comments = true` [#5234](https://github.com/rust-lang/rustfmt/issues/5234). For example: ```rust @@ -14,7 +18,7 @@ /// ``` fn main() {} ``` -- Use the correct span when rewriting struct generics. This prevents rustfmt from incorrectly duplicating where clause bounds when using const expression in where clause bounds with feature `#![feature(generic_const_exprs)]` [#5691](https://github.com/rust-lang/rustfmt/issues/5691). e.g.: +- rustfmt no longer incorrectly duplicates the where clause bounds when using const expression in where clause bounds with feature `#![feature(generic_const_exprs)]` [#5691](https://github.com/rust-lang/rustfmt/issues/5691). e.g.: ```rust struct S where @@ -22,6 +26,9 @@ // code ... } ``` +- Prevent ICE when parsing invalid attributes in `cfg_if!` macros [#5728](https://github.com/rust-lang/rustfmt/issues/5728), [#5729](https://github.com/rust-lang/rustfmt/issues/5729) +- rustfmt no longer loses comments placed between a doc comment and generic params [#5320](https://github.com/rust-lang/rustfmt/issues/5320) +- Handle explicit discriminants in enums with comments present [#5686](https://github.com/rust-lang/rustfmt/issues/5686) ### Changed @@ -34,34 +41,7 @@ ### Misc -- Prevent ICE when parsing invalid attributes in `cfg_if!` macros [#5728](https://github.com/rust-lang/rustfmt/issues/5728) - - -## [1.5.2] 2023-01-24 - -### Fixed - -- Resolve issue when comments are found within const generic defaults in unit structs [#5668](https://github.com/rust-lang/rustfmt/issues/5668) -- Resolve issue when block comments are found within trait generics [#5358](https://github.com/rust-lang/rustfmt/issues/5358) -- Correctly handle alignment of comments containing unicode characters [#5504](https://github.com/rust-lang/rustfmt/issues/5504) -- Properly indent a single generic bound that requires being written across multiple lines [#4689](https://github.com/rust-lang/rustfmt/issues/4689) (n.b. this change is version gated and will only appear when the `version` configuration option is set to `Two`) - -### Changed - -- Renamed `fn_args_layout` configuration option to `fn_params_layout` [#4149](https://github.com/rust-lang/rustfmt/issues/4149). Note that `fn_args_layout` has only been soft deprecated: `fn_args_layout` will continue to work without issue, but rustfmt will display a warning to encourage users to switch to the new name - -### Added - -- New configuration option (`skip_macro_invocations`)[https://rust-lang.github.io/rustfmt/?version=master&search=#skip_macro_invocations] [#5347](https://github.com/rust-lang/rustfmt/pull/5347) that can be used to globally define a single enumerated list of macro calls that rustfmt should skip formatting. rustfmt [currently also supports this via a custom tool attribute](https://github.com/rust-lang/rustfmt#tips), however, these cannot be used in all contexts because [custom inner attributes are unstable](https://github.com/rust-lang/rust/issues/54726) - -### Misc - -- rustfmt now internally supports the ability to have both stable and unstable variants of a configuration option [#5378](https://github.com/rust-lang/rustfmt/issues/5378). This ability will allow the rustfmt team to make certain configuration options available on stable toolchains more quickly because we no longer have to wait for _every_ variant to be stable-ready before stabilizing _any_ variant. - -### Install/Download Options -- **rustup (nightly)** - nightly-2023-01-24 -- **GitHub Release Binaries** - [Release v1.5.2](https://github.com/rust-lang/rustfmt/releases/tag/v1.5.2) -- **Build from source** - [Tag v1.5.2](https://github.com/rust-lang/rustfmt/tree/v1.5.2), see instructions for how to [install rustfmt from source][install-from-source] +- Update various dependencies, including `syn`, `cargo_metadata`, `env_logger`, and `toml` ## [1.5.2] 2023-01-24 diff --git a/Cargo.lock b/Cargo.lock index a59e0b6819bf7..999125118f8f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -545,7 +545,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.5.2" +version = "1.5.3" dependencies = [ "annotate-snippets", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index 5f483693a116e..a8928bfcd505b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "1.5.2" +version = "1.5.3" description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang/rustfmt" readme = "README.md" From aca66a20c63c19feb4ed9a30cd9e8290972b70f6 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Mon, 19 Jun 2023 23:19:48 -0500 Subject: [PATCH 58/58] update lockfile for rustfmt sync --- Cargo.lock | 39 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4eafda94037c3..3d0f9e8844e06 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -360,7 +360,7 @@ dependencies = [ name = "cargo-miri" version = "0.1.0" dependencies = [ - "cargo_metadata 0.15.3", + "cargo_metadata", "directories", "rustc-build-sysroot", "rustc-workspace-hack", @@ -381,22 +381,9 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c297bd3135f558552f99a0daa180876984ea2c4ffa7470314540dff8c654109a" -dependencies = [ - "camino", - "cargo-platform", - "semver", - "serde", - "serde_json", -] - -[[package]] -name = "cargo_metadata" -version = "0.15.3" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08a1ec454bc3eead8719cb56e15dbbfecdbc14e4b3a3ae4936cc6e31f5fc0d07" +checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" dependencies = [ "camino", "cargo-platform", @@ -631,7 +618,7 @@ name = "clippy_lints" version = "0.1.72" dependencies = [ "arrayvec", - "cargo_metadata 0.15.3", + "cargo_metadata", "clippy_utils", "declare_clippy_lint", "if_chain", @@ -4348,35 +4335,33 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 1.0.102", + "syn 2.0.8", ] [[package]] name = "rustfmt-nightly" -version = "1.5.2" +version = "1.5.3" dependencies = [ "annotate-snippets", "anyhow", "bytecount", - "cargo_metadata 0.14.0", - "clap 3.2.20", - "derive-new", + "cargo_metadata", + "clap 4.2.1", "diff", "dirs", - "env_logger 0.9.0", + "env_logger 0.10.0", "getopts", "ignore", "itertools", "lazy_static", "log", "regex", - "rustc-workspace-hack", "rustfmt-config_proc_macro", "serde", "serde_json", "term", "thiserror", - "toml 0.5.7", + "toml 0.7.4", "unicode-segmentation", "unicode-width", "unicode_categories", @@ -4956,7 +4941,7 @@ name = "tidy" version = "0.1.0" dependencies = [ "cargo-platform", - "cargo_metadata 0.15.3", + "cargo_metadata", "ignore", "lazy_static", "miropt-test-tools", @@ -5192,7 +5177,7 @@ checksum = "191a442639ea102fa62671026047e51d574bfda44b7fdf32151d7314624c1cd2" dependencies = [ "bstr", "cargo-platform", - "cargo_metadata 0.15.3", + "cargo_metadata", "color-eyre", "colored", "crossbeam-channel",