From 60ed5e912b399e24d43be428eb7dee5422c3c6b4 Mon Sep 17 00:00:00 2001 From: bradleypmartin Date: Sun, 26 Apr 2020 22:33:33 -0600 Subject: [PATCH 01/59] add recursive mode and clean up whitelist where we can --- rustfmt-core/rustfmt-lib/src/test/mod.rs | 13 +------------ rustfmt-core/rustfmt-lib/tests/source/cfg_if/lib.rs | 1 + rustfmt-core/rustfmt-lib/tests/target/cfg_if/lib.rs | 1 + 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/rustfmt-core/rustfmt-lib/src/test/mod.rs b/rustfmt-core/rustfmt-lib/src/test/mod.rs index d5af64292bd..1d7608394c8 100644 --- a/rustfmt-core/rustfmt-lib/src/test/mod.rs +++ b/rustfmt-core/rustfmt-lib/src/test/mod.rs @@ -21,21 +21,10 @@ const DIFF_CONTEXT_SIZE: usize = 3; // A list of files on which we want to skip testing. const SKIP_FILE_WHITE_LIST: &[&str] = &[ + "issue-3253/paths", "issue-3434/no_entry.rs", "issue-3665/sub_mod.rs", - // Testing for issue-3779 "issue-3779/ice.rs", - // These files and directory are a part of modules defined inside `cfg_if!`. - "cfg_if/mod.rs", - "cfg_if/detect", - "issue-3253/foo.rs", - "issue-3253/bar.rs", - "issue-3253/paths", - // These files and directory are a part of modules defined inside `cfg_attr(..)`. - "cfg_mod/dir", - "cfg_mod/bar.rs", - "cfg_mod/foo.rs", - "cfg_mod/wasm32.rs", // We want to ensure `recursive` is working correctly, so do not test // these files directly "configs/recursive/disabled/foo.rs", diff --git a/rustfmt-core/rustfmt-lib/tests/source/cfg_if/lib.rs b/rustfmt-core/rustfmt-lib/tests/source/cfg_if/lib.rs index 8b3bb304f1c..bb333be01a9 100644 --- a/rustfmt-core/rustfmt-lib/tests/source/cfg_if/lib.rs +++ b/rustfmt-core/rustfmt-lib/tests/source/cfg_if/lib.rs @@ -10,6 +10,7 @@ //! * `mips64`: [`is_mips64_feature_detected`] //! * `powerpc`: [`is_powerpc_feature_detected`] //! * `powerpc64`: [`is_powerpc64_feature_detected`] +// rustfmt-recursive: true #![unstable(feature = "stdsimd", issue = "27731")] #![feature(const_fn, staged_api, stdsimd, doc_cfg, allow_internal_unstable)] diff --git a/rustfmt-core/rustfmt-lib/tests/target/cfg_if/lib.rs b/rustfmt-core/rustfmt-lib/tests/target/cfg_if/lib.rs index 8b3bb304f1c..bb333be01a9 100644 --- a/rustfmt-core/rustfmt-lib/tests/target/cfg_if/lib.rs +++ b/rustfmt-core/rustfmt-lib/tests/target/cfg_if/lib.rs @@ -10,6 +10,7 @@ //! * `mips64`: [`is_mips64_feature_detected`] //! * `powerpc`: [`is_powerpc_feature_detected`] //! * `powerpc64`: [`is_powerpc64_feature_detected`] +// rustfmt-recursive: true #![unstable(feature = "stdsimd", issue = "27731")] #![feature(const_fn, staged_api, stdsimd, doc_cfg, allow_internal_unstable)] From 3f40a9e275b97393df4848dbeb34983de7ef351e Mon Sep 17 00:00:00 2001 From: bradleypmartin Date: Mon, 27 Apr 2020 21:44:55 -0600 Subject: [PATCH 02/59] move recursive setting to top of lib.rs files --- rustfmt-core/rustfmt-lib/tests/source/cfg_if/lib.rs | 3 ++- rustfmt-core/rustfmt-lib/tests/target/cfg_if/lib.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/rustfmt-core/rustfmt-lib/tests/source/cfg_if/lib.rs b/rustfmt-core/rustfmt-lib/tests/source/cfg_if/lib.rs index bb333be01a9..17e76286a61 100644 --- a/rustfmt-core/rustfmt-lib/tests/source/cfg_if/lib.rs +++ b/rustfmt-core/rustfmt-lib/tests/source/cfg_if/lib.rs @@ -1,3 +1,5 @@ +// rustfmt-recursive: true + //! Run-time feature detection for the Rust standard library. //! //! To detect whether a feature is enabled in the system running the binary @@ -10,7 +12,6 @@ //! * `mips64`: [`is_mips64_feature_detected`] //! * `powerpc`: [`is_powerpc_feature_detected`] //! * `powerpc64`: [`is_powerpc64_feature_detected`] -// rustfmt-recursive: true #![unstable(feature = "stdsimd", issue = "27731")] #![feature(const_fn, staged_api, stdsimd, doc_cfg, allow_internal_unstable)] diff --git a/rustfmt-core/rustfmt-lib/tests/target/cfg_if/lib.rs b/rustfmt-core/rustfmt-lib/tests/target/cfg_if/lib.rs index bb333be01a9..17e76286a61 100644 --- a/rustfmt-core/rustfmt-lib/tests/target/cfg_if/lib.rs +++ b/rustfmt-core/rustfmt-lib/tests/target/cfg_if/lib.rs @@ -1,3 +1,5 @@ +// rustfmt-recursive: true + //! Run-time feature detection for the Rust standard library. //! //! To detect whether a feature is enabled in the system running the binary @@ -10,7 +12,6 @@ //! * `mips64`: [`is_mips64_feature_detected`] //! * `powerpc`: [`is_powerpc_feature_detected`] //! * `powerpc64`: [`is_powerpc64_feature_detected`] -// rustfmt-recursive: true #![unstable(feature = "stdsimd", issue = "27731")] #![feature(const_fn, staged_api, stdsimd, doc_cfg, allow_internal_unstable)] From 009421c5343f3f2da963cb1cf155a27ddf2d823d Mon Sep 17 00:00:00 2001 From: bradleypmartin Date: Tue, 28 Apr 2020 08:36:30 -0600 Subject: [PATCH 03/59] rustfmt-core/rustfmt-lib/src/test/mod.rs : revert skipped files --- rustfmt-core/rustfmt-lib/src/test/mod.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/rustfmt-core/rustfmt-lib/src/test/mod.rs b/rustfmt-core/rustfmt-lib/src/test/mod.rs index 1d7608394c8..d5af64292bd 100644 --- a/rustfmt-core/rustfmt-lib/src/test/mod.rs +++ b/rustfmt-core/rustfmt-lib/src/test/mod.rs @@ -21,10 +21,21 @@ const DIFF_CONTEXT_SIZE: usize = 3; // A list of files on which we want to skip testing. const SKIP_FILE_WHITE_LIST: &[&str] = &[ - "issue-3253/paths", "issue-3434/no_entry.rs", "issue-3665/sub_mod.rs", + // Testing for issue-3779 "issue-3779/ice.rs", + // These files and directory are a part of modules defined inside `cfg_if!`. + "cfg_if/mod.rs", + "cfg_if/detect", + "issue-3253/foo.rs", + "issue-3253/bar.rs", + "issue-3253/paths", + // These files and directory are a part of modules defined inside `cfg_attr(..)`. + "cfg_mod/dir", + "cfg_mod/bar.rs", + "cfg_mod/foo.rs", + "cfg_mod/wasm32.rs", // We want to ensure `recursive` is working correctly, so do not test // these files directly "configs/recursive/disabled/foo.rs", From ddd5c6eab72157709557c785a3a79d87f08aff93 Mon Sep 17 00:00:00 2001 From: bradleypmartin Date: Sun, 26 Apr 2020 22:33:33 -0600 Subject: [PATCH 04/59] add recursive mode and clean up whitelist where we can --- rustfmt-core/rustfmt-lib/src/test/mod.rs | 13 +------------ rustfmt-core/rustfmt-lib/tests/source/cfg_if/lib.rs | 1 + rustfmt-core/rustfmt-lib/tests/target/cfg_if/lib.rs | 1 + 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/rustfmt-core/rustfmt-lib/src/test/mod.rs b/rustfmt-core/rustfmt-lib/src/test/mod.rs index d5af64292bd..1d7608394c8 100644 --- a/rustfmt-core/rustfmt-lib/src/test/mod.rs +++ b/rustfmt-core/rustfmt-lib/src/test/mod.rs @@ -21,21 +21,10 @@ const DIFF_CONTEXT_SIZE: usize = 3; // A list of files on which we want to skip testing. const SKIP_FILE_WHITE_LIST: &[&str] = &[ + "issue-3253/paths", "issue-3434/no_entry.rs", "issue-3665/sub_mod.rs", - // Testing for issue-3779 "issue-3779/ice.rs", - // These files and directory are a part of modules defined inside `cfg_if!`. - "cfg_if/mod.rs", - "cfg_if/detect", - "issue-3253/foo.rs", - "issue-3253/bar.rs", - "issue-3253/paths", - // These files and directory are a part of modules defined inside `cfg_attr(..)`. - "cfg_mod/dir", - "cfg_mod/bar.rs", - "cfg_mod/foo.rs", - "cfg_mod/wasm32.rs", // We want to ensure `recursive` is working correctly, so do not test // these files directly "configs/recursive/disabled/foo.rs", diff --git a/rustfmt-core/rustfmt-lib/tests/source/cfg_if/lib.rs b/rustfmt-core/rustfmt-lib/tests/source/cfg_if/lib.rs index 8b3bb304f1c..bb333be01a9 100644 --- a/rustfmt-core/rustfmt-lib/tests/source/cfg_if/lib.rs +++ b/rustfmt-core/rustfmt-lib/tests/source/cfg_if/lib.rs @@ -10,6 +10,7 @@ //! * `mips64`: [`is_mips64_feature_detected`] //! * `powerpc`: [`is_powerpc_feature_detected`] //! * `powerpc64`: [`is_powerpc64_feature_detected`] +// rustfmt-recursive: true #![unstable(feature = "stdsimd", issue = "27731")] #![feature(const_fn, staged_api, stdsimd, doc_cfg, allow_internal_unstable)] diff --git a/rustfmt-core/rustfmt-lib/tests/target/cfg_if/lib.rs b/rustfmt-core/rustfmt-lib/tests/target/cfg_if/lib.rs index 8b3bb304f1c..bb333be01a9 100644 --- a/rustfmt-core/rustfmt-lib/tests/target/cfg_if/lib.rs +++ b/rustfmt-core/rustfmt-lib/tests/target/cfg_if/lib.rs @@ -10,6 +10,7 @@ //! * `mips64`: [`is_mips64_feature_detected`] //! * `powerpc`: [`is_powerpc_feature_detected`] //! * `powerpc64`: [`is_powerpc64_feature_detected`] +// rustfmt-recursive: true #![unstable(feature = "stdsimd", issue = "27731")] #![feature(const_fn, staged_api, stdsimd, doc_cfg, allow_internal_unstable)] From 278a4f109af382b8a257d6b47f4410fb1088236a Mon Sep 17 00:00:00 2001 From: bradleypmartin Date: Mon, 27 Apr 2020 21:44:55 -0600 Subject: [PATCH 05/59] move recursive setting to top of lib.rs files --- rustfmt-core/rustfmt-lib/tests/source/cfg_if/lib.rs | 3 ++- rustfmt-core/rustfmt-lib/tests/target/cfg_if/lib.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/rustfmt-core/rustfmt-lib/tests/source/cfg_if/lib.rs b/rustfmt-core/rustfmt-lib/tests/source/cfg_if/lib.rs index bb333be01a9..17e76286a61 100644 --- a/rustfmt-core/rustfmt-lib/tests/source/cfg_if/lib.rs +++ b/rustfmt-core/rustfmt-lib/tests/source/cfg_if/lib.rs @@ -1,3 +1,5 @@ +// rustfmt-recursive: true + //! Run-time feature detection for the Rust standard library. //! //! To detect whether a feature is enabled in the system running the binary @@ -10,7 +12,6 @@ //! * `mips64`: [`is_mips64_feature_detected`] //! * `powerpc`: [`is_powerpc_feature_detected`] //! * `powerpc64`: [`is_powerpc64_feature_detected`] -// rustfmt-recursive: true #![unstable(feature = "stdsimd", issue = "27731")] #![feature(const_fn, staged_api, stdsimd, doc_cfg, allow_internal_unstable)] diff --git a/rustfmt-core/rustfmt-lib/tests/target/cfg_if/lib.rs b/rustfmt-core/rustfmt-lib/tests/target/cfg_if/lib.rs index bb333be01a9..17e76286a61 100644 --- a/rustfmt-core/rustfmt-lib/tests/target/cfg_if/lib.rs +++ b/rustfmt-core/rustfmt-lib/tests/target/cfg_if/lib.rs @@ -1,3 +1,5 @@ +// rustfmt-recursive: true + //! Run-time feature detection for the Rust standard library. //! //! To detect whether a feature is enabled in the system running the binary @@ -10,7 +12,6 @@ //! * `mips64`: [`is_mips64_feature_detected`] //! * `powerpc`: [`is_powerpc_feature_detected`] //! * `powerpc64`: [`is_powerpc64_feature_detected`] -// rustfmt-recursive: true #![unstable(feature = "stdsimd", issue = "27731")] #![feature(const_fn, staged_api, stdsimd, doc_cfg, allow_internal_unstable)] From f0cce5b5269b783d5834c36cf5d5279947d8ceb2 Mon Sep 17 00:00:00 2001 From: bradleypmartin Date: Tue, 28 Apr 2020 08:36:30 -0600 Subject: [PATCH 06/59] rustfmt-core/rustfmt-lib/src/test/mod.rs : revert skipped files --- rustfmt-core/rustfmt-lib/src/test/mod.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/rustfmt-core/rustfmt-lib/src/test/mod.rs b/rustfmt-core/rustfmt-lib/src/test/mod.rs index 1d7608394c8..d5af64292bd 100644 --- a/rustfmt-core/rustfmt-lib/src/test/mod.rs +++ b/rustfmt-core/rustfmt-lib/src/test/mod.rs @@ -21,10 +21,21 @@ const DIFF_CONTEXT_SIZE: usize = 3; // A list of files on which we want to skip testing. const SKIP_FILE_WHITE_LIST: &[&str] = &[ - "issue-3253/paths", "issue-3434/no_entry.rs", "issue-3665/sub_mod.rs", + // Testing for issue-3779 "issue-3779/ice.rs", + // These files and directory are a part of modules defined inside `cfg_if!`. + "cfg_if/mod.rs", + "cfg_if/detect", + "issue-3253/foo.rs", + "issue-3253/bar.rs", + "issue-3253/paths", + // These files and directory are a part of modules defined inside `cfg_attr(..)`. + "cfg_mod/dir", + "cfg_mod/bar.rs", + "cfg_mod/foo.rs", + "cfg_mod/wasm32.rs", // We want to ensure `recursive` is working correctly, so do not test // these files directly "configs/recursive/disabled/foo.rs", From 010c678afe107b3c9564bf4393656e5ec12ac15e Mon Sep 17 00:00:00 2001 From: Koki Nishihara Date: Fri, 1 May 2020 12:43:02 +0900 Subject: [PATCH 07/59] Update diff.rs (#4150) --- rustfmt-core/rustfmt-lib/src/emitter/diff.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustfmt-core/rustfmt-lib/src/emitter/diff.rs b/rustfmt-core/rustfmt-lib/src/emitter/diff.rs index f1e905180f5..dc5908155c9 100644 --- a/rustfmt-core/rustfmt-lib/src/emitter/diff.rs +++ b/rustfmt-core/rustfmt-lib/src/emitter/diff.rs @@ -33,7 +33,7 @@ impl Emitter for DiffEmitter { } else { print_diff( mismatch, - |line_num| format!("Diff in {} at line {}:", filename, line_num), + |line_num| format!("Diff in {}:{}:", filename, line_num), &self.config, ); } From 759aaf7391a8362bbe0fa35bf40a08743176f810 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sun, 3 May 2020 15:13:46 -0500 Subject: [PATCH 08/59] docs: clarify config opts availability [skip ci] (#4155) --- Configurations.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Configurations.md b/Configurations.md index 6ba78e714e0..f75cb71a3e1 100644 --- a/Configurations.md +++ b/Configurations.md @@ -15,7 +15,11 @@ To enable unstable options, set `unstable_features = true` in `rustfmt.toml` or # Configuration Options -Below you find a detailed visual guide on all the supported configuration options of rustfmt: +Below you can find a detailed visual guide on all the supported configuration options of rustfmt. + +**_Note that the below list reflects the configuration options available on the latest version of rustfmt in source control. Some newer options may not be available yet in a released version of rustfmt_** + + ## `array_width` From 58c6c796d6ef7f00cc70a79aa8e54ad936d6c895 Mon Sep 17 00:00:00 2001 From: Cameron Taggart Date: Mon, 4 May 2020 21:41:30 -0600 Subject: [PATCH 09/59] update to rustc 656 --- Cargo.lock | 149 ++++++++++++++-------------- rustfmt-core/rustfmt-lib/Cargo.toml | 16 +-- 2 files changed, 81 insertions(+), 84 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2bf1e0d05ad..4ea282147e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -386,9 +386,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d737e0f947a1864e93d33fdef4af8445a00d1ed8dc0c8ddb73139ea6abf15" +checksum = "61565ff7aaace3525556587bd2dc31d4a07071957be715e63ce7b1eccf51a8f4" dependencies = [ "libc", ] @@ -581,7 +581,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" dependencies = [ "lock_api", - "parking_lot_core 0.7.1", + "parking_lot_core 0.7.2", ] [[package]] @@ -601,15 +601,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e136c1904604defe99ce5fd71a28d473fa60a12255d511aa78a9ddf11237aeb" +checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" dependencies = [ "cfg-if", "cloudabi", "libc", "redox_syscall", - "smallvec 1.3.0", + "smallvec 1.4.0", "winapi", ] @@ -641,9 +641,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.10" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3" +checksum = "8872cf6f48eee44265156c111456a700ab3483686b3f96df4cf5481c89157319" dependencies = [ "unicode-xid", ] @@ -656,9 +656,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" +checksum = "4c1f4b0efa5fc5e8ceb705136bfee52cfdb6a4e3509f770b478cd6ed434232a7" dependencies = [ "proc-macro2", ] @@ -712,25 +712,25 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "654.0.0" +version = "656.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfcfbb0ddfd533abf8c076e3b49d1e5042d1962526a12ce2c66d514b24cca3" +checksum = "fb6df19dd0afdfda2ff7e1dc33c23ac5e77be2298dfce76b0be90df852fde281" dependencies = [ "rustc-ap-rustc_data_structures", - "smallvec 1.3.0", + "smallvec 1.4.0", ] [[package]] name = "rustc-ap-graphviz" -version = "654.0.0" +version = "656.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7490bb07b014a7f9531bde33c905a805e08095dbefdb4c9988a1b19fe6d019fd" +checksum = "c7771196b6eb99a166cf1dd8deb974b492fdf96e090d5a55db6cb5cf9f517afa" [[package]] name = "rustc-ap-rustc_ast" -version = "654.0.0" +version = "656.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "189f16dbb8dd11089274c9ced58b0cae9e1ea3e434a58f3db683817eda849e58" +checksum = "edc1cfea59f901244ab488cfd4615da786208e5bd75d782abdbf5c94eccb6280" dependencies = [ "log", "rustc-ap-rustc_data_structures", @@ -740,14 +740,14 @@ dependencies = [ "rustc-ap-rustc_span", "rustc-ap-serialize", "scoped-tls", - "smallvec 1.3.0", + "smallvec 1.4.0", ] [[package]] name = "rustc-ap-rustc_ast_passes" -version = "654.0.0" +version = "656.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe619609b56a617fa986332b066d53270093c816d8ff8281fc90e1dbe74c1cc" +checksum = "fe14bcea3dd2a44f89e2d5ca453838e8d71ebaaede2c265eaed3fa044ce7358e" dependencies = [ "itertools", "log", @@ -764,21 +764,20 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_ast_pretty" -version = "654.0.0" +version = "656.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26ab1495f7b420e937688749c1da5763aaabd6ebe8cacb758665a0b8481da094" +checksum = "83c4ea460aa09e592f89ddab2efcfde050bd963bf02740347293294a40c1c757" dependencies = [ "log", "rustc-ap-rustc_ast", - "rustc-ap-rustc_data_structures", "rustc-ap-rustc_span", ] [[package]] name = "rustc-ap-rustc_attr" -version = "654.0.0" +version = "656.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e057495724c60729c1d1d9d49374e0b3ebd6d3481cd161b2871f52fe017b7b5" +checksum = "f0a2f931847e5967f69622bc9ffd47d4d4ce5444f5165a036c2eda0000ff4eeb" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_ast_pretty", @@ -789,14 +788,13 @@ dependencies = [ "rustc-ap-rustc_session", "rustc-ap-rustc_span", "rustc-ap-serialize", - "smallvec 1.3.0", ] [[package]] name = "rustc-ap-rustc_data_structures" -version = "654.0.0" +version = "656.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2130997667833692f4bec4681d0e73b066d5a01dac1d8a68f22068b82bf173a" +checksum = "e105049018a06b05bcab026d751b5ccfa320cb6b078d1aaf2884121dbc939df3" dependencies = [ "bitflags", "cfg-if", @@ -815,16 +813,16 @@ dependencies = [ "rustc-hash", "rustc-rayon", "rustc-rayon-core", - "smallvec 1.3.0", + "smallvec 1.4.0", "stable_deref_trait", "winapi", ] [[package]] name = "rustc-ap-rustc_errors" -version = "654.0.0" +version = "656.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "908e1ea187c6bb368af4ba6db980001e920515e67371ddc4086e749baabe6080" +checksum = "b3fb69cb302869dd8398a268c4dae19cfcaf39eaeb121374237d393232ab9ca8" dependencies = [ "annotate-snippets", "atty", @@ -840,9 +838,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_expand" -version = "654.0.0" +version = "656.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50066a75bca872ff933b0ee8a582d18ef1876c8054a392f60c39e538446bfb00" +checksum = "25d47c4dac84f583e36c6fabb60f7cbf12fae90aa77d45593f71f24b13b006d3" dependencies = [ "log", "rustc-ap-rustc_ast", @@ -857,14 +855,14 @@ dependencies = [ "rustc-ap-rustc_session", "rustc-ap-rustc_span", "rustc-ap-serialize", - "smallvec 1.3.0", + "smallvec 1.4.0", ] [[package]] name = "rustc-ap-rustc_feature" -version = "654.0.0" +version = "656.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96fb53e1710e6de7c2e371ca56c857b79f9b399aba58aa6b6fbed6e2f677d3f6" +checksum = "298f0c625a922d4675b91db3fac7d3b587849667a166c19eee2596e7edef9712" dependencies = [ "lazy_static", "rustc-ap-rustc_data_structures", @@ -873,34 +871,34 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_fs_util" -version = "654.0.0" +version = "656.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3f91357e5e468fc2729211571d769723c728a34e200d90a70164e945f881e09" +checksum = "b16f794f99d7a115ee9d5e73dada35d9cb553b0c6c34b3549f38960c9c301c62" [[package]] name = "rustc-ap-rustc_index" -version = "654.0.0" +version = "656.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32220c3e6cdf226f38e4474b747dca15f3106bb680c74f10b299af3f6cdb1663" +checksum = "59edea7fb099ca9589268aa8676b741f43db5c6f1bc1ced231db9d56e2aa9f94" dependencies = [ "rustc-ap-serialize", - "smallvec 1.3.0", + "smallvec 1.4.0", ] [[package]] name = "rustc-ap-rustc_lexer" -version = "654.0.0" +version = "656.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b324d2a2bacad344e53e182e5ca04ffb74745b932849aa074f8f7fec8177da5" +checksum = "9cbba98ec46e96a4663197dfa8c0378752de2006e314e5400c0ca74929d6692f" dependencies = [ "unicode-xid", ] [[package]] name = "rustc-ap-rustc_macros" -version = "654.0.0" +version = "656.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59686c56d5f1b3ed47d0f070c257ed35caf24ecf2d744dd11fe44b1014baee0f" +checksum = "73f36ca24a130773044800e6806bf890365afb6175df8ab32efa59c577a11d4e" dependencies = [ "proc-macro2", "quote", @@ -910,9 +908,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_parse" -version = "654.0.0" +version = "656.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfb0c11c591ec5f87bbadb10819795abc9035ff79a26703c1b6c9487ac51f49" +checksum = "f7ec08a2f8e98799a668e24578cb6e1b37ddca25132badd4b07ebb2cb6412b90" dependencies = [ "bitflags", "log", @@ -924,15 +922,14 @@ dependencies = [ "rustc-ap-rustc_lexer", "rustc-ap-rustc_session", "rustc-ap-rustc_span", - "smallvec 1.3.0", "unicode-normalization", ] [[package]] name = "rustc-ap-rustc_session" -version = "654.0.0" +version = "656.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1a194b1a81d7233ee492847638dc9ebdb7d084300e5ade8dea0ceaa98f95b9" +checksum = "1661cc89ec2e1992d686955aa24fa358ee5af11fdd91ecacb63575ae33c0c6b4" dependencies = [ "getopts", "log", @@ -950,9 +947,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_span" -version = "654.0.0" +version = "656.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a648146050fed6b58e681ec22488e728f60e16036bb7497c9815e3debd1e4242" +checksum = "2afe35ea88a8f61198ff08f627fa3c5ef925e8d4ba23e678d8ab07d76b2999bb" dependencies = [ "cfg-if", "log", @@ -969,9 +966,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_target" -version = "654.0.0" +version = "656.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cf28798f0988b808e3616713630e4098d68c6f1f41052a2f7e922e094da744" +checksum = "00835074c37fc7cb377477c24dc8ca3cbaab7e3451925f8844e1a13eea5ec8cc" dependencies = [ "bitflags", "log", @@ -984,12 +981,12 @@ dependencies = [ [[package]] name = "rustc-ap-serialize" -version = "654.0.0" +version = "656.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "756e8f526ec7906e132188bf25e3c10a6ee42ab77294ecb3b3602647f0508eef" +checksum = "5b2ca2e47af678242e35e38518a64b97bc61b83b6e833c3ae734400f836679a6" dependencies = [ "indexmap", - "smallvec 1.3.0", + "smallvec 1.4.0", ] [[package]] @@ -1103,9 +1100,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76" +checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" [[package]] name = "same-file" @@ -1166,9 +1163,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.51" +version = "1.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da07b57ee2623368351e9a0488bb0b261322a15a6e0ae53e243cbdc0f4208da9" +checksum = "a7894c8ed05b7a3a279aeb79025fdec1d3158080b75b98a08faf2806bb799edd" dependencies = [ "itoa", "ryu", @@ -1198,9 +1195,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05720e22615919e4734f6a99ceae50d00226c3c5aca406e102ebc33298214e0a" +checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4" [[package]] name = "stable_deref_trait" @@ -1216,9 +1213,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff6da2e8d107dfd7b74df5ef4d205c6aebee0706c647f6bc6a2d5789905c00fb" +checksum = "863246aaf5ddd0d6928dfeb1a9ca65f505599e4e1b399935ef7e75107516b4ef" dependencies = [ "clap", "lazy_static", @@ -1227,9 +1224,9 @@ dependencies = [ [[package]] name = "structopt-derive" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a489c87c08fbaf12e386665109dd13470dcc9c4583ea3e10dd2b4523e5ebd9ac" +checksum = "d239ca4b13aee7a2142e6795cbd69e457665ff8037aed33b3effdc430d2f927a" dependencies = [ "heck", "proc-macro-error", @@ -1240,9 +1237,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03" +checksum = "410a7488c0a728c7ceb4ad59b9567eb4053d02e8cc7f5c0e0eeeb39518369213" dependencies = [ "proc-macro2", "quote", @@ -1312,18 +1309,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b3d3d2ff68104100ab257bb6bb0cb26c901abe4bd4ba15961f3bf867924012" +checksum = "d12a1dae4add0f0d568eebc7bf142f145ba1aa2544cafb195c76f0f409091b60" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca972988113b7715266f91250ddb98070d033c62a011fa0fcc57434a649310dd" +checksum = "3f34e0c1caaa462fd840ec6b768946ea1e7842620d94fe29d5b847138f521269" dependencies = [ "proc-macro2", "quote", @@ -1360,7 +1357,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" dependencies = [ - "smallvec 1.3.0", + "smallvec 1.4.0", ] [[package]] @@ -1434,9 +1431,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa515c5163a99cc82bab70fd3bfdd36d827be85de63737b40fcef2ce084a436e" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ "winapi", ] diff --git a/rustfmt-core/rustfmt-lib/Cargo.toml b/rustfmt-core/rustfmt-lib/Cargo.toml index bac246be139..8609cc8e243 100644 --- a/rustfmt-core/rustfmt-lib/Cargo.toml +++ b/rustfmt-core/rustfmt-lib/Cargo.toml @@ -59,32 +59,32 @@ env_logger = "0.7" [dependencies.rustc_ast] package = "rustc-ap-rustc_ast" -version = "654.0.0" +version = "656.0.0" [dependencies.rustc_ast_pretty] package = "rustc-ap-rustc_ast_pretty" -version = "654.0.0" +version = "656.0.0" [dependencies.rustc_data_structures] package = "rustc-ap-rustc_data_structures" -version = "654.0.0" +version = "656.0.0" [dependencies.rustc_errors] package = "rustc-ap-rustc_errors" -version = "654.0.0" +version = "656.0.0" [dependencies.rustc_expand] package = "rustc-ap-rustc_expand" -version = "654.0.0" +version = "656.0.0" [dependencies.rustc_parse] package = "rustc-ap-rustc_parse" -version = "654.0.0" +version = "656.0.0" [dependencies.rustc_session] package = "rustc-ap-rustc_session" -version = "654.0.0" +version = "656.0.0" [dependencies.rustc_span] package = "rustc-ap-rustc_span" -version = "654.0.0" +version = "656.0.0" From ce8493ab794f7ab551a379572742586413db1bdb Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 7 May 2020 22:21:59 +0900 Subject: [PATCH 10/59] Remove disable_all_formatting (#4147) --- Configurations.md | 8 ----- rustfmt-core/rustfmt-bin/src/bin/main.rs | 29 ------------------- .../tests/config/disable_all_formatting.toml | 1 - rustfmt-core/rustfmt-lib/src/config.rs | 2 -- rustfmt-core/rustfmt-lib/src/formatting.rs | 10 ------- .../configs/disable_all_formatting/false.rs | 6 ---- .../configs/disable_all_formatting/true.rs | 6 ---- .../configs/disable_all_formatting/false.rs | 10 ------- .../configs/disable_all_formatting/true.rs | 6 ---- 9 files changed, 78 deletions(-) delete mode 100644 rustfmt-core/rustfmt-bin/tests/config/disable_all_formatting.toml delete mode 100644 rustfmt-core/rustfmt-lib/tests/source/configs/disable_all_formatting/false.rs delete mode 100644 rustfmt-core/rustfmt-lib/tests/source/configs/disable_all_formatting/true.rs delete mode 100644 rustfmt-core/rustfmt-lib/tests/target/configs/disable_all_formatting/false.rs delete mode 100644 rustfmt-core/rustfmt-lib/tests/target/configs/disable_all_formatting/true.rs diff --git a/Configurations.md b/Configurations.md index f75cb71a3e1..377d0c0e931 100644 --- a/Configurations.md +++ b/Configurations.md @@ -523,14 +523,6 @@ fn main() { } ``` -## `disable_all_formatting` - -Don't reformat anything - -- **Default value**: `false` -- **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: [#3388](https://github.com/rust-lang/rustfmt/issues/3388)) - ## `edition` Specifies which edition is used by the parser. diff --git a/rustfmt-core/rustfmt-bin/src/bin/main.rs b/rustfmt-core/rustfmt-bin/src/bin/main.rs index 512fd311107..49d45e984f5 100644 --- a/rustfmt-core/rustfmt-bin/src/bin/main.rs +++ b/rustfmt-core/rustfmt-bin/src/bin/main.rs @@ -567,35 +567,6 @@ mod test { let _ = env_logger::builder().is_test(true).try_init(); } - #[test] - fn stdin_disable_all_formatting_test() { - init_log(); - match option_env!("CFG_RELEASE_CHANNEL") { - None | Some("nightly") => {} - // These tests require nightly. - _ => return, - } - let input = "fn main() { println!(\"This should not be formatted.\"); }"; - let mut child = Command::new(rustfmt()) - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .arg("--config-path=./tests/config/disable_all_formatting.toml") - .spawn() - .expect("failed to execute child"); - - { - let stdin = child.stdin.as_mut().expect("failed to get stdin"); - stdin - .write_all(input.as_bytes()) - .expect("failed to write stdin"); - } - - let output = child.wait_with_output().expect("failed to wait on child"); - assert!(output.status.success()); - assert!(output.stderr.is_empty()); - assert_eq!(input, String::from_utf8(output.stdout).unwrap()); - } - #[test] fn format_lines_errors_are_reported() { init_log(); diff --git a/rustfmt-core/rustfmt-bin/tests/config/disable_all_formatting.toml b/rustfmt-core/rustfmt-bin/tests/config/disable_all_formatting.toml deleted file mode 100644 index c7ad93bafe3..00000000000 --- a/rustfmt-core/rustfmt-bin/tests/config/disable_all_formatting.toml +++ /dev/null @@ -1 +0,0 @@ -disable_all_formatting = true diff --git a/rustfmt-core/rustfmt-lib/src/config.rs b/rustfmt-core/rustfmt-lib/src/config.rs index 6b1c73ee4c1..27ee1881397 100644 --- a/rustfmt-core/rustfmt-lib/src/config.rs +++ b/rustfmt-core/rustfmt-lib/src/config.rs @@ -144,7 +144,6 @@ create_config! { "Require a specific version of rustfmt"; unstable_features: bool, false, false, "Enables unstable features. Only available on nightly channel"; - disable_all_formatting: bool, false, false, "Don't reformat anything"; hide_parse_errors: bool, false, false, "Hide errors from the parser"; error_on_line_overflow: bool, false, false, "Error if unable to get all lines within max_width"; error_on_unformatted: bool, false, false, @@ -572,7 +571,6 @@ condense_wildcard_suffixes = false color = "Auto" required_version = "{}" unstable_features = false -disable_all_formatting = false hide_parse_errors = false error_on_line_overflow = false error_on_unformatted = false diff --git a/rustfmt-core/rustfmt-lib/src/formatting.rs b/rustfmt-core/rustfmt-lib/src/formatting.rs index a3766a99f43..1f92b005e66 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting.rs @@ -29,16 +29,6 @@ impl<'b, T: Write + 'b> Session<'b, T> { } rustc_ast::with_globals(self.config.edition().into(), || { - if self.config.disable_all_formatting() { - // When the input is from stdin, echo back the input. - if let Input::Text(ref buf) = input { - if let Err(e) = io::stdout().write_all(buf.as_bytes()) { - return Err(From::from(e)); - } - } - return Ok(FormatReport::new()); - } - let config = &self.config.clone(); let format_result = format_project(input, config, self); diff --git a/rustfmt-core/rustfmt-lib/tests/source/configs/disable_all_formatting/false.rs b/rustfmt-core/rustfmt-lib/tests/source/configs/disable_all_formatting/false.rs deleted file mode 100644 index 834ca7a3c89..00000000000 --- a/rustfmt-core/rustfmt-lib/tests/source/configs/disable_all_formatting/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-disable_all_formatting: false -// Disable all formatting - -fn main() { - if lorem{println!("ipsum!");}else{println!("dolor!");} -} diff --git a/rustfmt-core/rustfmt-lib/tests/source/configs/disable_all_formatting/true.rs b/rustfmt-core/rustfmt-lib/tests/source/configs/disable_all_formatting/true.rs deleted file mode 100644 index 56955bf384d..00000000000 --- a/rustfmt-core/rustfmt-lib/tests/source/configs/disable_all_formatting/true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-disable_all_formatting: true -// Disable all formatting - -fn main() { - iflorem{println!("ipsum!");}else{println!("dolor!");} -} diff --git a/rustfmt-core/rustfmt-lib/tests/target/configs/disable_all_formatting/false.rs b/rustfmt-core/rustfmt-lib/tests/target/configs/disable_all_formatting/false.rs deleted file mode 100644 index 1a0477ddb39..00000000000 --- a/rustfmt-core/rustfmt-lib/tests/target/configs/disable_all_formatting/false.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-disable_all_formatting: false -// Disable all formatting - -fn main() { - if lorem { - println!("ipsum!"); - } else { - println!("dolor!"); - } -} diff --git a/rustfmt-core/rustfmt-lib/tests/target/configs/disable_all_formatting/true.rs b/rustfmt-core/rustfmt-lib/tests/target/configs/disable_all_formatting/true.rs deleted file mode 100644 index 736ccf56942..00000000000 --- a/rustfmt-core/rustfmt-lib/tests/target/configs/disable_all_formatting/true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-disable_all_formatting: true -// Disable all formatting - -fn main() { - if lorem{println!("ipsum!");}else{println!("dolor!");} -} From 445f71e16ef68a0525fc479dff59b3fc5c9a151e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 30 Apr 2020 03:51:45 +0200 Subject: [PATCH 11/59] Stabilize binop_separator. Servo has used this since forever, and it'd be useful to be able to use rustfmt stable there so that we can use the same rustfmt version in both Firefox and Servo. Feel free to close this if there's any reason it shouldn't be done. Closes #3368 --- Configurations.md | 2 +- rustfmt-core/rustfmt-lib/src/config.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Configurations.md b/Configurations.md index 377d0c0e931..aea2673f567 100644 --- a/Configurations.md +++ b/Configurations.md @@ -51,7 +51,7 @@ Where to put a binary operator when a binary expression goes multiline. - **Default value**: `"Front"` - **Possible values**: `"Front"`, `"Back"` -- **Stable**: No (tracking issue: [#3368](https://github.com/rust-lang/rustfmt/issues/3368)) +- **Stable**: Yes #### `"Front"` (default): diff --git a/rustfmt-core/rustfmt-lib/src/config.rs b/rustfmt-core/rustfmt-lib/src/config.rs index 27ee1881397..e479608841a 100644 --- a/rustfmt-core/rustfmt-lib/src/config.rs +++ b/rustfmt-core/rustfmt-lib/src/config.rs @@ -92,7 +92,7 @@ create_config! { space_around_attr_eq: bool, true, false, "Determines if '=' are wrapped in spaces in attributes."; spaces_around_ranges: bool, false, false, "Put spaces around the .. and ..= range operators"; - binop_separator: SeparatorPlace, SeparatorPlace::Front, false, + binop_separator: SeparatorPlace, SeparatorPlace::Front, true, "Where to put a binary operator when a binary expression goes multiline"; // Misc. From 552475229680f9f9bdea9021051d206377188afe Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Sat, 9 May 2020 15:19:48 -0700 Subject: [PATCH 12/59] Preserve and format type aliases in extern blocks Previously, non-trivial type aliases in extern blocks were dropped by rustfmt because only the type alias name would be passed to a rewritter. This commit fixes that by passing all type information (generics, bounds, and assignments) to a type alias rewritter, and consolidates `rewrite_type_alias` and `rewrite_associated_type` as one function. Closes #4159 --- rustfmt-core/rustfmt-lib/src/items.rs | 95 +++++++++++-------- rustfmt-core/rustfmt-lib/src/visitor.rs | 16 ++-- .../rustfmt-lib/tests/target/issue-4159.rs | 18 ++++ 3 files changed, 81 insertions(+), 48 deletions(-) create mode 100644 rustfmt-core/rustfmt-lib/tests/target/issue-4159.rs diff --git a/rustfmt-core/rustfmt-lib/src/items.rs b/rustfmt-core/rustfmt-lib/src/items.rs index 3b71f1bb19d..45c225fb028 100644 --- a/rustfmt-core/rustfmt-lib/src/items.rs +++ b/rustfmt-core/rustfmt-lib/src/items.rs @@ -1562,6 +1562,7 @@ fn rewrite_type_prefix( prefix: &str, ident: ast::Ident, generics: &ast::Generics, + generic_bounds_opt: Option<&ast::GenericBounds>, ) -> Option { let mut result = String::with_capacity(128); result.push_str(prefix); @@ -1578,6 +1579,19 @@ fn rewrite_type_prefix( result.push_str(&generics_str); } + let type_bounds_str = if let Some(bounds) = generic_bounds_opt { + if bounds.is_empty() { + String::new() + } else { + // 2 = `: ` + let shape = Shape::indented(indent, context.config).offset_left(result.len() + 2)?; + bounds.rewrite(context, shape).map(|s| format!(": {}", s))? + } + } else { + String::new() + }; + result.push_str(&type_bounds_str); + let where_budget = context.budget(last_line_width(&result)); let option = WhereClauseOption::snuggled(&result); let where_clause_str = rewrite_where_clause( @@ -1604,6 +1618,7 @@ fn rewrite_type_item( ident: ast::Ident, rhs: &R, generics: &ast::Generics, + generic_bounds_opt: Option<&ast::GenericBounds>, vis: &ast::Visibility, ) -> Option { let mut result = String::with_capacity(128); @@ -1613,6 +1628,7 @@ fn rewrite_type_item( &format!("{}{} ", format_visibility(context, vis), prefix), ident, generics, + generic_bounds_opt, )?); if generics.where_clause.predicates.is_empty() { @@ -1627,17 +1643,6 @@ fn rewrite_type_item( rewrite_assign_rhs(context, result, rhs, rhs_shape).map(|s| s + ";") } -pub(crate) fn rewrite_type_alias( - context: &RewriteContext<'_>, - indent: Indent, - ident: ast::Ident, - ty: &ast::Ty, - generics: &ast::Generics, - vis: &ast::Visibility, -) -> Option { - rewrite_type_item(context, indent, "type", " =", ident, ty, generics, vis) -} - pub(crate) fn rewrite_opaque_type( context: &RewriteContext<'_>, indent: Indent, @@ -1655,6 +1660,7 @@ pub(crate) fn rewrite_opaque_type( ident, &opaque_type_bounds, generics, + Some(generic_bounds), vis, ) } @@ -1897,39 +1903,39 @@ fn rewrite_static( } } -pub(crate) fn rewrite_associated_type( +pub(crate) fn rewrite_type_alias( ident: ast::Ident, ty_opt: Option<&ptr::P>, generics: &ast::Generics, generic_bounds_opt: Option<&ast::GenericBounds>, context: &RewriteContext<'_>, indent: Indent, + vis: &ast::Visibility, ) -> Option { - let ident_str = rewrite_ident(context, ident); - // 5 = "type " - let generics_shape = Shape::indented(indent, context.config).offset_left(5)?; - let generics_str = rewrite_generics(context, ident_str, generics, generics_shape)?; - let prefix = format!("type {}", generics_str); - - let type_bounds_str = if let Some(bounds) = generic_bounds_opt { - if bounds.is_empty() { - String::new() - } else { - // 2 = ": ".len() - let shape = Shape::indented(indent, context.config).offset_left(prefix.len() + 2)?; - bounds.rewrite(context, shape).map(|s| format!(": {}", s))? - } - } else { - String::new() - }; + let mut prefix = rewrite_type_prefix( + context, + indent, + &format!("{}type ", format_visibility(context, vis)), + ident, + generics, + generic_bounds_opt, + )?; if let Some(ty) = ty_opt { // 1 = `;` let shape = Shape::indented(indent, context.config).sub_width(1)?; - let lhs = format!("{}{} =", prefix, type_bounds_str); + + // If there's a where clause, add a newline before the assignment. Otherwise just add a + // space. + if !generics.where_clause.predicates.is_empty() { + prefix.push_str(&indent.to_string_with_newline(context.config)); + } else { + prefix.push(' '); + } + let lhs = format!("{}=", prefix); rewrite_assign_rhs(context, lhs, &**ty, shape).map(|s| s + ";") } else { - Some(format!("{}{};", prefix, type_bounds_str)) + Some(format!("{};", prefix)) } } @@ -1973,13 +1979,14 @@ pub(crate) fn rewrite_opaque_impl_type( pub(crate) fn rewrite_associated_impl_type( ident: ast::Ident, + vis: &ast::Visibility, defaultness: ast::Defaultness, ty_opt: Option<&ptr::P>, generics: &ast::Generics, context: &RewriteContext<'_>, indent: Indent, ) -> Option { - let result = rewrite_associated_type(ident, ty_opt, generics, None, context, indent)?; + let result = rewrite_type_alias(ident, ty_opt, generics, None, context, indent, vis)?; match defaultness { ast::Defaultness::Default(..) => Some(format!("default {}", result)), @@ -3132,7 +3139,7 @@ impl Rewrite for ast::ForeignItem { // FIXME: this may be a faulty span from libsyntax. let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1)); - let item_str = match self.kind { + let item_str: String = match self.kind { ast::ForeignItemKind::Fn(_, ref fn_sig, ref generics, _) => rewrite_fn_base( context, shape.indent, @@ -3156,14 +3163,20 @@ impl Rewrite for ast::ForeignItem { // 1 = ; rewrite_assign_rhs(context, prefix, &**ty, shape.sub_width(1)?).map(|s| s + ";") } - ast::ForeignItemKind::TyAlias(..) => { - let vis = format_visibility(context, &self.vis); - Some(format!( - "{}type {};", - vis, - rewrite_ident(context, self.ident) - )) - } + ast::ForeignItemKind::TyAlias( + _, + ref generics, + ref generic_bounds, + ref type_default, + ) => rewrite_type_alias( + self.ident, + type_default.as_ref(), + generics, + Some(generic_bounds), + &context, + shape.indent, + &self.vis, + ), ast::ForeignItemKind::MacCall(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Item) } diff --git a/rustfmt-core/rustfmt-lib/src/visitor.rs b/rustfmt-core/rustfmt-lib/src/visitor.rs index 1a1a5368d9f..02c6cffe4a9 100644 --- a/rustfmt-core/rustfmt-lib/src/visitor.rs +++ b/rustfmt-core/rustfmt-lib/src/visitor.rs @@ -9,9 +9,8 @@ use crate::comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; use crate::config::{BraceStyle, Config}; use crate::items::{ format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, - rewrite_associated_impl_type, rewrite_associated_type, rewrite_extern_crate, - rewrite_opaque_impl_type, rewrite_opaque_type, rewrite_type_alias, FnBraceStyle, FnSig, - StaticParts, StructParts, + rewrite_associated_impl_type, rewrite_extern_crate, rewrite_opaque_impl_type, + rewrite_opaque_type, rewrite_type_alias, FnBraceStyle, FnSig, StaticParts, StructParts, }; use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition}; use crate::rewrite::{Rewrite, RewriteContext}; @@ -538,11 +537,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ast::ItemKind::TyAlias(_, ref generics, ref generic_bounds, ref ty) => match ty { Some(ty) => { let rewrite = rewrite_type_alias( - &self.get_context(), - self.block_indent, item.ident, - &*ty, + Some(&*ty), generics, + Some(generic_bounds), + &self.get_context(), + self.block_indent, &item.vis, ); self.push_rewrite(item.span, rewrite); @@ -609,13 +609,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ); } ast::AssocItemKind::TyAlias(_, ref generics, ref generic_bounds, ref type_default) => { - let rewrite = rewrite_associated_type( + let rewrite = rewrite_type_alias( ti.ident, type_default.as_ref(), generics, Some(generic_bounds), &self.get_context(), self.block_indent, + &ti.vis, ); self.push_rewrite(ti.span, rewrite); } @@ -656,6 +657,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let rewrite_associated = || { rewrite_associated_impl_type( ii.ident, + &ii.vis, defaultness, ty.as_ref(), generics, diff --git a/rustfmt-core/rustfmt-lib/tests/target/issue-4159.rs b/rustfmt-core/rustfmt-lib/tests/target/issue-4159.rs new file mode 100644 index 00000000000..52abb132cae --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/target/issue-4159.rs @@ -0,0 +1,18 @@ +extern "C" { + type A: Ord; + + type A<'a> + where + 'a: 'static,; + + type A + where + T: 'static,; + + type A = u8; + + type A<'a: 'static, T: Ord + 'static>: Eq + PartialEq + where + T: 'static + Copy, + = Vec; +} From 8d66e73531c2eea900ce6c8f0631673148f761ea Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Sat, 9 May 2020 16:01:42 -0700 Subject: [PATCH 13/59] fixup! Preserve and format type aliases in extern blocks --- rustfmt-core/rustfmt-lib/src/items.rs | 3 +++ rustfmt-core/rustfmt-lib/tests/target/issue-4159.rs | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/rustfmt-core/rustfmt-lib/src/items.rs b/rustfmt-core/rustfmt-lib/src/items.rs index 45c225fb028..130f2bce3d7 100644 --- a/rustfmt-core/rustfmt-lib/src/items.rs +++ b/rustfmt-core/rustfmt-lib/src/items.rs @@ -1935,6 +1935,9 @@ pub(crate) fn rewrite_type_alias( let lhs = format!("{}=", prefix); rewrite_assign_rhs(context, lhs, &**ty, shape).map(|s| s + ";") } else { + if !generics.where_clause.predicates.is_empty() { + prefix.push_str(&indent.to_string_with_newline(context.config)); + } Some(format!("{};", prefix)) } } diff --git a/rustfmt-core/rustfmt-lib/tests/target/issue-4159.rs b/rustfmt-core/rustfmt-lib/tests/target/issue-4159.rs index 52abb132cae..fed6095354a 100644 --- a/rustfmt-core/rustfmt-lib/tests/target/issue-4159.rs +++ b/rustfmt-core/rustfmt-lib/tests/target/issue-4159.rs @@ -3,11 +3,13 @@ extern "C" { type A<'a> where - 'a: 'static,; + 'a: 'static, + ; type A where - T: 'static,; + T: 'static, + ; type A = u8; From dc5fb24a73b29af0e1fb5e098f9785bb5662a621 Mon Sep 17 00:00:00 2001 From: hafiz <20735482+ayazhafiz@users.noreply.github.com> Date: Sun, 10 May 2020 06:52:59 -0500 Subject: [PATCH 14/59] Rename fn_args_layout config option to fn_params_layout (#4163) --- Configurations.md | 4 ++-- rustfmt-core/rustfmt-lib/src/config.rs | 6 +++--- rustfmt-core/rustfmt-lib/src/items.rs | 2 +- rustfmt-core/rustfmt-lib/tests/config/small_tabs.toml | 2 +- .../{fn_args_layout => fn_params_layout}/compressed.rs | 4 ++-- .../configs/{fn_args_layout => fn_params_layout}/tall.rs | 4 ++-- .../{fn_args_layout => fn_params_layout}/vertical.rs | 4 ++-- rustfmt-core/rustfmt-lib/tests/source/fn-custom-7.rs | 2 +- rustfmt-core/rustfmt-lib/tests/source/fn-custom.rs | 2 +- ...args_layout-vertical.rs => fn_params_layout-vertical.rs} | 2 +- .../{fn_args_layout => fn_params_layout}/compressed.rs | 4 ++-- .../configs/{fn_args_layout => fn_params_layout}/tall.rs | 4 ++-- .../{fn_args_layout => fn_params_layout}/vertical.rs | 4 ++-- rustfmt-core/rustfmt-lib/tests/target/fn-custom-7.rs | 2 +- rustfmt-core/rustfmt-lib/tests/target/fn-custom.rs | 2 +- ...args_layout-vertical.rs => fn_params_layout-vertical.rs} | 2 +- 16 files changed, 25 insertions(+), 25 deletions(-) rename rustfmt-core/rustfmt-lib/tests/source/configs/{fn_args_layout => fn_params_layout}/compressed.rs (86%) rename rustfmt-core/rustfmt-lib/tests/source/configs/{fn_args_layout => fn_params_layout}/tall.rs (87%) rename rustfmt-core/rustfmt-lib/tests/source/configs/{fn_args_layout => fn_params_layout}/vertical.rs (86%) rename rustfmt-core/rustfmt-lib/tests/source/{fn_args_layout-vertical.rs => fn_params_layout-vertical.rs} (95%) rename rustfmt-core/rustfmt-lib/tests/target/configs/{fn_args_layout => fn_params_layout}/compressed.rs (87%) rename rustfmt-core/rustfmt-lib/tests/target/configs/{fn_args_layout => fn_params_layout}/tall.rs (89%) rename rustfmt-core/rustfmt-lib/tests/target/configs/{fn_args_layout => fn_params_layout}/vertical.rs (90%) rename rustfmt-core/rustfmt-lib/tests/target/{fn_args_layout-vertical.rs => fn_params_layout-vertical.rs} (96%) diff --git a/Configurations.md b/Configurations.md index aea2673f567..e013c711c2c 100644 --- a/Configurations.md +++ b/Configurations.md @@ -637,9 +637,9 @@ trailing whitespaces. - **Possible values**: `true`, `false` - **Stable**: No (tracking issue: [#3392](https://github.com/rust-lang/rustfmt/issues/3392)) -## `fn_args_layout` +## `fn_params_layout` -Control the layout of arguments in a function +Control the layout of parameters in a function signature - **Default value**: `"Tall"` - **Possible values**: `"Compressed"`, `"Tall"`, `"Vertical"` diff --git a/rustfmt-core/rustfmt-lib/src/config.rs b/rustfmt-core/rustfmt-lib/src/config.rs index e479608841a..c321bea0686 100644 --- a/rustfmt-core/rustfmt-lib/src/config.rs +++ b/rustfmt-core/rustfmt-lib/src/config.rs @@ -108,8 +108,8 @@ create_config! { the same line with the pattern of arms"; 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"; + fn_params_layout: Density, Density::Tall, true, + "Control the layout of parameters in a function signature"; brace_style: BraceStyle, BraceStyle::SameLineWhere, false, "Brace style for items"; control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, false, "Brace style for control flow constructs"; @@ -552,7 +552,7 @@ struct_field_align_threshold = 0 enum_discrim_align_threshold = 0 match_arm_blocks = true force_multiline_blocks = false -fn_args_layout = "Tall" +fn_params_layout = "Tall" brace_style = "SameLineWhere" control_brace_style = "AlwaysSameLine" trailing_semicolon = true diff --git a/rustfmt-core/rustfmt-lib/src/items.rs b/rustfmt-core/rustfmt-lib/src/items.rs index 130f2bce3d7..2763d71b96a 100644 --- a/rustfmt-core/rustfmt-lib/src/items.rs +++ b/rustfmt-core/rustfmt-lib/src/items.rs @@ -2623,7 +2623,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/rustfmt-core/rustfmt-lib/tests/config/small_tabs.toml b/rustfmt-core/rustfmt-lib/tests/config/small_tabs.toml index c3cfd34317a..4c37100894f 100644 --- a/rustfmt-core/rustfmt-lib/tests/config/small_tabs.toml +++ b/rustfmt-core/rustfmt-lib/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/rustfmt-core/rustfmt-lib/tests/source/configs/fn_args_layout/compressed.rs b/rustfmt-core/rustfmt-lib/tests/source/configs/fn_params_layout/compressed.rs similarity index 86% rename from rustfmt-core/rustfmt-lib/tests/source/configs/fn_args_layout/compressed.rs rename to rustfmt-core/rustfmt-lib/tests/source/configs/fn_params_layout/compressed.rs index 66a371c259f..ee2a21a3ee6 100644 --- a/rustfmt-core/rustfmt-lib/tests/source/configs/fn_args_layout/compressed.rs +++ b/rustfmt-core/rustfmt-lib/tests/source/configs/fn_params_layout/compressed.rs @@ -1,5 +1,5 @@ -// rustfmt-fn_args_layout: Compressed -// Function arguments density +// rustfmt-fn_params_layout: Compressed +// Function parameter density trait Lorem { fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); diff --git a/rustfmt-core/rustfmt-lib/tests/source/configs/fn_args_layout/tall.rs b/rustfmt-core/rustfmt-lib/tests/source/configs/fn_params_layout/tall.rs similarity index 87% rename from rustfmt-core/rustfmt-lib/tests/source/configs/fn_args_layout/tall.rs rename to rustfmt-core/rustfmt-lib/tests/source/configs/fn_params_layout/tall.rs index f11e86fd313..9cf02df7d05 100644 --- a/rustfmt-core/rustfmt-lib/tests/source/configs/fn_args_layout/tall.rs +++ b/rustfmt-core/rustfmt-lib/tests/source/configs/fn_params_layout/tall.rs @@ -1,5 +1,5 @@ -// rustfmt-fn_args_layout: Tall -// Function arguments density +// rustfmt-fn_params_layout: Tall +// Function parameter density trait Lorem { fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); diff --git a/rustfmt-core/rustfmt-lib/tests/source/configs/fn_args_layout/vertical.rs b/rustfmt-core/rustfmt-lib/tests/source/configs/fn_params_layout/vertical.rs similarity index 86% rename from rustfmt-core/rustfmt-lib/tests/source/configs/fn_args_layout/vertical.rs rename to rustfmt-core/rustfmt-lib/tests/source/configs/fn_params_layout/vertical.rs index a23cc025225..8eca5c72a55 100644 --- a/rustfmt-core/rustfmt-lib/tests/source/configs/fn_args_layout/vertical.rs +++ b/rustfmt-core/rustfmt-lib/tests/source/configs/fn_params_layout/vertical.rs @@ -1,5 +1,5 @@ -// rustfmt-fn_args_layout: Vertical -// Function arguments density +// rustfmt-fn_params_layout: Vertical +// Function parameter density trait Lorem { fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); diff --git a/rustfmt-core/rustfmt-lib/tests/source/fn-custom-7.rs b/rustfmt-core/rustfmt-lib/tests/source/fn-custom-7.rs index d5330196bf7..3ecd8701727 100644 --- a/rustfmt-core/rustfmt-lib/tests/source/fn-custom-7.rs +++ b/rustfmt-core/rustfmt-lib/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/rustfmt-core/rustfmt-lib/tests/source/fn-custom.rs b/rustfmt-core/rustfmt-lib/tests/source/fn-custom.rs index 77ced4c5e0e..64ef0ecfaae 100644 --- a/rustfmt-core/rustfmt-lib/tests/source/fn-custom.rs +++ b/rustfmt-core/rustfmt-lib/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/rustfmt-core/rustfmt-lib/tests/source/fn_args_layout-vertical.rs b/rustfmt-core/rustfmt-lib/tests/source/fn_params_layout-vertical.rs similarity index 95% rename from rustfmt-core/rustfmt-lib/tests/source/fn_args_layout-vertical.rs rename to rustfmt-core/rustfmt-lib/tests/source/fn_params_layout-vertical.rs index 759bc83d015..fd6e3f0442e 100644 --- a/rustfmt-core/rustfmt-lib/tests/source/fn_args_layout-vertical.rs +++ b/rustfmt-core/rustfmt-lib/tests/source/fn_params_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/rustfmt-core/rustfmt-lib/tests/target/configs/fn_args_layout/compressed.rs b/rustfmt-core/rustfmt-lib/tests/target/configs/fn_params_layout/compressed.rs similarity index 87% rename from rustfmt-core/rustfmt-lib/tests/target/configs/fn_args_layout/compressed.rs rename to rustfmt-core/rustfmt-lib/tests/target/configs/fn_params_layout/compressed.rs index f189446e25d..6274b4431ac 100644 --- a/rustfmt-core/rustfmt-lib/tests/target/configs/fn_args_layout/compressed.rs +++ b/rustfmt-core/rustfmt-lib/tests/target/configs/fn_params_layout/compressed.rs @@ -1,5 +1,5 @@ -// rustfmt-fn_args_layout: Compressed -// Function arguments density +// rustfmt-fn_params_layout: Compressed +// Function parameter density trait Lorem { fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); diff --git a/rustfmt-core/rustfmt-lib/tests/target/configs/fn_args_layout/tall.rs b/rustfmt-core/rustfmt-lib/tests/target/configs/fn_params_layout/tall.rs similarity index 89% rename from rustfmt-core/rustfmt-lib/tests/target/configs/fn_args_layout/tall.rs rename to rustfmt-core/rustfmt-lib/tests/target/configs/fn_params_layout/tall.rs index 20f308973ac..c45cd4455b3 100644 --- a/rustfmt-core/rustfmt-lib/tests/target/configs/fn_args_layout/tall.rs +++ b/rustfmt-core/rustfmt-lib/tests/target/configs/fn_params_layout/tall.rs @@ -1,5 +1,5 @@ -// rustfmt-fn_args_layout: Tall -// Function arguments density +// rustfmt-fn_params_layout: Tall +// Function parameter density trait Lorem { fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); diff --git a/rustfmt-core/rustfmt-lib/tests/target/configs/fn_args_layout/vertical.rs b/rustfmt-core/rustfmt-lib/tests/target/configs/fn_params_layout/vertical.rs similarity index 90% rename from rustfmt-core/rustfmt-lib/tests/target/configs/fn_args_layout/vertical.rs rename to rustfmt-core/rustfmt-lib/tests/target/configs/fn_params_layout/vertical.rs index 6c695a75df9..ae98de097f3 100644 --- a/rustfmt-core/rustfmt-lib/tests/target/configs/fn_args_layout/vertical.rs +++ b/rustfmt-core/rustfmt-lib/tests/target/configs/fn_params_layout/vertical.rs @@ -1,5 +1,5 @@ -// rustfmt-fn_args_layout: Vertical -// Function arguments density +// rustfmt-fn_params_layout: Vertical +// Function parameter density trait Lorem { fn lorem( diff --git a/rustfmt-core/rustfmt-lib/tests/target/fn-custom-7.rs b/rustfmt-core/rustfmt-lib/tests/target/fn-custom-7.rs index 2c20ac5a752..f6a1a90c3fc 100644 --- a/rustfmt-core/rustfmt-lib/tests/target/fn-custom-7.rs +++ b/rustfmt-core/rustfmt-lib/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/rustfmt-core/rustfmt-lib/tests/target/fn-custom.rs b/rustfmt-core/rustfmt-lib/tests/target/fn-custom.rs index 2eb2a973d24..506d9de3437 100644 --- a/rustfmt-core/rustfmt-lib/tests/target/fn-custom.rs +++ b/rustfmt-core/rustfmt-lib/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/rustfmt-core/rustfmt-lib/tests/target/fn_args_layout-vertical.rs b/rustfmt-core/rustfmt-lib/tests/target/fn_params_layout-vertical.rs similarity index 96% rename from rustfmt-core/rustfmt-lib/tests/target/fn_args_layout-vertical.rs rename to rustfmt-core/rustfmt-lib/tests/target/fn_params_layout-vertical.rs index da0ac981d87..bfeca15c967 100644 --- a/rustfmt-core/rustfmt-lib/tests/target/fn_args_layout-vertical.rs +++ b/rustfmt-core/rustfmt-lib/tests/target/fn_params_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 { From e08643603bd4a51c894ebc53fb76809bc2ecbe9d Mon Sep 17 00:00:00 2001 From: hafiz <20735482+ayazhafiz@users.noreply.github.com> Date: Sun, 10 May 2020 06:54:46 -0500 Subject: [PATCH 15/59] Compare code block line indentation with config whitespace (#4166) Previously the indetation of a line was compared with the configured number of spaces per tab, which could cause lines that were formatted with hard tabs not to be recognized as indented ("\t".len() < " ".len()). Closes #4152 --- rustfmt-core/rustfmt-lib/src/lib.rs | 4 ++-- .../rustfmt-lib/tests/target/issue-4152.rs | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 rustfmt-core/rustfmt-lib/tests/target/issue-4152.rs diff --git a/rustfmt-core/rustfmt-lib/src/lib.rs b/rustfmt-core/rustfmt-lib/src/lib.rs index 4dc0981b6c6..29e2a7c360e 100644 --- a/rustfmt-core/rustfmt-lib/src/lib.rs +++ b/rustfmt-core/rustfmt-lib/src/lib.rs @@ -350,6 +350,7 @@ fn format_code_block(code_snippet: &str, config: &Config) -> Option Option config.tab_spaces() { + } else if line.len() > indent_str.len() { // Make sure that the line has leading whitespaces. - let indent_str = Indent::from_width(config, config.tab_spaces()).to_string(config); if line.starts_with(indent_str.as_ref()) { let offset = if config.hard_tabs() { 1 diff --git a/rustfmt-core/rustfmt-lib/tests/target/issue-4152.rs b/rustfmt-core/rustfmt-lib/tests/target/issue-4152.rs new file mode 100644 index 00000000000..80f9ff5e304 --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/target/issue-4152.rs @@ -0,0 +1,18 @@ +// rustfmt-hard_tabs: true + +macro_rules! bit { + ($bool:expr) => { + if $bool { + 1; + 1 + } else { + 0; + 0 + } + }; +} +macro_rules! add_one { + ($vec:expr) => {{ + $vec.push(1); + }}; +} From a98b1cddfdff7df6c522a2f43261a13104eae59b Mon Sep 17 00:00:00 2001 From: hafiz <20735482+ayazhafiz@users.noreply.github.com> Date: Sun, 10 May 2020 07:04:07 -0500 Subject: [PATCH 16/59] Exclude code block delimiters when wrapping comments (#4165) * Exclude code block delimiters when wrapping comments Closes #4158 * fixup! Exclude code block delimiters when wrapping comments --- rustfmt-core/rustfmt-lib/src/comment.rs | 11 +++++- .../rustfmt-lib/tests/source/issue-4158.rs | 30 ++++++++++++++++ .../rustfmt-lib/tests/target/issue-4158.rs | 34 +++++++++++++++++++ 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 rustfmt-core/rustfmt-lib/tests/source/issue-4158.rs create mode 100644 rustfmt-core/rustfmt-lib/tests/target/issue-4158.rs diff --git a/rustfmt-core/rustfmt-lib/src/comment.rs b/rustfmt-core/rustfmt-lib/src/comment.rs index c57288e58f6..0e98607c651 100644 --- a/rustfmt-core/rustfmt-lib/src/comment.rs +++ b/rustfmt-core/rustfmt-lib/src/comment.rs @@ -290,8 +290,9 @@ fn identify_comment( ) -> (bool, usize) { let mut first_group_ending = 0; let mut hbl = false; + let mut seen_cb_delimiters = 0; - for line in orig.lines() { + for (i, line) in orig.lines().enumerate() { let trimmed_line = line.trim_start(); if trimmed_line.is_empty() { hbl = true; @@ -299,6 +300,14 @@ fn identify_comment( } else if trimmed_line.starts_with(line_start) || comment_style(trimmed_line, false) == style { + if line.starts_with(&format!("{}```", line_start)) { + seen_cb_delimiters += 1; + if seen_cb_delimiters % 2 != 0 && i != 0 { + // Next line is the start of a new code block. Stop here to avoid wrapping + // the delimiter up when we format the comment group. + break; + } + } first_group_ending += compute_len(&orig[first_group_ending..], line); } else { break; diff --git a/rustfmt-core/rustfmt-lib/tests/source/issue-4158.rs b/rustfmt-core/rustfmt-lib/tests/source/issue-4158.rs new file mode 100644 index 00000000000..8c3221b2b37 --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/source/issue-4158.rs @@ -0,0 +1,30 @@ +// rustfmt-wrap_comments: true +// rustfmt-max_width: 50 + +// This is a long line that will be wrapped on the next line. +// This line will be wrapped with it. +// ``` +// this is code that won't +// even if it also is very very very very very very very very very very very very long +// ``` +// This is a second long line that will be wrapped on the next line. +// ``` +// this is code that won't +// ``` + +/// This is a long line that will be wrapped on the next line. +/// ``` +/// Should handle code blocks with no end +fn outer() { + //! This is a long line that will be wrapped on the next line. + //! ```rust + //! assert!(true); + //! ``` + fn inner() { + /* This is a long line that will be wrapped on the next line. + * ```rust + * assert!(true); + * ``` + */ + } +} diff --git a/rustfmt-core/rustfmt-lib/tests/target/issue-4158.rs b/rustfmt-core/rustfmt-lib/tests/target/issue-4158.rs new file mode 100644 index 00000000000..7e5e0ab6abd --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/target/issue-4158.rs @@ -0,0 +1,34 @@ +// rustfmt-wrap_comments: true +// rustfmt-max_width: 50 + +// This is a long line that will be wrapped on the +// next line. This line will be wrapped with it. +// ``` +// this is code that won't +// even if it also is very very very very very very very very very very very very long +// ``` +// This is a second long line that will be wrapped +// on the next line. +// ``` +// this is code that won't +// ``` + +/// This is a long line that will be wrapped on +/// the next line. +/// ``` +/// Should handle code blocks with no end +fn outer() { + //! This is a long line that will be wrapped + //! on the next line. + //! ```rust + //! assert!(true); + //! ``` + fn inner() { + /* This is a long line that will be + * wrapped on the next line. + * ```rust + * assert!(true); + * ``` + */ + } +} From 6af9fed4affd29fe022e505ee9422be8dffb5af1 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 10 May 2020 22:40:28 +0900 Subject: [PATCH 17/59] Create FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000000..6a9c0d003db --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: [topecongiro] From 04fdc7a3f1ef44a3fbcb03e044620ca25cfc677e Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Mon, 20 Apr 2020 21:47:09 -0500 Subject: [PATCH 18/59] feat: support configurability of leading pipe --- rustfmt-core/rustfmt-lib/src/config.rs | 3 +++ .../rustfmt-lib/src/config/options.rs | 11 +++++++++ rustfmt-core/rustfmt-lib/src/matches.rs | 24 +++++++++++++++---- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/rustfmt-core/rustfmt-lib/src/config.rs b/rustfmt-core/rustfmt-lib/src/config.rs index c321bea0686..51462290957 100644 --- a/rustfmt-core/rustfmt-lib/src/config.rs +++ b/rustfmt-core/rustfmt-lib/src/config.rs @@ -106,6 +106,8 @@ create_config! { "Align enum variants discrims, if their diffs fit within threshold"; match_arm_blocks: bool, true, false, "Wrap the body of arms in blocks when it does not fit on \ the same line with the pattern of arms"; + match_arm_leading_pipes: MatchArmLeadingPipe, MatchArmLeadingPipe::Never, true, + "Determines whether leading pipes are emitted on match arms"; force_multiline_blocks: bool, false, false, "Force multiline closure bodies and match arms to be wrapped in a block"; fn_params_layout: Density, Density::Tall, true, @@ -551,6 +553,7 @@ overflow_delimited_expr = false struct_field_align_threshold = 0 enum_discrim_align_threshold = 0 match_arm_blocks = true +match_arm_leading_pipes = "Never" force_multiline_blocks = false fn_params_layout = "Tall" brace_style = "SameLineWhere" diff --git a/rustfmt-core/rustfmt-lib/src/config/options.rs b/rustfmt-core/rustfmt-lib/src/config/options.rs index fb2c9d27aa1..f5592273ba3 100644 --- a/rustfmt-core/rustfmt-lib/src/config/options.rs +++ b/rustfmt-core/rustfmt-lib/src/config/options.rs @@ -374,3 +374,14 @@ impl From for rustc_span::edition::Edition { } } } + +/// Controls how rustfmt should handle leading pipes on match arms. +#[config_type] +pub enum MatchArmLeadingPipe { + /// Place leading pipes on all match arms + Always, + /// Never emit leading pipes on match arms + Never, + /// Maintain any existing leading pipes + KeepExisting, +} diff --git a/rustfmt-core/rustfmt-lib/src/matches.rs b/rustfmt-core/rustfmt-lib/src/matches.rs index c11c65aac89..0f3d835bcce 100644 --- a/rustfmt-core/rustfmt-lib/src/matches.rs +++ b/rustfmt-core/rustfmt-lib/src/matches.rs @@ -7,7 +7,7 @@ use rustc_span::{BytePos, Span}; use crate::comment::{combine_strs_with_missing_comments, rewrite_comment}; use crate::config::lists::*; -use crate::config::{Config, ControlBraceStyle, IndentStyle}; +use crate::config::{Config, ControlBraceStyle, IndentStyle, MatchArmLeadingPipe}; use crate::expr::{ format_expr, is_empty_block, is_simple_block, is_unsafe_block, prefer_next_line, rewrite_cond, ExprType, RhsTactics, @@ -55,7 +55,13 @@ impl<'a> Spanned for ArmWrapper<'a> { impl<'a> Rewrite for ArmWrapper<'a> { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - rewrite_match_arm(context, self.arm, shape, self.is_last) + rewrite_match_arm( + context, + self.arm, + shape, + self.is_last, + self.beginning_vert.is_some(), + ) } } @@ -215,6 +221,7 @@ fn rewrite_match_arm( arm: &ast::Arm, shape: Shape, is_last: bool, + has_leading_pipe: bool, ) -> Option { let (missing_span, attrs_str) = if !arm.attrs.is_empty() { if contains_skip(&arm.attrs) { @@ -232,9 +239,18 @@ fn rewrite_match_arm( (mk_sp(arm.span().lo(), arm.span().lo()), String::new()) }; + // Leading pipe offset + // 2 = `| ` + let (pipe_offset, pipe_str) = match context.config.match_arm_leading_pipes() { + MatchArmLeadingPipe::Never => (0, ""), + MatchArmLeadingPipe::KeepExisting if !has_leading_pipe => (0, ""), + MatchArmLeadingPipe::KeepExisting | MatchArmLeadingPipe::Always => (2, "| "), + }; + // Patterns // 5 = ` => {` - let pat_shape = shape.sub_width(5)?; + let pat_shape = shape.sub_width(5)?.offset_left(pipe_offset)?; + let pats_str = arm.pat.rewrite(context, pat_shape)?; // Guard @@ -251,7 +267,7 @@ fn rewrite_match_arm( let lhs_str = combine_strs_with_missing_comments( context, &attrs_str, - &format!("{}{}", pats_str, guard_str), + &format!("{}{}{}", pipe_str, pats_str, guard_str), missing_span, shape, false, From db9962ab8ff61ddc058cfe215226efb34258e10f Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Mon, 20 Apr 2020 21:47:40 -0500 Subject: [PATCH 19/59] tests: add tests for leading pipe config --- .../configs/match_arm_leading_pipes/always.rs | 27 ++++++++++++++++++ .../match_arm_leading_pipes/keep_existing.rs | 28 +++++++++++++++++++ .../configs/match_arm_leading_pipes/never.rs | 28 +++++++++++++++++++ .../configs/match_arm_leading_pipes/always.rs | 27 ++++++++++++++++++ .../match_arm_leading_pipes/keep_existing.rs | 27 ++++++++++++++++++ .../configs/match_arm_leading_pipes/never.rs | 27 ++++++++++++++++++ 6 files changed, 164 insertions(+) create mode 100644 rustfmt-core/rustfmt-lib/tests/source/configs/match_arm_leading_pipes/always.rs create mode 100644 rustfmt-core/rustfmt-lib/tests/source/configs/match_arm_leading_pipes/keep_existing.rs create mode 100644 rustfmt-core/rustfmt-lib/tests/source/configs/match_arm_leading_pipes/never.rs create mode 100644 rustfmt-core/rustfmt-lib/tests/target/configs/match_arm_leading_pipes/always.rs create mode 100644 rustfmt-core/rustfmt-lib/tests/target/configs/match_arm_leading_pipes/keep_existing.rs create mode 100644 rustfmt-core/rustfmt-lib/tests/target/configs/match_arm_leading_pipes/never.rs diff --git a/rustfmt-core/rustfmt-lib/tests/source/configs/match_arm_leading_pipes/always.rs b/rustfmt-core/rustfmt-lib/tests/source/configs/match_arm_leading_pipes/always.rs new file mode 100644 index 00000000000..162d812d8cf --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/source/configs/match_arm_leading_pipes/always.rs @@ -0,0 +1,27 @@ +// rustfmt-match_arm_leading_pipes: Always + +fn foo() { + match foo { + "foo" | "bar" => {} + "baz" + | "something relatively long" + | "something really really really realllllllllllllly long" => println!("x"), + "qux" => println!("y"), + _ => {} + } +} + +fn issue_3973() { + match foo { + "foo" | "bar" => {} + _ => {} + } +} + +fn bar() { + match baz { + "qux" => {} + "foo" | "bar" => {} + _ => {} + } +} diff --git a/rustfmt-core/rustfmt-lib/tests/source/configs/match_arm_leading_pipes/keep_existing.rs b/rustfmt-core/rustfmt-lib/tests/source/configs/match_arm_leading_pipes/keep_existing.rs new file mode 100644 index 00000000000..3980edb3dcd --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/source/configs/match_arm_leading_pipes/keep_existing.rs @@ -0,0 +1,28 @@ +// rustfmt-match_arm_leading_pipes: KeepExisting + +fn foo() { + match foo { + | "foo" | "bar" => {} + | "baz" + | "something relatively long" + | "something really really really realllllllllllllly long" => println!("x"), + | "qux" => println!("y"), + _ => {} + } +} + +fn issue_3973() { + match foo { + | "foo" + | "bar" => {} + _ => {} + } +} + +fn bar() { + match baz { + "qux" => { } + "foo" | "bar" => {} + _ => {} + } +} diff --git a/rustfmt-core/rustfmt-lib/tests/source/configs/match_arm_leading_pipes/never.rs b/rustfmt-core/rustfmt-lib/tests/source/configs/match_arm_leading_pipes/never.rs new file mode 100644 index 00000000000..8a68fe21407 --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/source/configs/match_arm_leading_pipes/never.rs @@ -0,0 +1,28 @@ +// rustfmt-match_arm_leading_pipes: Never + +fn foo() { + match foo { + | "foo" | "bar" => {} + | "baz" + | "something relatively long" + | "something really really really realllllllllllllly long" => println!("x"), + | "qux" => println!("y"), + _ => {} + } +} + +fn issue_3973() { + match foo { + | "foo" + | "bar" => {} + _ => {} + } +} + +fn bar() { + match baz { + "qux" => {} + "foo" | "bar" => {} + _ => {} + } +} diff --git a/rustfmt-core/rustfmt-lib/tests/target/configs/match_arm_leading_pipes/always.rs b/rustfmt-core/rustfmt-lib/tests/target/configs/match_arm_leading_pipes/always.rs new file mode 100644 index 00000000000..f2af81eac3c --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/target/configs/match_arm_leading_pipes/always.rs @@ -0,0 +1,27 @@ +// rustfmt-match_arm_leading_pipes: Always + +fn foo() { + match foo { + | "foo" | "bar" => {} + | "baz" + | "something relatively long" + | "something really really really realllllllllllllly long" => println!("x"), + | "qux" => println!("y"), + | _ => {} + } +} + +fn issue_3973() { + match foo { + | "foo" | "bar" => {} + | _ => {} + } +} + +fn bar() { + match baz { + | "qux" => {} + | "foo" | "bar" => {} + | _ => {} + } +} diff --git a/rustfmt-core/rustfmt-lib/tests/target/configs/match_arm_leading_pipes/keep_existing.rs b/rustfmt-core/rustfmt-lib/tests/target/configs/match_arm_leading_pipes/keep_existing.rs new file mode 100644 index 00000000000..4b76f845e0a --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/target/configs/match_arm_leading_pipes/keep_existing.rs @@ -0,0 +1,27 @@ +// rustfmt-match_arm_leading_pipes: KeepExisting + +fn foo() { + match foo { + | "foo" | "bar" => {} + | "baz" + | "something relatively long" + | "something really really really realllllllllllllly long" => println!("x"), + | "qux" => println!("y"), + _ => {} + } +} + +fn issue_3973() { + match foo { + | "foo" | "bar" => {} + _ => {} + } +} + +fn bar() { + match baz { + "qux" => {} + "foo" | "bar" => {} + _ => {} + } +} diff --git a/rustfmt-core/rustfmt-lib/tests/target/configs/match_arm_leading_pipes/never.rs b/rustfmt-core/rustfmt-lib/tests/target/configs/match_arm_leading_pipes/never.rs new file mode 100644 index 00000000000..345014e4b4e --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/target/configs/match_arm_leading_pipes/never.rs @@ -0,0 +1,27 @@ +// rustfmt-match_arm_leading_pipes: Never + +fn foo() { + match foo { + "foo" | "bar" => {} + "baz" + | "something relatively long" + | "something really really really realllllllllllllly long" => println!("x"), + "qux" => println!("y"), + _ => {} + } +} + +fn issue_3973() { + match foo { + "foo" | "bar" => {} + _ => {} + } +} + +fn bar() { + match baz { + "qux" => {} + "foo" | "bar" => {} + _ => {} + } +} From 8ef90d15322cfe591a9b4c08bc6bb254f6436b57 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Mon, 20 Apr 2020 21:48:22 -0500 Subject: [PATCH 20/59] docs: add config info for match_arm_leading_pipes --- Configurations.md | 82 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/Configurations.md b/Configurations.md index e013c711c2c..730326c2d55 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1504,6 +1504,88 @@ fn main() { See also: [`match_block_trailing_comma`](#match_block_trailing_comma). +## `match_arm_leading_pipes` + +Controls whether to include a leading pipe on match arms + +- **Default value**: `Never` +- **Possible values**: `Always`, `Never`, `KeepExisting` +- **Stable**: Yes + +#### `Never` (default): +```rust +// Leading pipes are from this: +// fn foo() { +// match foo { +// | "foo" | "bar" => {} +// | "baz" +// | "something relatively long" +// | "something really really really realllllllllllllly long" => println!("x"), +// | "qux" => println!("y"), +// _ => {} +// } +// } + +// Are removed: +fn foo() { + match foo { + "foo" | "bar" => {} + "baz" + | "something relatively long" + | "something really really really realllllllllllllly long" => println!("x"), + "qux" => println!("y"), + _ => {} + } +} +``` + +#### `Always`: +```rust +// Leading pipes are emitted on all arms of this: +// fn foo() { +// match foo { +// "foo" | "bar" => {} +// "baz" +// | "something relatively long" +// | "something really really really realllllllllllllly long" => println!("x"), +// "qux" => println!("y"), +// _ => {} +// } +// } + +// Becomes: +fn foo() { + match foo { + | "foo" | "bar" => {} + | "baz" + | "something relatively long" + | "something really really really realllllllllllllly long" => println!("x"), + | "qux" => println!("y"), + | _ => {} + } +} +``` + +#### `KeepExisting`: +```rust +fn foo() { + match foo { + | "foo" | "bar" => {} + | "baz" + | "something relatively long" + | "something really really really realllllllllllllly long" => println!("x"), + | "qux" => println!("y"), + _ => {} + } + + match baz { + "qux" => {} + "foo" | "bar" => {} + _ => {} + } +} +``` + ## `match_block_trailing_comma` Put a trailing comma after a block based match arm (non-block arms are not affected) From a6509fe70edd118bafe84b7b2ba9fe0bee4f0fc2 Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Sun, 10 May 2020 10:06:23 -0700 Subject: [PATCH 21/59] fixup! Preserve and format type aliases in extern blocks --- rustfmt-core/rustfmt-lib/src/items.rs | 107 ++++++------------ .../rustfmt-lib/tests/target/issue-4159.rs | 6 +- 2 files changed, 36 insertions(+), 77 deletions(-) diff --git a/rustfmt-core/rustfmt-lib/src/items.rs b/rustfmt-core/rustfmt-lib/src/items.rs index 2763d71b96a..1e39272133f 100644 --- a/rustfmt-core/rustfmt-lib/src/items.rs +++ b/rustfmt-core/rustfmt-lib/src/items.rs @@ -1556,22 +1556,23 @@ fn format_tuple_struct( Some(result) } -fn rewrite_type_prefix( +fn rewrite_type( context: &RewriteContext<'_>, indent: Indent, - prefix: &str, ident: ast::Ident, + vis: &ast::Visibility, generics: &ast::Generics, generic_bounds_opt: Option<&ast::GenericBounds>, + rhs: Option<&R>, ) -> Option { let mut result = String::with_capacity(128); - result.push_str(prefix); + result.push_str(&format!("{}type ", format_visibility(context, vis))); let ident_str = rewrite_ident(context, ident); - // 2 = `= ` if generics.params.is_empty() { result.push_str(ident_str) } else { + // 2 = `= ` let g_shape = Shape::indented(indent, context.config) .offset_left(result.len())? .sub_width(2)?; @@ -1579,21 +1580,20 @@ fn rewrite_type_prefix( result.push_str(&generics_str); } - let type_bounds_str = if let Some(bounds) = generic_bounds_opt { - if bounds.is_empty() { - String::new() - } else { + if let Some(bounds) = generic_bounds_opt { + if !bounds.is_empty() { // 2 = `: ` let shape = Shape::indented(indent, context.config).offset_left(result.len() + 2)?; - bounds.rewrite(context, shape).map(|s| format!(": {}", s))? + let type_bounds = bounds.rewrite(context, shape).map(|s| format!(": {}", s))?; + result.push_str(&type_bounds); } - } else { - String::new() - }; - result.push_str(&type_bounds_str); + } let where_budget = context.budget(last_line_width(&result)); - let option = WhereClauseOption::snuggled(&result); + let mut option = WhereClauseOption::snuggled(&result); + if rhs.is_none() { + option.suppress_comma(); + } let where_clause_str = rewrite_where_clause( context, &generics.where_clause, @@ -1607,40 +1607,22 @@ fn rewrite_type_prefix( )?; result.push_str(&where_clause_str); - Some(result) -} - -fn rewrite_type_item( - context: &RewriteContext<'_>, - indent: Indent, - prefix: &str, - suffix: &str, - ident: ast::Ident, - rhs: &R, - generics: &ast::Generics, - generic_bounds_opt: Option<&ast::GenericBounds>, - vis: &ast::Visibility, -) -> Option { - let mut result = String::with_capacity(128); - result.push_str(&rewrite_type_prefix( - context, - indent, - &format!("{}{} ", format_visibility(context, vis), prefix), - ident, - generics, - generic_bounds_opt, - )?); + if let Some(ty) = rhs { + // If there's a where clause, add a newline before the assignment. Otherwise just add a + // space. + if !generics.where_clause.predicates.is_empty() { + result.push_str(&indent.to_string_with_newline(context.config)); + } else { + result.push(' '); + } + let lhs = format!("{}=", result); - if generics.where_clause.predicates.is_empty() { - result.push_str(suffix); + // 1 = `;` + let shape = Shape::indented(indent, context.config).sub_width(1)?; + rewrite_assign_rhs(context, lhs, &*ty, shape).map(|s| s + ";") } else { - result.push_str(&indent.to_string_with_newline(context.config)); - result.push_str(suffix.trim_start()); + Some(format!("{};", result)) } - - // 1 = ";" - let rhs_shape = Shape::indented(indent, context.config).sub_width(1)?; - rewrite_assign_rhs(context, result, rhs, rhs_shape).map(|s| s + ";") } pub(crate) fn rewrite_opaque_type( @@ -1652,16 +1634,14 @@ pub(crate) fn rewrite_opaque_type( vis: &ast::Visibility, ) -> Option { let opaque_type_bounds = OpaqueTypeBounds { generic_bounds }; - rewrite_type_item( + rewrite_type( context, indent, - "type", - " =", ident, - &opaque_type_bounds, + vis, generics, Some(generic_bounds), - vis, + Some(&opaque_type_bounds), ) } @@ -1912,34 +1892,15 @@ pub(crate) fn rewrite_type_alias( indent: Indent, vis: &ast::Visibility, ) -> Option { - let mut prefix = rewrite_type_prefix( + rewrite_type( context, indent, - &format!("{}type ", format_visibility(context, vis)), ident, + vis, generics, generic_bounds_opt, - )?; - - if let Some(ty) = ty_opt { - // 1 = `;` - let shape = Shape::indented(indent, context.config).sub_width(1)?; - - // If there's a where clause, add a newline before the assignment. Otherwise just add a - // space. - if !generics.where_clause.predicates.is_empty() { - prefix.push_str(&indent.to_string_with_newline(context.config)); - } else { - prefix.push(' '); - } - let lhs = format!("{}=", prefix); - rewrite_assign_rhs(context, lhs, &**ty, shape).map(|s| s + ";") - } else { - if !generics.where_clause.predicates.is_empty() { - prefix.push_str(&indent.to_string_with_newline(context.config)); - } - Some(format!("{};", prefix)) - } + ty_opt, + ) } struct OpaqueType<'a> { diff --git a/rustfmt-core/rustfmt-lib/tests/target/issue-4159.rs b/rustfmt-core/rustfmt-lib/tests/target/issue-4159.rs index fed6095354a..2f8cf20da2c 100644 --- a/rustfmt-core/rustfmt-lib/tests/target/issue-4159.rs +++ b/rustfmt-core/rustfmt-lib/tests/target/issue-4159.rs @@ -3,13 +3,11 @@ extern "C" { type A<'a> where - 'a: 'static, - ; + 'a: 'static; type A where - T: 'static, - ; + T: 'static; type A = u8; From e6d5aea21e26cb9e1f978cdf8fdf2e289815244d Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Sun, 10 May 2020 10:11:36 -0700 Subject: [PATCH 22/59] fixup! Preserve and format type aliases in extern blocks --- rustfmt-core/rustfmt-lib/src/items.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustfmt-core/rustfmt-lib/src/items.rs b/rustfmt-core/rustfmt-lib/src/items.rs index 1e39272133f..197bffc750d 100644 --- a/rustfmt-core/rustfmt-lib/src/items.rs +++ b/rustfmt-core/rustfmt-lib/src/items.rs @@ -3103,7 +3103,7 @@ impl Rewrite for ast::ForeignItem { // FIXME: this may be a faulty span from libsyntax. let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1)); - let item_str: String = match self.kind { + let item_str = match self.kind { ast::ForeignItemKind::Fn(_, ref fn_sig, ref generics, _) => rewrite_fn_base( context, shape.indent, From a5232a23ff50f1dd880b6fde4f08923410f31af8 Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Sun, 10 May 2020 13:29:41 -0700 Subject: [PATCH 23/59] Properly align comments in unicode lines For an end user, the number of characters in a string is most likely interpreted as the number of [grapheme cluster](http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries)s in the string, which may be different than either the number of unicode codepoints or bytes. Use the number of graphemes to determine list comment alignment rather than the byte length of the line. Closes #4151 --- rustfmt-core/rustfmt-lib/src/lists.rs | 15 ++++++++++----- .../rustfmt-lib/tests/target/issue-4151.rs | 8 ++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 rustfmt-core/rustfmt-lib/tests/target/issue-4151.rs diff --git a/rustfmt-core/rustfmt-lib/src/lists.rs b/rustfmt-core/rustfmt-lib/src/lists.rs index 6546deb5d10..f67908a3b8c 100644 --- a/rustfmt-core/rustfmt-lib/src/lists.rs +++ b/rustfmt-core/rustfmt-lib/src/lists.rs @@ -4,6 +4,7 @@ use std::cmp; use std::iter::Peekable; use rustc_span::BytePos; +use unicode_segmentation::UnicodeSegmentation; use crate::comment::{find_comment_end, rewrite_comment, FindUncommented}; use crate::config::lists::*; @@ -464,8 +465,10 @@ where if !starts_with_newline(comment) { if formatting.align_comments { - let mut comment_alignment = - post_comment_alignment(item_max_width, inner_item.len()); + let mut comment_alignment = post_comment_alignment( + item_max_width, + UnicodeSegmentation::graphemes(inner_item.as_str(), true).count(), + ); if first_line_width(&formatted_comment) + last_line_width(&result) + comment_alignment @@ -474,8 +477,10 @@ 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()); + comment_alignment = post_comment_alignment( + item_max_width, + UnicodeSegmentation::graphemes(inner_item.as_str(), true).count(), + ); } for _ in 0..=comment_alignment { result.push(' '); @@ -533,7 +538,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 = UnicodeSegmentation::graphemes(item.inner_as_ref(), true).count(); if !first && (item.is_different_group() || item.post_comment.is_none() diff --git a/rustfmt-core/rustfmt-lib/tests/target/issue-4151.rs b/rustfmt-core/rustfmt-lib/tests/target/issue-4151.rs new file mode 100644 index 00000000000..e08ed6b2709 --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/target/issue-4151.rs @@ -0,0 +1,8 @@ +fn main() { + let mappings = [ + ("gamma", 'ɡ'), // comment 1 + ("sqrt", '√'), // comment 2 + ("a", 'a'), // comment 3 + ("eye", 'ಠ'), // comment 4 + ]; +} From e81d184d6ec2848c6e9cfeba626eaec1f83b657e Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 11 May 2020 09:50:41 +0900 Subject: [PATCH 24/59] Remove legacy-rustfmt.toml (#4169) --- legacy-rustfmt.toml | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 legacy-rustfmt.toml diff --git a/legacy-rustfmt.toml b/legacy-rustfmt.toml deleted file mode 100644 index f976fa68e4c..00000000000 --- a/legacy-rustfmt.toml +++ /dev/null @@ -1,2 +0,0 @@ -indent_style = "Visual" -combine_control_expr = false From e7af9c18aa0581a150f401646369d9682ead5dea Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Mon, 11 May 2020 15:11:25 -0700 Subject: [PATCH 25/59] Remove spaces added by comment opener when creating itemized block I'm not sure there's a better way to do this without a larger refactor of this method. Closes #4104 --- rustfmt-core/rustfmt-lib/src/comment.rs | 3 +++ rustfmt-core/rustfmt-lib/tests/target/issue-4104.rs | 7 +++++++ 2 files changed, 10 insertions(+) create mode 100644 rustfmt-core/rustfmt-lib/tests/target/issue-4104.rs diff --git a/rustfmt-core/rustfmt-lib/src/comment.rs b/rustfmt-core/rustfmt-lib/src/comment.rs index 0e98607c651..f24b9568ab1 100644 --- a/rustfmt-core/rustfmt-lib/src/comment.rs +++ b/rustfmt-core/rustfmt-lib/src/comment.rs @@ -704,6 +704,9 @@ impl<'a> CommentRewrite<'a> { } else if self.fmt.config.wrap_comments() && ItemizedBlock::is_itemized_line(&line) { let ib = ItemizedBlock::new(&line); self.item_block = Some(ib); + if self.result.ends_with(' ') { + self.result.pop(); + } return false; } diff --git a/rustfmt-core/rustfmt-lib/tests/target/issue-4104.rs b/rustfmt-core/rustfmt-lib/tests/target/issue-4104.rs new file mode 100644 index 00000000000..0e498536729 --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/target/issue-4104.rs @@ -0,0 +1,7 @@ +// rustfmt-wrap_comments: true +// rustfmt-normalize_comments: true + +/// +/// - item 1 + +fn main() {} From 02e740da08ef61d2df2ed074052e11bd2114b306 Mon Sep 17 00:00:00 2001 From: hafiz <20735482+ayazhafiz@users.noreply.github.com> Date: Sat, 16 May 2020 01:21:55 -0500 Subject: [PATCH 26/59] Exclude where kw from comment following fn return type (#4175) rustfmt tries to preserve the comment between a fn return type and the start of the fn body if there are no where clauses following the return type. However, even if there are no where clauses present, the "where" keyword may be. To elide the "where" keyword in this context, just get the comment snippet starting after the where clause span, which always includes the "where" keyword if present. Closes #4001 --- rustfmt-core/rustfmt-lib/src/items.rs | 6 ++++-- rustfmt-core/rustfmt-lib/tests/source/issue-4001.rs | 3 +++ rustfmt-core/rustfmt-lib/tests/target/issue-4001.rs | 3 +++ 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 rustfmt-core/rustfmt-lib/tests/source/issue-4001.rs create mode 100644 rustfmt-core/rustfmt-lib/tests/target/issue-4001.rs diff --git a/rustfmt-core/rustfmt-lib/src/items.rs b/rustfmt-core/rustfmt-lib/src/items.rs index 197bffc750d..3750fa5766e 100644 --- a/rustfmt-core/rustfmt-lib/src/items.rs +++ b/rustfmt-core/rustfmt-lib/src/items.rs @@ -2403,9 +2403,11 @@ fn rewrite_fn_base( result.push_str(&ret_str); } - // Comment between return type and the end of the decl. - let snippet_lo = fd.output.span().hi(); if where_clause.predicates.is_empty() { + // Comment between return type and the end of the decl. + // Even if there are no predicates in the where clause, the "where" kw may be present, + // so start the snippet after it. + let snippet_lo = where_clause.span.hi(); let snippet_hi = span.hi(); let snippet = context.snippet(mk_sp(snippet_lo, snippet_hi)); // Try to preserve the layout of the original snippet. diff --git a/rustfmt-core/rustfmt-lib/tests/source/issue-4001.rs b/rustfmt-core/rustfmt-lib/tests/source/issue-4001.rs new file mode 100644 index 00000000000..bf2fb0cddee --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/source/issue-4001.rs @@ -0,0 +1,3 @@ +fn unit() -> () where /* comment */ { + () +} diff --git a/rustfmt-core/rustfmt-lib/tests/target/issue-4001.rs b/rustfmt-core/rustfmt-lib/tests/target/issue-4001.rs new file mode 100644 index 00000000000..6c1f204eecf --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/target/issue-4001.rs @@ -0,0 +1,3 @@ +fn unit() -> () /* comment */ { + () +} From 2ade08875a4eefe80998424aa25fb0099c55d279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 16 May 2020 22:20:51 +0200 Subject: [PATCH 27/59] Stabilize match_block_trailing_comma. (#4145) Servo has used this since forever, and it'd be useful to be able to use rustfmt stable there so that we can use the same rustfmt version in both Firefox and Servo. Feel free to close this if there's any reason it shouldn't be done. Closes #3380 --- Configurations.md | 2 +- rustfmt-core/rustfmt-lib/src/config.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Configurations.md b/Configurations.md index 730326c2d55..2cfc25fcc16 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1592,7 +1592,7 @@ Put a trailing comma after a block based match arm (non-block arms are not affec - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: [#3380](https://github.com/rust-lang/rustfmt/issues/3380)) +- **Stable**: Yes #### `false` (default): diff --git a/rustfmt-core/rustfmt-lib/src/config.rs b/rustfmt-core/rustfmt-lib/src/config.rs index 51462290957..b02fb4bd0b9 100644 --- a/rustfmt-core/rustfmt-lib/src/config.rs +++ b/rustfmt-core/rustfmt-lib/src/config.rs @@ -119,7 +119,7 @@ create_config! { "Add trailing semicolon after break, continue and return"; trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, false, "How to handle trailing commas for lists"; - match_block_trailing_comma: bool, false, false, + match_block_trailing_comma: bool, false, true, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; blank_lines_upper_bound: usize, 1, false, "Maximum number of blank lines which can be put between items"; From 1c06692f908112dd006edcc406b1f82fc295cd14 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 20 May 2020 14:32:19 +0900 Subject: [PATCH 28/59] Update rustc-ap crates to 659.0.0 (#4188) --- .github/workflows/linux.yml | 1 + .github/workflows/mac.yml | 4 + .github/workflows/windows.yml | 4 + .travis.yml | 2 + Cargo.lock | 177 ++++++++++-------- appveyor.yml | 2 + ci/integration.sh | 4 + rustfmt-core/rustfmt-lib/Cargo.toml | 16 +- rustfmt-core/rustfmt-lib/src/chains.rs | 8 +- rustfmt-core/rustfmt-lib/src/imports.rs | 8 +- rustfmt-core/rustfmt-lib/src/items.rs | 26 +-- rustfmt-core/rustfmt-lib/src/lib.rs | 3 +- rustfmt-core/rustfmt-lib/src/macros.rs | 19 +- rustfmt-core/rustfmt-lib/src/modules.rs | 6 +- .../rustfmt-lib/src/syntux/session.rs | 7 +- rustfmt-core/rustfmt-lib/src/utils.rs | 4 +- rustfmt-core/rustfmt-lib/src/visitor.rs | 6 +- 17 files changed, 170 insertions(+), 127 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 33894dd0c87..6074c9c76b5 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -24,6 +24,7 @@ jobs: env: CFG_RELEASE_CHANNEL: ${{ matrix.cfg-release-channel }} + CFG_RELEASE: ${{ matrix.cfg-release-channel }} steps: - name: checkout diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index 0d3c733a0fa..183d5dc7bc7 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -15,6 +15,10 @@ jobs: ] channel: [ nightly ] + env: + CFG_RELEASE_CHANNEL: nightly + CFG_RELEASE: nightly + steps: - name: checkout uses: actions/checkout@v2 diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 3385f4463be..dcb80852611 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -25,6 +25,10 @@ jobs: target: i686-pc-windows-gnu mingw-7z-path: mingw + env: + CFG_RELEASE_CHANNEL: nightly + CFG_RELEASE: nightly + steps: # The Windows runners have autocrlf enabled by default # which causes failures for some of rustfmt's line-ending sensitive tests diff --git a/.travis.yml b/.travis.yml index 05c7e4306ef..7f92a175f00 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,6 +45,8 @@ matrix: script: - | + export CFG_RELEASE_CHANNEL=nightly + export CFG_RELEASE=nightly if [ -z ${INTEGRATION} ]; then cargo build && cargo test && cargo test -- --ignored && cargo test --manifest-path rustfmt-core/Cargo.toml && cargo test --manifest-path rustfmt-core/Cargo.toml -- --ignored else diff --git a/Cargo.lock b/Cargo.lock index 4ea282147e0..4740588c3d2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,9 +29,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.28" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9a60d744a80c30fcb657dfe2c1b22bcb3e814c1a1e3674f32bf5820b570fbff" +checksum = "85bb70cc08ec97ca5450e6eba421deeea5f172c0fc61f78b5357b2a8e8be195f" [[package]] name = "arrayref" @@ -108,9 +108,9 @@ dependencies = [ [[package]] name = "bstr" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2889e6d50f394968c8bf4240dc3f2a7eb4680844d27308f798229ac9d4725f41" +checksum = "31accafdb70df7871592c058eca3985b71104e15ac32f64706022c58867da931" dependencies = [ "memchr", ] @@ -148,6 +148,12 @@ dependencies = [ "serde_json", ] +[[package]] +name = "cc" +version = "1.0.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "404b1fe4f65288577753b17e3b36a04596ee784493ec249bf81c7f2d2acd751c" + [[package]] name = "cfg-if" version = "0.1.10" @@ -156,9 +162,9 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "clap" -version = "2.33.0" +version = "2.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" +checksum = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129" dependencies = [ "ansi_term", "atty", @@ -184,16 +190,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" -[[package]] -name = "crossbeam-channel" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061" -dependencies = [ - "crossbeam-utils 0.7.2", - "maybe-uninit", -] - [[package]] name = "crossbeam-deque" version = "0.7.3" @@ -301,9 +297,9 @@ checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" [[package]] name = "ena" -version = "0.13.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8944dc8fa28ce4a38f778bd46bf7d923fe73eed5a439398507246c8e017e6f36" +checksum = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3" dependencies = [ "log", ] @@ -329,9 +325,9 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "fnv" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "generic-array" @@ -404,11 +400,10 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddf60d063dbe6b75388eec66cfc07781167ae3d34a09e0c433e6c5de0511f7fb" +checksum = "128b9e89d15a3faa642ee164c998fd4fae3d89d054463cddb2c25a7baad3a352" dependencies = [ - "crossbeam-channel", "crossbeam-utils 0.7.2", "globset", "lazy_static", @@ -462,9 +457,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.69" +version = "0.2.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005" +checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f" [[package]] name = "lock_api" @@ -648,6 +643,15 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "psm" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "659ecfea2142a458893bb7673134bad50b752fea932349c213d6a23874ce3aa7" +dependencies = [ + "cc", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -656,9 +660,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c1f4b0efa5fc5e8ceb705136bfee52cfdb6a4e3509f770b478cd6ed434232a7" +checksum = "42934bc9c8ab0d3b273a16d8551c8f0fcff46be73276ca083ec2414c15c4ba5e" dependencies = [ "proc-macro2", ] @@ -712,9 +716,9 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "656.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb6df19dd0afdfda2ff7e1dc33c23ac5e77be2298dfce76b0be90df852fde281" +checksum = "fdaf0295fc40b10ec1091aad1a1760b4bb3b4e7c4f77d543d1a2e9d50a01e6b1" dependencies = [ "rustc-ap-rustc_data_structures", "smallvec 1.4.0", @@ -722,15 +726,15 @@ dependencies = [ [[package]] name = "rustc-ap-graphviz" -version = "656.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7771196b6eb99a166cf1dd8deb974b492fdf96e090d5a55db6cb5cf9f517afa" +checksum = "8028e8cdb4eb71810d0c22a5a5e1e3106c81123be63ce7f044b6d4ac100d8941" [[package]] name = "rustc-ap-rustc_ast" -version = "656.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edc1cfea59f901244ab488cfd4615da786208e5bd75d782abdbf5c94eccb6280" +checksum = "16e9e502bb3a5568433db1cf2fb1f1e1074934636069cf744ad7c77b58e1428e" dependencies = [ "log", "rustc-ap-rustc_data_structures", @@ -745,9 +749,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_ast_passes" -version = "656.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe14bcea3dd2a44f89e2d5ca453838e8d71ebaaede2c265eaed3fa044ce7358e" +checksum = "faf35ffecab28f97f7ac01cf6a13afaca6408529d15eb95f317a43b2ffb88933" dependencies = [ "itertools", "log", @@ -764,9 +768,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_ast_pretty" -version = "656.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c4ea460aa09e592f89ddab2efcfde050bd963bf02740347293294a40c1c757" +checksum = "3684ed43dc552f1e030e3f7a5a300a7a834bdda4e9e00ab80284be4220d8c603" dependencies = [ "log", "rustc-ap-rustc_ast", @@ -775,9 +779,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_attr" -version = "656.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0a2f931847e5967f69622bc9ffd47d4d4ce5444f5165a036c2eda0000ff4eeb" +checksum = "31b413927daa666983b3b49227f9ac218aa29254546abdb585f20cd71c391870" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_ast_pretty", @@ -788,13 +792,14 @@ dependencies = [ "rustc-ap-rustc_session", "rustc-ap-rustc_span", "rustc-ap-serialize", + "version_check", ] [[package]] name = "rustc-ap-rustc_data_structures" -version = "656.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e105049018a06b05bcab026d751b5ccfa320cb6b078d1aaf2884121dbc939df3" +checksum = "4b1c6069e5c522657f1c6f5ab33074e097092f48e804cc896d337e319aacbd60" dependencies = [ "bitflags", "cfg-if", @@ -815,14 +820,15 @@ dependencies = [ "rustc-rayon-core", "smallvec 1.4.0", "stable_deref_trait", + "stacker", "winapi", ] [[package]] name = "rustc-ap-rustc_errors" -version = "656.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3fb69cb302869dd8398a268c4dae19cfcaf39eaeb121374237d393232ab9ca8" +checksum = "0c374e89b3c9714869ef86076942155383804ba6778c26be2169d324563c31f9" dependencies = [ "annotate-snippets", "atty", @@ -838,9 +844,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_expand" -version = "656.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25d47c4dac84f583e36c6fabb60f7cbf12fae90aa77d45593f71f24b13b006d3" +checksum = "259d2a7aa7a12f3c99a4ce4123643ec065f1a26f8e89be1f9bedd9757ea53fdc" dependencies = [ "log", "rustc-ap-rustc_ast", @@ -860,9 +866,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_feature" -version = "656.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298f0c625a922d4675b91db3fac7d3b587849667a166c19eee2596e7edef9712" +checksum = "c0296fbc29b629d5ae2ebee1bbf0407bb22de04d26d87216c20899b79579ccb3" dependencies = [ "lazy_static", "rustc-ap-rustc_data_structures", @@ -871,15 +877,15 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_fs_util" -version = "656.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16f794f99d7a115ee9d5e73dada35d9cb553b0c6c34b3549f38960c9c301c62" +checksum = "34734f6cc681399630acd836a14207c6b5b9671a290cc7cad0354b0a4d71b3c9" [[package]] name = "rustc-ap-rustc_index" -version = "656.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59edea7fb099ca9589268aa8676b741f43db5c6f1bc1ced231db9d56e2aa9f94" +checksum = "d1e4508753d71d3523209c2ca5086db15a1413e71ebf17ad5412bb7ced5e44c2" dependencies = [ "rustc-ap-serialize", "smallvec 1.4.0", @@ -887,18 +893,18 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_lexer" -version = "656.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cbba98ec46e96a4663197dfa8c0378752de2006e314e5400c0ca74929d6692f" +checksum = "42b9fcd8407e322908a721262fbc0b35b5f3c35bb173a26dd1e0070bde336e33" dependencies = [ "unicode-xid", ] [[package]] name = "rustc-ap-rustc_macros" -version = "656.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f36ca24a130773044800e6806bf890365afb6175df8ab32efa59c577a11d4e" +checksum = "3d104115a689367d2e0bcd99f37e0ebd6b9c8c78bab0d9cbea5bae86323601b5" dependencies = [ "proc-macro2", "quote", @@ -908,9 +914,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_parse" -version = "656.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7ec08a2f8e98799a668e24578cb6e1b37ddca25132badd4b07ebb2cb6412b90" +checksum = "afaaab91853fc5a3916785ccae727a4433359d9787c260d42b96a2265fe5b287" dependencies = [ "bitflags", "log", @@ -927,9 +933,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_session" -version = "656.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1661cc89ec2e1992d686955aa24fa358ee5af11fdd91ecacb63575ae33c0c6b4" +checksum = "86e756a57ce6ce1b868e35e64a7e10ab28d49ece80d7c661b07aff5afc6e5d2d" dependencies = [ "getopts", "log", @@ -947,9 +953,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_span" -version = "656.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2afe35ea88a8f61198ff08f627fa3c5ef925e8d4ba23e678d8ab07d76b2999bb" +checksum = "21031c3396ee452f4c6e994b67513a633055c57c86d00336afd9d63149518f34" dependencies = [ "cfg-if", "log", @@ -966,9 +972,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_target" -version = "656.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00835074c37fc7cb377477c24dc8ca3cbaab7e3451925f8844e1a13eea5ec8cc" +checksum = "ff21badfbead5b0050391eaad8840f2e4fcb03b6b0fc6006f447443529e9ae6e" dependencies = [ "bitflags", "log", @@ -981,9 +987,9 @@ dependencies = [ [[package]] name = "rustc-ap-serialize" -version = "656.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b2ca2e47af678242e35e38518a64b97bc61b83b6e833c3ae734400f836679a6" +checksum = "768b5a305669d934522712bc13502962edfde5128ea63b9e7db4000410be1dc6" dependencies = [ "indexmap", "smallvec 1.4.0", @@ -1143,18 +1149,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.106" +version = "1.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399" +checksum = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.106" +version = "1.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c" +checksum = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984" dependencies = [ "proc-macro2", "quote", @@ -1163,9 +1169,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.52" +version = "1.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7894c8ed05b7a3a279aeb79025fdec1d3158080b75b98a08faf2806bb799edd" +checksum = "993948e75b189211a9b31a7528f950c6adc21f9720b6438ff80a7fa2f864cea2" dependencies = [ "itoa", "ryu", @@ -1205,6 +1211,19 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" +[[package]] +name = "stacker" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72dd941b456e1c006d6b9f27c526d5b69281288aeea8cba82c19d3843d8ccdd2" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "winapi", +] + [[package]] name = "strsim" version = "0.8.0" @@ -1237,9 +1256,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.18" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "410a7488c0a728c7ceb4ad59b9567eb4053d02e8cc7f5c0e0eeeb39518369213" +checksum = "4696caa4048ac7ce2bcd2e484b3cef88c1004e41b8e945a277e2c25dc0b72060" dependencies = [ "proc-macro2", "quote", @@ -1309,18 +1328,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d12a1dae4add0f0d568eebc7bf142f145ba1aa2544cafb195c76f0f409091b60" +checksum = "467e5ff447618a916519a4e0d62772ab14f434897f3d63f05d8700ef1e9b22c1" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f34e0c1caaa462fd840ec6b768946ea1e7842620d94fe29d5b847138f521269" +checksum = "e63c1091225b9834089b429bc4a2e01223470e3183e891582909e9d1c4cb55d9" dependencies = [ "proc-macro2", "quote", @@ -1386,9 +1405,9 @@ checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" [[package]] name = "vec_map" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" diff --git a/appveyor.yml b/appveyor.yml index 7520fbecd04..8e84dd7e7a8 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -48,6 +48,8 @@ install: build: false test_script: + - set CFG_RELEASE_CHANNEL=nightly + - set CFG_RELEASE=nightly - cargo build --verbose - cargo test - cargo test -- --ignored diff --git a/ci/integration.sh b/ci/integration.sh index b1e8d0c8db1..823f176a95b 100755 --- a/ci/integration.sh +++ b/ci/integration.sh @@ -15,6 +15,10 @@ set -ex # it again. # #which cargo-fmt || cargo install --force + +export CFG_RELEASE_CHANNEL=nightly +export CFG_RELEASE=nightly + cargo install --path . --force --locked echo "Integration tests for: ${INTEGRATION}" diff --git a/rustfmt-core/rustfmt-lib/Cargo.toml b/rustfmt-core/rustfmt-lib/Cargo.toml index 8609cc8e243..6296eebe192 100644 --- a/rustfmt-core/rustfmt-lib/Cargo.toml +++ b/rustfmt-core/rustfmt-lib/Cargo.toml @@ -59,32 +59,32 @@ env_logger = "0.7" [dependencies.rustc_ast] package = "rustc-ap-rustc_ast" -version = "656.0.0" +version = "659.0.0" [dependencies.rustc_ast_pretty] package = "rustc-ap-rustc_ast_pretty" -version = "656.0.0" +version = "659.0.0" [dependencies.rustc_data_structures] package = "rustc-ap-rustc_data_structures" -version = "656.0.0" +version = "659.0.0" [dependencies.rustc_errors] package = "rustc-ap-rustc_errors" -version = "656.0.0" +version = "659.0.0" [dependencies.rustc_expand] package = "rustc-ap-rustc_expand" -version = "656.0.0" +version = "659.0.0" [dependencies.rustc_parse] package = "rustc-ap-rustc_parse" -version = "656.0.0" +version = "659.0.0" [dependencies.rustc_session] package = "rustc-ap-rustc_session" -version = "656.0.0" +version = "659.0.0" [dependencies.rustc_span] package = "rustc-ap-rustc_span" -version = "656.0.0" +version = "659.0.0" diff --git a/rustfmt-core/rustfmt-lib/src/chains.rs b/rustfmt-core/rustfmt-lib/src/chains.rs index 16a570945c5..2f938ae340d 100644 --- a/rustfmt-core/rustfmt-lib/src/chains.rs +++ b/rustfmt-core/rustfmt-lib/src/chains.rs @@ -59,7 +59,7 @@ use std::borrow::Cow; use std::cmp::min; use rustc_ast::{ast, ptr}; -use rustc_span::{BytePos, Span}; +use rustc_span::{symbol, BytePos, Span}; use crate::comment::{rewrite_comment, CharClasses, FullCodeCharKind, RichChar}; use crate::config::IndentStyle; @@ -116,8 +116,8 @@ enum ChainItemKind { Vec, Vec>, ), - StructField(ast::Ident), - TupleField(ast::Ident, bool), + StructField(symbol::Ident), + TupleField(symbol::Ident, bool), Await, Comment(String, CommentPosition), } @@ -234,7 +234,7 @@ impl ChainItem { } fn rewrite_method_call( - method_name: ast::Ident, + method_name: symbol::Ident, types: &[ast::GenericArg], args: &[ptr::P], span: Span, diff --git a/rustfmt-core/rustfmt-lib/src/imports.rs b/rustfmt-core/rustfmt-lib/src/imports.rs index f686e22d250..17a173e39cb 100644 --- a/rustfmt-core/rustfmt-lib/src/imports.rs +++ b/rustfmt-core/rustfmt-lib/src/imports.rs @@ -3,7 +3,11 @@ use std::cmp::Ordering; use std::fmt; use rustc_ast::ast::{self, UseTreeKind}; -use rustc_span::{source_map, symbol::sym, BytePos, Span, DUMMY_SP}; +use rustc_span::{ + source_map, + symbol::{self, sym}, + BytePos, Span, DUMMY_SP, +}; use crate::comment::combine_strs_with_missing_comments; use crate::config::lists::*; @@ -21,7 +25,7 @@ use crate::visitor::FmtVisitor; /// Returns a name imported by a `use` declaration. /// E.g., returns `Ordering` for `std::cmp::Ordering` and `self` for `std::cmp::self`. -pub(crate) fn path_to_imported_ident(path: &ast::Path) -> ast::Ident { +pub(crate) fn path_to_imported_ident(path: &ast::Path) -> symbol::Ident { path.segments.last().unwrap().ident } diff --git a/rustfmt-core/rustfmt-lib/src/items.rs b/rustfmt-core/rustfmt-lib/src/items.rs index 3750fa5766e..40395bbbbd5 100644 --- a/rustfmt-core/rustfmt-lib/src/items.rs +++ b/rustfmt-core/rustfmt-lib/src/items.rs @@ -370,7 +370,7 @@ impl<'a> FmtVisitor<'a> { pub(crate) fn rewrite_fn_before_block( &mut self, indent: Indent, - ident: ast::Ident, + ident: symbol::Ident, fn_sig: &FnSig<'_>, span: Span, ) -> Option<(String, FnBraceStyle)> { @@ -394,7 +394,7 @@ impl<'a> FmtVisitor<'a> { pub(crate) fn rewrite_required_fn( &mut self, indent: Indent, - ident: ast::Ident, + ident: symbol::Ident, sig: &ast::FnSig, generics: &ast::Generics, span: Span, @@ -470,7 +470,7 @@ impl<'a> FmtVisitor<'a> { pub(crate) fn visit_enum( &mut self, - ident: ast::Ident, + ident: symbol::Ident, vis: &ast::Visibility, enum_def: &ast::EnumDef, generics: &ast::Generics, @@ -1012,7 +1012,7 @@ fn rewrite_trait_ref( pub(crate) struct StructParts<'a> { prefix: &'a str, - ident: ast::Ident, + ident: symbol::Ident, vis: &'a ast::Visibility, def: &'a ast::VariantData, generics: Option<&'a ast::Generics>, @@ -1279,7 +1279,7 @@ impl<'a> Rewrite for TraitAliasBounds<'a> { pub(crate) fn format_trait_alias( context: &RewriteContext<'_>, - ident: ast::Ident, + ident: symbol::Ident, vis: &ast::Visibility, generics: &ast::Generics, generic_bounds: &ast::GenericBounds, @@ -1559,7 +1559,7 @@ fn format_tuple_struct( fn rewrite_type( context: &RewriteContext<'_>, indent: Indent, - ident: ast::Ident, + ident: symbol::Ident, vis: &ast::Visibility, generics: &ast::Generics, generic_bounds_opt: Option<&ast::GenericBounds>, @@ -1628,7 +1628,7 @@ fn rewrite_type( pub(crate) fn rewrite_opaque_type( context: &RewriteContext<'_>, indent: Indent, - ident: ast::Ident, + ident: symbol::Ident, generic_bounds: &ast::GenericBounds, generics: &ast::Generics, vis: &ast::Visibility, @@ -1742,7 +1742,7 @@ pub(crate) fn rewrite_struct_field( pub(crate) struct StaticParts<'a> { prefix: &'a str, vis: &'a ast::Visibility, - ident: ast::Ident, + ident: symbol::Ident, ty: &'a ast::Ty, mutability: ast::Mutability, expr_opt: Option<&'a ptr::P>, @@ -1884,7 +1884,7 @@ fn rewrite_static( } pub(crate) fn rewrite_type_alias( - ident: ast::Ident, + ident: symbol::Ident, ty_opt: Option<&ptr::P>, generics: &ast::Generics, generic_bounds_opt: Option<&ast::GenericBounds>, @@ -1918,7 +1918,7 @@ impl<'a> Rewrite for OpaqueType<'a> { pub(crate) fn rewrite_opaque_impl_type( context: &RewriteContext<'_>, - ident: ast::Ident, + ident: symbol::Ident, generics: &ast::Generics, generic_bounds: &ast::GenericBounds, indent: Indent, @@ -1942,7 +1942,7 @@ pub(crate) fn rewrite_opaque_impl_type( } pub(crate) fn rewrite_associated_impl_type( - ident: ast::Ident, + ident: symbol::Ident, vis: &ast::Visibility, defaultness: ast::Defaultness, ty_opt: Option<&ptr::P>, @@ -2178,7 +2178,7 @@ pub(crate) enum FnBraceStyle { fn rewrite_fn_base( context: &RewriteContext<'_>, indent: Indent, - ident: ast::Ident, + ident: symbol::Ident, fn_sig: &FnSig<'_>, span: Span, fn_brace_style: FnBraceStyle, @@ -2981,7 +2981,7 @@ fn rewrite_comments_before_after_where( fn format_header( context: &RewriteContext<'_>, item_name: &str, - ident: ast::Ident, + ident: symbol::Ident, vis: &ast::Visibility, ) -> String { format!( diff --git a/rustfmt-core/rustfmt-lib/src/lib.rs b/rustfmt-core/rustfmt-lib/src/lib.rs index 29e2a7c360e..073e08d4710 100644 --- a/rustfmt-core/rustfmt-lib/src/lib.rs +++ b/rustfmt-core/rustfmt-lib/src/lib.rs @@ -16,6 +16,7 @@ use std::path::PathBuf; use std::rc::Rc; use rustc_ast::ast; +use rustc_span::symbol; use thiserror::Error; pub use crate::config::{ @@ -508,7 +509,7 @@ impl Input { let file_stem = file.file_stem()?; if file.parent()?.to_path_buf().join(file_stem).is_dir() { Some(DirectoryOwnership::Owned { - relative: file_stem.to_str().map(ast::Ident::from_str), + relative: file_stem.to_str().map(symbol::Ident::from_str), }) } else { None diff --git a/rustfmt-core/rustfmt-lib/src/macros.rs b/rustfmt-core/rustfmt-lib/src/macros.rs index b92faae8898..919c29185d3 100644 --- a/rustfmt-core/rustfmt-lib/src/macros.rs +++ b/rustfmt-core/rustfmt-lib/src/macros.rs @@ -17,7 +17,10 @@ use rustc_ast::tokenstream::{Cursor, TokenStream, TokenTree}; use rustc_ast::{ast, ptr}; use rustc_ast_pretty::pprust; use rustc_parse::{new_parser_from_tts, parser::Parser}; -use rustc_span::{symbol::kw, BytePos, Span, Symbol, DUMMY_SP}; +use rustc_span::{ + symbol::{self, kw}, + BytePos, Span, Symbol, DUMMY_SP, +}; use crate::comment::{ contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses, @@ -52,7 +55,7 @@ pub(crate) enum MacroArg { Ty(ptr::P), Pat(ptr::P), Item(ptr::P), - Keyword(ast::Ident, Span), + Keyword(symbol::Ident, Span), } impl MacroArg { @@ -137,7 +140,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { fn rewrite_macro_name( context: &RewriteContext<'_>, path: &ast::Path, - extra_ident: Option, + extra_ident: Option, ) -> String { let name = if path.segments.len() == 1 { // Avoid using pretty-printer in the common case. @@ -188,7 +191,7 @@ fn return_macro_parse_failure_fallback( pub(crate) fn rewrite_macro( mac: &ast::MacCall, - extra_ident: Option, + extra_ident: Option, context: &RewriteContext<'_>, shape: Shape, position: MacroPosition, @@ -229,7 +232,7 @@ fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { if parser.token.is_keyword(keyword) && parser.look_ahead(1, |t| is_delim(t.kind.clone())) { parser.bump(); return Some(MacroArg::Keyword( - ast::Ident::with_dummy_span(keyword), + symbol::Ident::with_dummy_span(keyword), parser.prev_token.span, )); } @@ -239,7 +242,7 @@ fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { fn rewrite_macro_inner( mac: &ast::MacCall, - extra_ident: Option, + extra_ident: Option, context: &RewriteContext<'_>, shape: Shape, position: MacroPosition, @@ -478,7 +481,7 @@ pub(crate) fn rewrite_macro_def( shape: Shape, indent: Indent, def: &ast::MacroDef, - ident: ast::Ident, + ident: symbol::Ident, vis: &ast::Visibility, span: Span, ) -> Option { @@ -618,7 +621,7 @@ fn replace_names(input: &str) -> Option<(String, HashMap)> { #[derive(Debug, Clone)] enum MacroArgKind { /// e.g., `$x: expr`. - MetaVariable(ast::Name, String), + MetaVariable(Symbol, String), /// e.g., `$($foo: expr),*` Repeat( /// `()`, `[]` or `{}`. diff --git a/rustfmt-core/rustfmt-lib/src/modules.rs b/rustfmt-core/rustfmt-lib/src/modules.rs index 0c932e78023..d51ded36117 100644 --- a/rustfmt-core/rustfmt-lib/src/modules.rs +++ b/rustfmt-core/rustfmt-lib/src/modules.rs @@ -4,7 +4,7 @@ use std::path::{Path, PathBuf}; use rustc_ast::ast; use rustc_ast::visit::Visitor; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::{self, sym, Symbol}; use crate::attr::MetaVisitor; use crate::config::FileName; @@ -239,7 +239,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { /// Find a file path in the filesystem which corresponds to the given module. fn find_external_module( &self, - mod_name: ast::Ident, + mod_name: symbol::Ident, attrs: &[ast::Attribute], sub_mod: &Cow<'ast, ast::Mod>, ) -> Result>, String> { @@ -326,7 +326,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } } - fn push_inline_mod_directory(&mut self, id: ast::Ident, attrs: &[ast::Attribute]) { + fn push_inline_mod_directory(&mut self, id: symbol::Ident, attrs: &[ast::Attribute]) { if let Some(path) = find_path_value(attrs) { self.directory.path.push(&*path.as_str()); self.directory.ownership = DirectoryOwnership::Owned { relative: None }; diff --git a/rustfmt-core/rustfmt-lib/src/syntux/session.rs b/rustfmt-core/rustfmt-lib/src/syntux/session.rs index da8741c84e5..00f12b32237 100644 --- a/rustfmt-core/rustfmt-lib/src/syntux/session.rs +++ b/rustfmt-core/rustfmt-lib/src/syntux/session.rs @@ -2,14 +2,13 @@ use std::cell::RefCell; use std::path::Path; use std::rc::Rc; -use rustc_ast::ast; use rustc_data_structures::sync::{Lrc, Send}; use rustc_errors::emitter::{Emitter, EmitterWriter}; use rustc_errors::{ColorConfig, Diagnostic, Handler, Level as DiagnosticLevel}; use rustc_session::parse::ParseSess as RawParseSess; use rustc_span::{ source_map::{FilePathMapping, SourceMap}, - BytePos, Span, + symbol, BytePos, Span, }; use crate::config::file_lines::LineRange; @@ -147,8 +146,8 @@ impl ParseSess { pub(crate) fn default_submod_path( &self, - id: ast::Ident, - relative: Option, + id: symbol::Ident, + relative: Option, dir_path: &Path, ) -> rustc_expand::module::ModulePath<'_> { rustc_expand::module::default_submod_path( diff --git a/rustfmt-core/rustfmt-lib/src/utils.rs b/rustfmt-core/rustfmt-lib/src/utils.rs index 63b09537961..c73eae5cd06 100644 --- a/rustfmt-core/rustfmt-lib/src/utils.rs +++ b/rustfmt-core/rustfmt-lib/src/utils.rs @@ -6,7 +6,7 @@ use rustc_ast::ast::{ }; use rustc_ast::ptr; use rustc_ast_pretty::pprust; -use rustc_span::{sym, BytePos, ExpnId, Span, Symbol, SyntaxContext}; +use rustc_span::{sym, symbol, BytePos, ExpnId, Span, Symbol, SyntaxContext}; use unicode_width::UnicodeWidthStr; use crate::comment::{filter_normal_code, CharClasses, FullCodeCharKind, LineClasses}; @@ -24,7 +24,7 @@ pub(crate) fn skip_annotation() -> Symbol { Symbol::intern("rustfmt::skip") } -pub(crate) fn rewrite_ident<'a>(context: &'a RewriteContext<'_>, ident: ast::Ident) -> &'a str { +pub(crate) fn rewrite_ident<'a>(context: &'a RewriteContext<'_>, ident: symbol::Ident) -> &'a str { context.snippet(ident.span) } diff --git a/rustfmt-core/rustfmt-lib/src/visitor.rs b/rustfmt-core/rustfmt-lib/src/visitor.rs index 02c6cffe4a9..daf96ac34f8 100644 --- a/rustfmt-core/rustfmt-lib/src/visitor.rs +++ b/rustfmt-core/rustfmt-lib/src/visitor.rs @@ -2,7 +2,7 @@ use std::cell::{Cell, RefCell}; use std::rc::Rc; use rustc_ast::{ast, token::DelimToken, visit}; -use rustc_span::{BytePos, Pos, Span}; +use rustc_span::{symbol, BytePos, Pos, Span}; use crate::attr::*; use crate::comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; @@ -686,7 +686,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } } - fn visit_mac(&mut self, mac: &ast::MacCall, ident: Option, pos: MacroPosition) { + fn visit_mac(&mut self, mac: &ast::MacCall, ident: Option, pos: MacroPosition) { skip_out_of_file_lines_range_visitor!(self, mac.span()); // 1 = ; @@ -896,7 +896,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { m: &ast::Mod, vis: &ast::Visibility, s: Span, - ident: ast::Ident, + ident: symbol::Ident, attrs: &[ast::Attribute], is_internal: bool, ) { From 4343c4f689f87906123f2dcade0c3c0082a71488 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 30 Apr 2020 16:18:59 +0900 Subject: [PATCH 29/59] Refactor --- Configurations.md | 23 +- rustfmt-core/rustfmt-bin/src/bin/main.rs | 194 +++--- .../rustfmt-bin/src/git-rustfmt/main.rs | 19 +- .../rustfmt-bin/tests/rustfmt/main.rs | 8 +- rustfmt-core/rustfmt-lib/src/comment.rs | 12 - rustfmt-core/rustfmt-lib/src/config.rs | 27 +- .../rustfmt-lib/src/config/config_type.rs | 5 +- .../rustfmt-lib/src/config/options.rs | 66 +- rustfmt-core/rustfmt-lib/src/emitter/diff.rs | 40 +- rustfmt-core/rustfmt-lib/src/emitter/files.rs | 5 +- .../rustfmt-lib/src/emitter/rustfmt_diff.rs | 7 +- .../rustfmt-lib/src/emitter/stdout.rs | 8 +- .../src/format_report_formatter.rs | 87 +-- rustfmt-core/rustfmt-lib/src/formatting.rs | 467 +++++--------- rustfmt-core/rustfmt-lib/src/lib.rs | 571 +++++++++++------- rustfmt-core/rustfmt-lib/src/macros.rs | 13 +- rustfmt-core/rustfmt-lib/src/rewrite.rs | 4 +- rustfmt-core/rustfmt-lib/src/source_file.rs | 61 +- .../rustfmt-lib/src/syntux/session.rs | 6 +- .../src/test/configuration_snippet.rs | 48 +- rustfmt-core/rustfmt-lib/src/test/mod.rs | 181 +++--- rustfmt-core/rustfmt-lib/src/visitor.rs | 24 +- .../rustfmt-lib/tests/config/issue-3933.toml | 1 - .../rustfmt-lib/tests/config/issue-3956.toml | 1 - .../tests/source/issue-3933/lib.rs | 1 + .../tests/target/issue-3933/lib.rs | 1 + .../tests/target/issue-3956/lib.rs | 1 + 27 files changed, 871 insertions(+), 1010 deletions(-) diff --git a/Configurations.md b/Configurations.md index 2cfc25fcc16..26dd316fb61 100644 --- a/Configurations.md +++ b/Configurations.md @@ -311,14 +311,6 @@ By default this option is set as a percentage of [`max_width`](#max_width) provi See also [`max_width`](#max_width) and [`width_heuristics`](#width_heuristics) -## `color` - -Whether to use colored output or not. - -- **Default value**: `"Auto"` -- **Possible values**: "Auto", "Always", "Never" -- **Stable**: No (tracking issue: [#3385](https://github.com/rust-lang/rustfmt/issues/3385)) - ## `combine_control_expr` Combine control expressions with function calls. @@ -2629,17 +2621,4 @@ 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. -``` - -# Internal Options - -## `emit_mode` - -Internal option - -## `print_misformatted_file_names` - -Internal option, use `-l` or `--files-with-diff` - -## `recursive` -Internal option, use `-r` or `--recursive` +``` \ No newline at end of file diff --git a/rustfmt-core/rustfmt-bin/src/bin/main.rs b/rustfmt-core/rustfmt-bin/src/bin/main.rs index 49d45e984f5..7f9b65664a9 100644 --- a/rustfmt-core/rustfmt-bin/src/bin/main.rs +++ b/rustfmt-core/rustfmt-bin/src/bin/main.rs @@ -14,12 +14,14 @@ use structopt::StructOpt; use thiserror::Error; use rustfmt_lib::{ - load_config, CliOptions, Config, Edition, EmitMode, FileLines, FileName, - FormatReportFormatterBuilder, Input, Session, Verbosity, + load_config, write_all_files, CliOptions, Config, Edition, EmitMode, EmitterConfig, FileLines, + FileName, FormatReport, FormatReportFormatterBuilder, Input, RustFormatterBuilder, Session, + Verbosity, }; fn main() { env_logger::init(); + let opt: Opt = Opt::from_args(); let exit_code = match execute(opt) { @@ -127,6 +129,32 @@ struct Opt { files: Vec, } +impl Opt { + fn verbosity(&self) -> Verbosity { + if self.verbose { + Verbosity::Verbose + } else if self.quiet { + Verbosity::Quiet + } else { + Verbosity::Normal + } + } + + fn emitter_config(&self, default_emit_mode: EmitMode) -> EmitterConfig { + let emit_mode = if self.check { + EmitMode::Diff + } else { + self.emit.map_or(default_emit_mode, Emit::to_emit_mode) + }; + EmitterConfig { + emit_mode, + verbosity: self.verbosity(), + print_filename: self.files_with_diff, + ..EmitterConfig::default() + } + } +} + #[derive(Debug, Clone)] struct InlineConfig(HashMap, bool /* is help */); @@ -307,29 +335,13 @@ impl From for OperationError { impl CliOptions for Opt { fn apply_to(&self, config: &mut Config) { - if self.verbose { - config.set().verbose(Verbosity::Verbose); - } else if self.quiet { - config.set().verbose(Verbosity::Quiet); - } config.set().file_lines(self.file_lines.clone()); - if self.recursive { - config.set().recursive(true); - } if self.error_on_unformatted { config.set().error_on_unformatted(true); } if let Some(ref edition) = self.edition { config.set().edition((*edition).clone()); } - if self.check { - config.set().emit_mode(EmitMode::Diff); - } else if let Some(emit) = self.emit { - config.set().emit_mode(emit.to_emit_mode()); - } - if self.files_with_diff { - config.set().print_misformatted_file_names(true); - } if let Some(ref inline_configs) = self.inline_config { for inline_config in inline_configs { for (k, v) in &inline_config.0 { @@ -392,17 +404,8 @@ fn format_string(input: String, opt: Opt) -> Result { // try to read config from local directory let (mut config, _) = load_config(Some(Path::new(".")), Some(&opt))?; - if opt.check { - config.set().emit_mode(EmitMode::Diff); - } else { - config - .set() - .emit_mode(opt.emit.map_or(EmitMode::Stdout, Emit::to_emit_mode)); - } - config.set().verbose(Verbosity::Quiet); - // parse file_lines - config.set().file_lines(opt.file_lines); + config.set().file_lines(opt.file_lines.clone()); for f in config.file_lines().files() { match *f { FileName::Stdin => {} @@ -411,15 +414,20 @@ fn format_string(input: String, opt: Opt) -> Result { } let out = &mut stdout(); - let mut session = Session::new(config, Some(out)); - format_and_emit_report(&mut session, Input::Text(input)); - - let exit_code = if session.has_operational_errors() || session.has_parsing_errors() { - 1 - } else { - 0 - }; - Ok(exit_code) + let mut session = RustFormatterBuilder::default() + .recursive(opt.recursive) + .verbosity(Verbosity::Quiet) + .build(); + let mut format_report = FormatReport::new(); + // FIXME: Add error handling. + format_and_emit_report( + &mut session, + Input::Text(input), + &config, + &mut format_report, + ); + let has_diff = write_all_files(format_report, out, opt.emitter_config(EmitMode::Stdout))?; + Ok(if opt.check && has_diff { 1 } else { 0 }) } enum FileConfig { @@ -484,21 +492,24 @@ fn format(opt: Opt) -> Result { let (config, config_path) = load_config(None, Some(&opt))?; - if config.verbose() == Verbosity::Verbose { + if opt.verbose { if let Some(path) = config_path.as_ref() { println!("Using rustfmt config file {}", path.display()); } } - let out = &mut stdout(); - let mut session = Session::new(config, Some(out)); + let mut session = RustFormatterBuilder::default() + .recursive(opt.recursive) + .verbosity(opt.verbosity()) + .build(); + let mut format_report = FormatReport::new(); for pair in FileConfigPairIter::new(&opt, config_path.is_some()) { let file = pair.file; if let FileConfig::Local(local_config, config_path) = pair.config { if let Some(path) = config_path { - if local_config.verbose() == Verbosity::Verbose { + if opt.verbose { println!( "Using rustfmt config file {} for {}", path.display(), @@ -507,54 +518,50 @@ fn format(opt: Opt) -> Result { } } - session.override_config(local_config, |sess| { - format_and_emit_report(sess, Input::File(file.to_path_buf())) - }); + format_and_emit_report( + &mut session, + Input::File(file.to_path_buf()), + &local_config, + &mut format_report, + ); } else { - format_and_emit_report(&mut session, Input::File(file.to_path_buf())); + format_and_emit_report( + &mut session, + Input::File(file.to_path_buf()), + &config, + &mut format_report, + ); } } - let exit_code = if session.has_operational_errors() - || session.has_parsing_errors() - || ((session.has_diff() || session.has_check_errors()) && opt.check) - { - 1 - } else { - 0 - }; - Ok(exit_code) + if format_report.has_errors() { + eprintln!( + "{}", + FormatReportFormatterBuilder::new(&format_report) + .enable_colors(true) + .build() + ); + } + + let out = &mut stdout(); + let has_diff = write_all_files(format_report, out, opt.emitter_config(EmitMode::Files))?; + + Ok(if opt.check && has_diff { 1 } else { 0 }) } -fn format_and_emit_report(session: &mut Session<'_, T>, input: Input) { - match session.format(input) { +fn format_and_emit_report( + session: &mut Session, + input: Input, + config: &Config, + format_report: &mut FormatReport, +) { + match session.format(input, config) { Ok(report) => { - if report.has_warnings() { - eprintln!( - "{}", - FormatReportFormatterBuilder::new(&report) - .enable_colors(should_print_with_colors(session)) - .build() - ); - } - } - Err(msg) => { - eprintln!("Error writing files: {}", msg); - session.add_operational_error(); + format_report.merge(report); } - } -} - -fn should_print_with_colors(session: &mut Session<'_, T>) -> bool { - match term::stderr() { - Some(ref t) - if session.config.color().use_colored_tty() - && t.supports_color() - && t.supports_attr(term::Attr::Bold) => - { - true + Err(err) => { + eprintln!("{}", err); } - _ => false, } } @@ -567,31 +574,6 @@ mod test { let _ = env_logger::builder().is_test(true).try_init(); } - #[test] - fn format_lines_errors_are_reported() { - init_log(); - let long_identifier = String::from_utf8(vec![b'a'; 239]).unwrap(); - let input = Input::Text(format!("fn {}() {{}}", long_identifier)); - let mut config = Config::default(); - config.set().error_on_line_overflow(true); - let mut session = Session::::new(config, None); - session.format(input).unwrap(); - assert!(session.has_formatting_errors()); - } - - #[test] - fn format_lines_errors_are_reported_with_tabs() { - init_log(); - let long_identifier = String::from_utf8(vec![b'a'; 97]).unwrap(); - let input = Input::Text(format!("fn a() {{\n\t{}\n}}", long_identifier)); - let mut config = Config::default(); - config.set().error_on_line_overflow(true); - config.set().hard_tabs(true); - let mut session = Session::::new(config, None); - session.format(input).unwrap(); - assert!(session.has_formatting_errors()); - } - struct TempFile { path: PathBuf, } @@ -704,7 +686,7 @@ mod test { let output = child .wait_with_output() .expect("Failed to wait on rustfmt child"); - assert!(output.status.success()); + assert!(!output.status.success()); assert_eq!(std::str::from_utf8(&output.stdout).unwrap(), "stdin\n"); } diff --git a/rustfmt-core/rustfmt-bin/src/git-rustfmt/main.rs b/rustfmt-core/rustfmt-bin/src/git-rustfmt/main.rs index d84b1a48ed9..495db9679a5 100644 --- a/rustfmt-core/rustfmt-bin/src/git-rustfmt/main.rs +++ b/rustfmt-core/rustfmt-bin/src/git-rustfmt/main.rs @@ -7,7 +7,10 @@ use std::process::Command; use structopt::StructOpt; -use rustfmt_lib::{load_config, CliOptions, FormatReportFormatterBuilder, Input, Session}; +use rustfmt_lib::{ + load_config, write_all_files, CliOptions, EmitterConfig, FormatReportFormatterBuilder, Input, + Session, +}; fn prune_files(files: Vec<&str>) -> Vec<&str> { let prefixes: Vec<_> = files @@ -57,19 +60,19 @@ fn fmt_files(files: &[&str]) -> i32 { let (config, _) = load_config::(Some(Path::new(".")), None).expect("couldn't load config"); - let mut exit_code = 0; let mut out = stdout(); - let mut session = Session::new(config, Some(&mut out)); + let mut session = Session::default(); for file in files { - let report = session.format(Input::File(PathBuf::from(file))).unwrap(); + let report = session + .format(Input::File(PathBuf::from(file)), &config) + .unwrap(); if report.has_warnings() { eprintln!("{}", FormatReportFormatterBuilder::new(&report).build()); } - if !session.has_no_errors() { - exit_code = 1; - } + write_all_files(report, &mut out, EmitterConfig::default()).unwrap(); } - exit_code + + todo!("Fix error handling") } struct NullOptions; diff --git a/rustfmt-core/rustfmt-bin/tests/rustfmt/main.rs b/rustfmt-core/rustfmt-bin/tests/rustfmt/main.rs index 34153da0856..29fc78c0a77 100644 --- a/rustfmt-core/rustfmt-bin/tests/rustfmt/main.rs +++ b/rustfmt-core/rustfmt-bin/tests/rustfmt/main.rs @@ -77,9 +77,9 @@ fn inline_config() { "--print-config", "current", ".", - "--config=color=Never,edition=2018" + "--config=max_width=50,edition=2018" ], - contains("color = \"Never\"") && contains("edition = \"2018\"") + contains("max_width = 50") && contains("edition = \"2018\"") ); // multiple overriding invocations @@ -89,11 +89,11 @@ fn inline_config() { "current", ".", "--config", - "color=never,edition=2018", + "max_width=80,edition=2018", "--config", "color=always,format_strings=true" ], - contains("color = \"Always\"") + contains("max_width = 80") && contains("edition = \"2018\"") && contains("format_strings = true") ); diff --git a/rustfmt-core/rustfmt-lib/src/comment.rs b/rustfmt-core/rustfmt-lib/src/comment.rs index f24b9568ab1..95ed499af6d 100644 --- a/rustfmt-core/rustfmt-lib/src/comment.rs +++ b/rustfmt-core/rustfmt-lib/src/comment.rs @@ -13,7 +13,6 @@ use crate::utils::{ count_newlines, first_line_width, last_line_width, tab_to_spaces, trim_left_preserve_layout, unicode_str_width, }; -use crate::{ErrorKind, FormattingError}; fn is_custom_comment(comment: &str) -> bool { if !comment.starts_with("//") { @@ -1580,17 +1579,6 @@ pub(crate) fn recover_comment_removed( let snippet = context.snippet(span); let includes_comment = contains_comment(snippet); if snippet != new && includes_comment && changed_comment_content(snippet, &new) { - // We missed some comments. Warn and keep the original text. - if context.config.error_on_unformatted() { - context.report.append( - context.parse_sess.span_to_filename(span), - vec![FormattingError::from_span( - span, - &context.parse_sess, - ErrorKind::LostComment, - )], - ); - } Some(snippet.to_owned()) } else { Some(new) diff --git a/rustfmt-core/rustfmt-lib/src/config.rs b/rustfmt-core/rustfmt-lib/src/config.rs index b02fb4bd0b9..76bd0d89055 100644 --- a/rustfmt-core/rustfmt-lib/src/config.rs +++ b/rustfmt-core/rustfmt-lib/src/config.rs @@ -140,8 +140,6 @@ create_config! { in tuple patterns"; // Control options (changes the operation of rustfmt, rather than the formatting) - color: Color, Color::Auto, false, - "What Color option to use when none is supplied: Always, Never, Auto"; required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false, "Require a specific version of rustfmt"; unstable_features: bool, false, false, @@ -155,17 +153,9 @@ create_config! { "Skip formatting the specified files and directories"; // Not user-facing - verbose: Verbosity, Verbosity::Normal, false, "How much to information to emit to the user"; file_lines: FileLines, FileLines::all(), false, "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ via the --file-lines option"; - emit_mode: EmitMode, EmitMode::Files, false, - "What emit Mode to use when none is supplied"; - 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. "; - recursive: bool, false, true, - "Format all encountered modules recursively, including those defined in external files."; } #[derive(Error, Debug)] @@ -177,10 +167,6 @@ impl PartialConfig { // Non-user-facing options can't be specified in TOML let mut cloned = self.clone(); cloned.file_lines = None; - cloned.verbose = None; - cloned.print_misformatted_file_names = None; - cloned.recursive = None; - cloned.emit_mode = None; ::toml::to_string(&cloned).map_err(ToTomlError) } @@ -405,8 +391,6 @@ mod test { "Require a specific version of rustfmt."; ignore: IgnoreList, IgnoreList::default(), false, "Skip formatting the specified files and directories."; - verbose: Verbosity, Verbosity::Normal, false, - "How much to information to emit to the user"; file_lines: FileLines, FileLines::all(), false, "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ via the --file-lines option"; @@ -436,10 +420,10 @@ mod test { #[test] fn test_config_set() { let mut config = Config::default(); - config.set().verbose(Verbosity::Quiet); - assert_eq!(config.verbose(), Verbosity::Quiet); - config.set().verbose(Verbosity::Normal); - assert_eq!(config.verbose(), Verbosity::Normal); + config.set().max_width(60); + assert_eq!(config.max_width(), 60); + config.set().max_width(80); + assert_eq!(config.max_width(), 80); } #[test] @@ -459,7 +443,7 @@ mod test { let config = Config::from_toml("hard_tabs = true", Path::new("")).unwrap(); assert_eq!(config.was_set().hard_tabs(), true); - assert_eq!(config.was_set().verbose(), false); + assert_eq!(config.was_set().max_width(), false); } #[test] @@ -571,7 +555,6 @@ use_try_shorthand = false use_field_init_shorthand = false force_explicit_abi = true condense_wildcard_suffixes = false -color = "Auto" required_version = "{}" unstable_features = false hide_parse_errors = false diff --git a/rustfmt-core/rustfmt-lib/src/config/config_type.rs b/rustfmt-core/rustfmt-lib/src/config/config_type.rs index fb014e2e6f0..5abb8ccc93f 100644 --- a/rustfmt-core/rustfmt-lib/src/config/config_type.rs +++ b/rustfmt-core/rustfmt-lib/src/config/config_type.rs @@ -252,9 +252,8 @@ macro_rules! create_config { #[allow(unreachable_pub)] pub fn is_hidden_option(name: &str) -> bool { - const HIDE_OPTIONS: [&str; 5] = [ - "verbose", "verbose_diff", "file_lines", - "recursive", "print_misformatted_file_names", + const HIDE_OPTIONS: [&str; 1] = [ + "file_lines", ]; HIDE_OPTIONS.contains(&name) } diff --git a/rustfmt-core/rustfmt-lib/src/config/options.rs b/rustfmt-core/rustfmt-lib/src/config/options.rs index f5592273ba3..23b4ba83e7a 100644 --- a/rustfmt-core/rustfmt-lib/src/config/options.rs +++ b/rustfmt-core/rustfmt-lib/src/config/options.rs @@ -22,6 +22,12 @@ pub enum NewlineStyle { Native, } +impl Default for NewlineStyle { + fn default() -> Self { + NewlineStyle::Auto + } +} + #[config_type] /// Where to put the opening brace of items (`fn`, `impl`, etc.). pub enum BraceStyle { @@ -107,39 +113,6 @@ pub enum ReportTactic { Never, } -/// What Rustfmt should emit. Mostly corresponds to the `--emit` command line -/// option. -#[config_type] -pub enum EmitMode { - /// Emits to files. - Files, - /// Writes the output to stdout. - Stdout, - /// Unfancy stdout - Checkstyle, - /// Writes the resulting diffs in a JSON format. Returns an empty array - /// `[]` if there were no diffs. - Json, - /// Output the changed lines (for internal value only) - ModifiedLines, - /// Checks if a diff can be generated. If so, rustfmt outputs a diff and - /// quits with exit code 1. - /// This option is designed to be run in CI where a non-zero exit signifies - /// non-standard code formatting. Used for `--check`. - Diff, -} - -/// Client-preference for coloured output. -#[config_type] -pub enum Color { - /// Always use color, whether it is a piped or terminal output - Always, - /// Never use color - Never, - /// Automatically use color, if supported by terminal - Auto, -} - #[config_type] /// rustfmt format style version. pub enum Version { @@ -149,27 +122,6 @@ pub enum Version { Two, } -impl Color { - /// Whether we should use a coloured terminal. - pub fn use_colored_tty(self) -> bool { - match self { - Color::Always | Color::Auto => true, - Color::Never => false, - } - } -} - -/// How chatty should Rustfmt be? -#[config_type] -pub enum Verbosity { - /// Emit more. - Verbose, - /// Default. - Normal, - /// Emit as little as possible. - Quiet, -} - #[derive(Deserialize, Serialize, Clone, Debug, PartialEq)] pub struct WidthHeuristics { // Maximum width of the args of a function call before falling back @@ -248,12 +200,6 @@ impl WidthHeuristics { } } -impl Default for EmitMode { - fn default() -> EmitMode { - EmitMode::Files - } -} - /// A set of directories, files and modules that rustfmt should ignore. #[derive(Default, Clone, Debug, PartialEq)] pub struct IgnoreList { diff --git a/rustfmt-core/rustfmt-lib/src/emitter/diff.rs b/rustfmt-core/rustfmt-lib/src/emitter/diff.rs index dc5908155c9..4f72211bdc0 100644 --- a/rustfmt-core/rustfmt-lib/src/emitter/diff.rs +++ b/rustfmt-core/rustfmt-lib/src/emitter/diff.rs @@ -1,15 +1,27 @@ -use crate::config::Config; - use super::*; +use crate::{Color, EmitterConfig, Verbosity}; use rustfmt_diff::{make_diff, print_diff}; pub struct DiffEmitter { - config: Config, + color: Color, + verbosity: Verbosity, + print_filename: bool, } impl DiffEmitter { - pub fn new(config: Config) -> Self { - Self { config } + pub fn new( + EmitterConfig { + color, + verbosity, + print_filename, + .. + }: EmitterConfig, + ) -> Self { + Self { + color, + verbosity, + print_filename, + } } } @@ -28,13 +40,14 @@ impl Emitter for DiffEmitter { let has_diff = !mismatch.is_empty(); if has_diff { - if self.config.print_misformatted_file_names() { + if self.print_filename { writeln!(output, "{}", filename)?; } else { print_diff( mismatch, |line_num| format!("Diff in {}:{}:", filename, line_num), - &self.config, + self.color, + self.verbosity, ); } } else if original_text != formatted_text { @@ -58,8 +71,7 @@ mod tests { #[test] fn does_not_print_when_no_files_reformatted() { let mut writer = Vec::new(); - let config = Config::default(); - let mut emitter = DiffEmitter::new(config); + let mut emitter = DiffEmitter::new(EmitterConfig::default()); let result = emitter .emit_formatted_file( &mut writer, @@ -84,9 +96,10 @@ mod tests { let lib_formatted = "fn greet() {\n println!(\"Greetings!\");\n}"; let mut writer = Vec::new(); - let mut config = Config::default(); - config.set().print_misformatted_file_names(true); - let mut emitter = DiffEmitter::new(config); + let mut emitter = DiffEmitter::new(EmitterConfig { + print_filename: true, + ..EmitterConfig::default() + }); let _ = emitter .emit_formatted_file( &mut writer, @@ -117,8 +130,7 @@ mod tests { #[test] fn prints_newline_message_with_only_newline_style_diff() { let mut writer = Vec::new(); - let config = Config::default(); - let mut emitter = DiffEmitter::new(config); + let mut emitter = DiffEmitter::new(EmitterConfig::default()); let _ = emitter .emit_formatted_file( &mut writer, diff --git a/rustfmt-core/rustfmt-lib/src/emitter/files.rs b/rustfmt-core/rustfmt-lib/src/emitter/files.rs index 4755cc8f1b6..6106c742e6a 100644 --- a/rustfmt-core/rustfmt-lib/src/emitter/files.rs +++ b/rustfmt-core/rustfmt-lib/src/emitter/files.rs @@ -1,4 +1,5 @@ use super::*; +use crate::EmitterConfig; use std::fs; #[derive(Debug, Default)] @@ -7,9 +8,9 @@ pub struct FilesEmitter { } impl FilesEmitter { - pub fn new(print_misformatted_file_names: bool) -> Self { + pub fn new(config: EmitterConfig) -> Self { Self { - print_misformatted_file_names, + print_misformatted_file_names: config.print_filename, } } } diff --git a/rustfmt-core/rustfmt-lib/src/emitter/rustfmt_diff.rs b/rustfmt-core/rustfmt-lib/src/emitter/rustfmt_diff.rs index 17f02a7e56d..56d129c75e4 100644 --- a/rustfmt-core/rustfmt-lib/src/emitter/rustfmt_diff.rs +++ b/rustfmt-core/rustfmt-lib/src/emitter/rustfmt_diff.rs @@ -3,7 +3,7 @@ use std::fmt; use std::io; use std::io::Write; -use crate::config::{Color, Config, Verbosity}; +use crate::{Color, Verbosity}; #[derive(Debug, PartialEq)] pub enum DiffLine { @@ -248,12 +248,11 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec(diff: Vec, get_section_title: F, config: &Config) +pub fn print_diff(diff: Vec, get_section_title: F, color: Color, verbosity: Verbosity) where F: Fn(u32) -> String, { - let color = config.color(); - let line_terminator = if config.verbose() == Verbosity::Verbose { + let line_terminator = if verbosity == Verbosity::Verbose { "⏎" } else { "" diff --git a/rustfmt-core/rustfmt-lib/src/emitter/stdout.rs b/rustfmt-core/rustfmt-lib/src/emitter/stdout.rs index 2ad734976a5..1673b9537b3 100644 --- a/rustfmt-core/rustfmt-lib/src/emitter/stdout.rs +++ b/rustfmt-core/rustfmt-lib/src/emitter/stdout.rs @@ -1,7 +1,7 @@ use std::io::Write; use super::*; -use crate::config::Verbosity; +use crate::{EmitterConfig, Verbosity}; #[derive(Debug)] pub struct StdoutEmitter { @@ -9,8 +9,10 @@ pub struct StdoutEmitter { } impl StdoutEmitter { - pub fn new(verbosity: Verbosity) -> Self { - Self { verbosity } + pub fn new(config: EmitterConfig) -> Self { + Self { + verbosity: config.verbosity, + } } } diff --git a/rustfmt-core/rustfmt-lib/src/format_report_formatter.rs b/rustfmt-core/rustfmt-lib/src/format_report_formatter.rs index 4532f0c8cf6..fc57d1b7985 100644 --- a/rustfmt-core/rustfmt-lib/src/format_report_formatter.rs +++ b/rustfmt-core/rustfmt-lib/src/format_report_formatter.rs @@ -1,6 +1,5 @@ use crate::config::FileName; -use crate::formatting::FormattingError; -use crate::{ErrorKind, FormatReport}; +use crate::{ErrorKind, FormatError, FormatReport}; use annotate_snippets::display_list::DisplayList; use annotate_snippets::formatter::DisplayListFormatter; use annotate_snippets::snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation}; @@ -49,16 +48,15 @@ pub struct FormatReportFormatter<'a> { impl<'a> Display for FormatReportFormatter<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let formatter = DisplayListFormatter::new(self.enable_colors, false); - let errors_by_file = &self.report.internal.borrow().0; - for (file, errors) in errors_by_file { - for error in errors { + for (file, errors) in self.report.format_result.borrow().iter() { + for error in errors.errors() { let snippet = formatting_error_to_snippet(file, error); writeln!(f, "{}\n", formatter.format(&DisplayList::from(snippet)))?; } } - if !errors_by_file.is_empty() { + if self.report.has_errors() { let snippet = formatting_failure_snippet(self.report.warning_count()); writeln!(f, "{}", formatter.format(&DisplayList::from(snippet)))?; } @@ -77,97 +75,70 @@ fn formatting_failure_snippet(warning_count: usize) -> Snippet { )), annotation_type: AnnotationType::Warning, }), - footer: Vec::new(), slices: Vec::new(), + footer: vec![], } } -fn formatting_error_to_snippet(file: &FileName, error: &FormattingError) -> Snippet { +fn formatting_error_to_snippet(file: &FileName, error: &FormatError) -> Snippet { let slices = vec![snippet_code_slice(file, error)]; let title = Some(snippet_title(error)); - let footer = snippet_footer(error).into_iter().collect(); Snippet { title, - footer, slices, + footer: vec![], } } -fn snippet_title(error: &FormattingError) -> Annotation { +fn snippet_title(error: &FormatError) -> Annotation { let annotation_type = error_kind_to_snippet_annotation_type(&error.kind); Annotation { - id: title_annotation_id(error), + id: None, label: Some(error.kind.to_string()), annotation_type, } } -fn snippet_footer(error: &FormattingError) -> Option { - let message_suffix = error.msg_suffix(); - - if !message_suffix.is_empty() { - Some(Annotation { - id: None, - label: Some(message_suffix.to_string()), - annotation_type: AnnotationType::Note, - }) - } else { - None - } -} - -fn snippet_code_slice(file: &FileName, error: &FormattingError) -> Slice { +fn snippet_code_slice(file: &FileName, error: &FormatError) -> Slice { let annotations = slice_annotation(error).into_iter().collect(); - let origin = Some(format!("{}:{}", file, error.line)); - let source = error.line_buffer.clone(); + let origin = error + .line_num + .as_ref() + .map(|line_num| format!("{}:{}", file, line_num)); + let source = error.line_str.clone().unwrap_or_else(|| String::new()); Slice { source, - line_start: error.line, + line_start: error.line_num.unwrap_or(0), origin, fold: false, annotations, } } -fn slice_annotation(error: &FormattingError) -> Option { - let (range_start, range_length) = error.format_len(); - let range_end = range_start + range_length; - - if range_length > 0 { - Some(SourceAnnotation { - annotation_type: AnnotationType::Error, - range: (range_start, range_end), - label: String::new(), - }) - } else { - None - } -} - -fn title_annotation_id(error: &FormattingError) -> Option { - const INTERNAL_ERROR_ID: &str = "internal"; - - if error.is_internal() { - Some(INTERNAL_ERROR_ID.to_string()) - } else { - None +fn slice_annotation(error: &FormatError) -> Option { + match error.format_len() { + Some((range_start, range_length)) if range_length > 0 => { + let range_end = range_start + range_length; + Some(SourceAnnotation { + annotation_type: AnnotationType::Error, + range: (range_start, range_end), + label: String::new(), + }) + } + _ => None, } } fn error_kind_to_snippet_annotation_type(error_kind: &ErrorKind) -> AnnotationType { match error_kind { ErrorKind::LineOverflow(..) + | ErrorKind::MacroFormatError | ErrorKind::TrailingWhitespace - | ErrorKind::IoError(_) - | ErrorKind::ParseError - | ErrorKind::LostComment | ErrorKind::LicenseCheck - | ErrorKind::BadAttr - | ErrorKind::InvalidGlobPattern(_) - | ErrorKind::VersionMismatch => AnnotationType::Error, + | ErrorKind::BadAttr => AnnotationType::Error, ErrorKind::DeprecatedAttr => AnnotationType::Warning, } } diff --git a/rustfmt-core/rustfmt-lib/src/formatting.rs b/rustfmt-core/rustfmt-lib/src/formatting.rs index 1f92b005e66..e2f3fa4a3b4 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting.rs @@ -1,166 +1,143 @@ // High level formatting functions. -use std::collections::HashMap; -use std::io::{self, Write}; +use std::io; use std::time::{Duration, Instant}; use rustc_ast::ast; -use rustc_span::Span; use self::newline_style::apply_newline_style; use crate::comment::{CharClasses, FullCodeCharKind}; -use crate::config::{Config, FileName, Verbosity}; +use crate::config::{Config, FileName}; use crate::syntux::parser::{DirectoryOwnership, Parser, ParserError}; use crate::syntux::session::ParseSess; use crate::utils::count_newlines; use crate::visitor::FmtVisitor; -use crate::{modules, source_file, ErrorKind, FormatReport, Input, Session}; +use crate::{ + modules, source_file, ErrorKind, FormatError, FormatReport, FormatResult, Input, + NonFormattedRange, OperationError, Session, Verbosity, +}; mod newline_style; -// A map of the files of a crate, with their new content -pub(crate) type SourceFile = Vec; -pub(crate) type FileRecord = (FileName, String); - -impl<'b, T: Write + 'b> Session<'b, T> { - pub(crate) fn format_input_inner(&mut self, input: Input) -> Result { - if !self.config.version_meets_requirement() { - return Err(ErrorKind::VersionMismatch); +impl Session { + pub(crate) fn format_input_inner( + &mut self, + input: Input, + config: &Config, + ) -> Result { + if !config.version_meets_requirement() { + return Err(OperationError::VersionMismatch); } - rustc_ast::with_globals(self.config.edition().into(), || { - let config = &self.config.clone(); - let format_result = format_project(input, config, self); - - format_result.map(|report| { - self.errors.add(&report.internal.borrow().1); - report - }) + rustc_ast::with_globals(config.edition().into(), || { + self.format_project(input, config) }) } -} -// Format an entire crate (or subset of the module tree). -fn format_project( - input: Input, - config: &Config, - handler: &mut T, -) -> Result { - let mut timer = Timer::start(); + fn format_project( + &mut self, + input: Input, + config: &Config, + ) -> Result { + let mut timer = Timer::start(); - let main_file = input.file_name(); - let input_is_stdin = main_file == FileName::Stdin; + let format_report = FormatReport::new(); - let mut parse_session = ParseSess::new(config)?; - if !config.recursive() && parse_session.ignore_file(&main_file) { - return Ok(FormatReport::new()); - } + let main_file = input.file_name(); + let input_is_stdin = main_file == FileName::Stdin; - // Parse the crate. - let mut report = FormatReport::new(); - let directory_ownership = input.to_directory_ownership(); - - let krate = match Parser::parse_crate(config, input, directory_ownership, &parse_session) { - Ok(krate) => krate, - Err(e) => { - let forbid_verbose = input_is_stdin || e != ParserError::ParsePanicError; - should_emit_verbose(forbid_verbose, config, || { - eprintln!( - "The Rust parser panicked while parsing input: {:?}: {:?}", - main_file, e - ); - }); - report.add_parsing_error(); - return Ok(report); - } - }; - timer = timer.done_parsing(); - - // Suppress error output if we have to do any further parsing. - parse_session.set_silent_emitter(); - - let mut context = FormatContext::new(&krate, report, parse_session, config, handler); - let files = modules::ModResolver::new( - &context.parse_session, - directory_ownership.unwrap_or(DirectoryOwnership::UnownedViaMod), - !input_is_stdin && config.recursive(), - ) - .visit_crate(&krate) - .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; - - for (path, module) in files { - let should_ignore = !input_is_stdin && context.ignore_file(&path); - if (!config.recursive() && path != main_file) || should_ignore { - continue; + let mut parse_session = ParseSess::new(config)?; + if !self.recursive && parse_session.ignore_file(&main_file) { + format_report.add_ignored_file(main_file); + return Ok(format_report); } - should_emit_verbose(input_is_stdin, config, || println!("Formatting {}", path)); - let is_root = path == main_file; - context.format_file(path, &module, is_root)?; - } - timer = timer.done_formatting(); - should_emit_verbose(input_is_stdin, config, || { - println!( - "Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase", - timer.get_parse_time(), - timer.get_format_time(), - ) - }); + // Parse the crate. + let directory_ownership = input.to_directory_ownership(); + let original_snippet = if let Input::Text(ref str) = input { + Some(str.to_owned()) + } else { + None + }; - Ok(context.report) -} + let krate = match Parser::parse_crate(config, input, directory_ownership, &parse_session) { + Ok(krate) => krate, + Err(e) => { + return Err(OperationError::ParseError { + input: main_file, + is_panic: e == ParserError::ParsePanicError, + }); + } + }; + timer = timer.done_parsing(); -/// Used for formatting files. -struct FormatContext<'a, T: FormatHandler> { - krate: &'a ast::Crate, - report: FormatReport, - parse_session: ParseSess, - config: &'a Config, - handler: &'a mut T, -} + // Suppress error output if we have to do any further parsing. + parse_session.set_silent_emitter(); -impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { - /// Constructs a new FormatContext. - fn new( - krate: &'a ast::Crate, - report: FormatReport, - parse_session: ParseSess, - config: &'a Config, - handler: &'a mut T, - ) -> Self { - Self { - krate, - report, - parse_session, - config, - handler, + let files = modules::ModResolver::new( + &parse_session, + directory_ownership.unwrap_or(DirectoryOwnership::UnownedViaMod), + !input_is_stdin && self.recursive, + ) + .visit_crate(&krate) + .map_err(|e| OperationError::IoError(io::Error::new(io::ErrorKind::Other, e)))?; + + for (path, module) in files { + let should_ignore = !input_is_stdin && parse_session.ignore_file(&path); + if (!self.recursive && path != main_file) || should_ignore { + continue; + } + should_emit_verbose(input_is_stdin, self.verbosity, || { + println!("Formatting {}", path) + }); + let is_root = path == main_file; + self.format_file( + &parse_session, + config, + &krate, + path, + &module, + is_root, + &format_report, + original_snippet.clone(), + ); } - } + timer = timer.done_formatting(); + + should_emit_verbose(input_is_stdin, self.verbosity, || { + println!( + "Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase", + timer.get_parse_time(), + timer.get_format_time(), + ) + }); - fn ignore_file(&self, path: &FileName) -> bool { - self.parse_session.ignore_file(path) + Ok(format_report) } +} +impl Session { // Formats a single file/module. fn format_file( &mut self, + parse_session: &ParseSess, + config: &Config, + krate: &ast::Crate, path: FileName, module: &ast::Mod, is_root: bool, - ) -> Result<(), ErrorKind> { - let snippet_provider = self.parse_session.snippet_provider(module.inner); - let mut visitor = FmtVisitor::from_parse_sess( - &self.parse_session, - &self.config, - &snippet_provider, - self.report.clone(), - ); - visitor.skip_context.update_with_attrs(&self.krate.attrs); + report: &FormatReport, + original_snippet: Option, + ) { + let snippet_provider = parse_session.snippet_provider(module.inner); + let mut visitor = + FmtVisitor::from_parse_sess(&parse_session, config, &snippet_provider, report.clone()); + visitor.skip_context.update_with_attrs(&krate.attrs); // Format inner attributes if available. - if !self.krate.attrs.is_empty() && is_root { + if !krate.attrs.is_empty() && is_root { visitor.skip_empty_lines(snippet_provider.end_pos()); - if visitor.visit_attrs(&self.krate.attrs, ast::AttrStyle::Inner) { + if visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner) { visitor.push_rewrite(module.inner, None); } else { visitor.format_separate_mod(module, snippet_provider.end_pos()); @@ -186,174 +163,26 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { &mut visitor.buffer, &path, &visitor.skipped_range.borrow(), - &self.config, - &self.report, + config, + report.clone(), ); apply_newline_style( - self.config.newline_style(), + config.newline_style(), &mut visitor.buffer, snippet_provider.entire_snippet(), ); if visitor.macro_rewrite_failure { - self.report.add_macro_format_failure(); + report.add_macro_format_failure(path.clone()); } - self.report - .add_non_formatted_ranges(visitor.skipped_range.borrow().clone()); - - self.handler.handle_formatted_file( - &self.parse_session, - path, + let format_result = FormatResult::success( visitor.buffer.to_owned(), - &mut self.report, - ) - } -} - -// Handle the results of formatting. -trait FormatHandler { - fn handle_formatted_file( - &mut self, - parse_session: &ParseSess, - path: FileName, - result: String, - report: &mut FormatReport, - ) -> Result<(), ErrorKind>; -} - -impl<'b, T: Write + 'b> FormatHandler for Session<'b, T> { - // Called for each formatted file. - fn handle_formatted_file( - &mut self, - parse_session: &ParseSess, - path: FileName, - result: String, - report: &mut FormatReport, - ) -> Result<(), ErrorKind> { - if let Some(ref mut out) = self.out { - match source_file::write_file( - Some(parse_session), - &path, - &result, - out, - &mut *self.emitter, - self.config.newline_style(), - ) { - Ok(ref result) if result.has_diff => report.add_diff(), - Err(e) => { - // Create a new error with path_str to help users see which files failed - let err_msg = format!("{}: {}", path, e); - return Err(io::Error::new(e.kind(), err_msg).into()); - } - _ => {} - } - } - - self.source_file.push((path, result)); - Ok(()) - } -} - -pub(crate) struct FormattingError { - pub(crate) line: usize, - pub(crate) kind: ErrorKind, - is_comment: bool, - is_string: bool, - pub(crate) line_buffer: String, -} - -impl FormattingError { - pub(crate) fn from_span( - span: Span, - parse_sess: &ParseSess, - kind: ErrorKind, - ) -> FormattingError { - FormattingError { - line: parse_sess.line_of_byte_pos(span.lo()), - is_comment: kind.is_comment(), - kind, - is_string: false, - line_buffer: parse_sess.span_to_first_line_string(span), - } - } - - pub(crate) fn is_internal(&self) -> bool { - match self.kind { - ErrorKind::LineOverflow(..) - | ErrorKind::TrailingWhitespace - | ErrorKind::IoError(_) - | ErrorKind::ParseError - | ErrorKind::LostComment => true, - _ => false, - } - } - - pub(crate) fn msg_suffix(&self) -> &str { - if self.is_comment || self.is_string { - "set `error_on_unformatted = false` to suppress \ - the warning against comments or string literals\n" - } else { - "" - } - } - - // (space, target) - pub(crate) fn format_len(&self) -> (usize, usize) { - match self.kind { - ErrorKind::LineOverflow(found, max) => (max, found - max), - ErrorKind::TrailingWhitespace - | ErrorKind::DeprecatedAttr - | ErrorKind::BadAttr - | ErrorKind::LostComment - | ErrorKind::LicenseCheck => { - let trailing_ws_start = self - .line_buffer - .rfind(|c: char| !c.is_whitespace()) - .map(|pos| pos + 1) - .unwrap_or(0); - ( - trailing_ws_start, - self.line_buffer.len() - trailing_ws_start, - ) - } - _ => unreachable!(), - } - } -} - -pub(crate) type FormatErrorMap = HashMap>; - -#[derive(Default, Debug, PartialEq)] -pub(crate) struct ReportedErrors { - // Encountered e.g., an IO error. - pub(crate) has_operational_errors: bool, - - // Failed to reformat code because of parsing errors. - pub(crate) has_parsing_errors: bool, - - // Code is valid, but it is impossible to format it properly. - pub(crate) has_formatting_errors: bool, - - // Code contains macro call that was unable to format. - pub(crate) has_macro_format_failure: bool, - - // Failed a check, such as the license check or other opt-in checking. - pub(crate) has_check_errors: bool, - - /// Formatted code differs from existing code (--check only). - pub(crate) has_diff: bool, -} - -impl ReportedErrors { - /// Combine two summaries together. - pub(crate) fn add(&mut self, other: &ReportedErrors) { - self.has_operational_errors |= other.has_operational_errors; - self.has_parsing_errors |= other.has_parsing_errors; - self.has_formatting_errors |= other.has_formatting_errors; - self.has_macro_format_failure |= other.has_macro_format_failure; - self.has_check_errors |= other.has_check_errors; - self.has_diff |= other.has_diff; + visitor.skipped_range.borrow().clone(), + original_snippet, + config.newline_style(), + ); + report.add_format_result(path, format_result); } } @@ -425,12 +254,14 @@ impl Timer { fn format_lines( text: &mut String, name: &FileName, - skipped_range: &[(usize, usize)], + skipped_range: &[NonFormattedRange], config: &Config, - report: &FormatReport, + report: FormatReport, ) { let mut formatter = FormatLines::new(name, skipped_range, config); - formatter.check_license(text); + if let Some(false) = formatter.check_license(text) { + report.add_license_failure(name.clone()); + } formatter.iterate(text); if formatter.newline_count > 1 { @@ -439,17 +270,17 @@ fn format_lines( text.truncate(line); } - report.append(name.clone(), formatter.errors); + report.append_errors(name.clone(), formatter.errors.into_iter()); } struct FormatLines<'a> { name: &'a FileName, - skipped_range: &'a [(usize, usize)], + skipped_range: &'a [NonFormattedRange], last_was_space: bool, line_len: usize, cur_line: usize, newline_count: usize, - errors: Vec, + errors: Vec, line_buffer: String, current_line_contains_string_literal: bool, format_line: bool, @@ -459,7 +290,7 @@ struct FormatLines<'a> { impl<'a> FormatLines<'a> { fn new( name: &'a FileName, - skipped_range: &'a [(usize, usize)], + skipped_range: &'a [NonFormattedRange], config: &'a Config, ) -> FormatLines<'a> { FormatLines { @@ -477,22 +308,15 @@ impl<'a> FormatLines<'a> { } } - fn check_license(&mut self, text: &mut String) { - if let Some(ref license_template) = self.config.license_template { - if !license_template.is_match(text) { - self.errors.push(FormattingError { - line: self.cur_line, - kind: ErrorKind::LicenseCheck, - is_comment: false, - is_string: false, - line_buffer: String::new(), - }); - } - } + fn check_license(&mut self, text: &str) -> Option { + self.config + .license_template + .as_ref() + .map(|license_template| license_template.is_match(text)) } // Iterate over the chars in the file map. - fn iterate(&mut self, text: &mut String) { + fn iterate(&mut self, text: &str) { for (kind, c) in CharClasses::new(text.chars()) { if c == '\r' { continue; @@ -513,11 +337,7 @@ impl<'a> FormatLines<'a> { if self.should_report_error(kind, &ErrorKind::TrailingWhitespace) && !self.is_skipped_line() { - self.push_err( - ErrorKind::TrailingWhitespace, - kind.is_comment(), - kind.is_string(), - ); + self.push_err(ErrorKind::TrailingWhitespace); } self.line_len -= 1; } @@ -528,8 +348,7 @@ impl<'a> FormatLines<'a> { && !self.is_skipped_line() && self.should_report_error(kind, &error_kind) { - let is_string = self.current_line_contains_string_literal; - self.push_err(error_kind, kind.is_comment(), is_string); + self.push_err(error_kind); } } @@ -559,31 +378,27 @@ impl<'a> FormatLines<'a> { } } - fn push_err(&mut self, kind: ErrorKind, is_comment: bool, is_string: bool) { - self.errors.push(FormattingError { - line: self.cur_line, + fn push_err(&mut self, kind: ErrorKind) { + self.errors.push(FormatError::new( kind, - is_comment, - is_string, - line_buffer: self.line_buffer.clone(), - }); + self.cur_line, + self.line_buffer.clone(), + )); } fn should_report_error(&self, char_kind: FullCodeCharKind, error_kind: &ErrorKind) -> bool { - let allow_error_report = if char_kind.is_comment() - || self.current_line_contains_string_literal - || error_kind.is_comment() - { - self.config.error_on_unformatted() - } else { - true - }; + let allow_error_report = + if char_kind.is_comment() || self.current_line_contains_string_literal { + self.config.error_on_unformatted() + } else { + true + }; match error_kind { ErrorKind::LineOverflow(..) => { self.config.error_on_line_overflow() && allow_error_report } - ErrorKind::TrailingWhitespace | ErrorKind::LostComment => allow_error_report, + ErrorKind::TrailingWhitespace => allow_error_report, _ => true, } } @@ -592,15 +407,15 @@ impl<'a> FormatLines<'a> { fn is_skipped_line(&self) -> bool { self.skipped_range .iter() - .any(|&(lo, hi)| lo <= self.cur_line && self.cur_line <= hi) + .any(|range| range.contains(self.cur_line)) } } -fn should_emit_verbose(forbid_verbose_output: bool, config: &Config, f: F) +fn should_emit_verbose(forbid_verbose_output: bool, verbosity: Verbosity, f: F) where F: Fn(), { - if config.verbose() == Verbosity::Verbose && !forbid_verbose_output { + if verbosity == Verbosity::Verbose && !forbid_verbose_output { f(); } } diff --git a/rustfmt-core/rustfmt-lib/src/lib.rs b/rustfmt-core/rustfmt-lib/src/lib.rs index 073e08d4710..c3e2043d010 100644 --- a/rustfmt-core/rustfmt-lib/src/lib.rs +++ b/rustfmt-core/rustfmt-lib/src/lib.rs @@ -1,37 +1,38 @@ #![deny(rust_2018_idioms)] #![warn(unreachable_pub)] +#![feature(cell_leak)] #[macro_use] extern crate lazy_static; #[macro_use] extern crate log; -use std::cell::RefCell; -use std::collections::HashMap; +use std::cell::{Ref, RefCell}; +use std::collections::{BTreeMap, BTreeSet, HashSet}; use std::fmt; -use std::io::{self, Write}; -use std::mem; +use std::io; use std::panic; use std::path::PathBuf; use std::rc::Rc; use rustc_ast::ast; -use rustc_span::symbol; +use rustc_span::{symbol, Span}; use thiserror::Error; pub use crate::config::{ - load_config, CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName, NewlineStyle, - Range, Verbosity, + load_config, CliOptions, Config, Edition, FileLines, FileName, NewlineStyle, Range, }; pub use crate::emitter::rustfmt_diff::{ModifiedChunk, ModifiedLines}; pub use crate::format_report_formatter::{FormatReportFormatter, FormatReportFormatterBuilder}; +pub use crate::source_file::write_all_files; use crate::comment::LineClasses; use crate::emitter::Emitter; -use crate::formatting::{FormatErrorMap, FormattingError, ReportedErrors, SourceFile}; use crate::shape::Indent; use crate::syntux::parser::DirectoryOwnership; +use crate::syntux::session::ParseSess; use crate::utils::indent_next_line; +use std::str::FromStr; #[macro_use] mod utils; @@ -76,9 +77,8 @@ mod types; mod vertical; pub(crate) mod visitor; -/// The various errors that can occur during formatting. Note that not all of -/// these can currently be propagated to clients. -#[derive(Error, Debug)] +/// The various errors that can occur during formatting. +#[derive(Error, Clone, Debug, Hash, Eq, PartialEq)] pub enum ErrorKind { /// Line has exceeded character limit (found, maximum). #[error( @@ -98,173 +98,315 @@ pub enum ErrorKind { /// Used a rustfmt:: attribute other than skip or skip::macros. #[error("invalid attribute")] BadAttr, - /// An io error during reading or writing. - #[error("io error: {0}")] - IoError(io::Error), - /// Parse error occurred when parsing the input. - #[error("parse error")] - ParseError, - /// The user mandated a version and the current version of Rustfmt does not - /// satisfy that requirement. - #[error("version mismatch")] - VersionMismatch, - /// If we had formatted the given node, then we would have lost a comment. - #[error("not formatted because a comment would be lost")] - LostComment, - /// Invalid glob pattern in `ignore` configuration option. - #[error("Invalid glob pattern found in ignore list: {0}")] - InvalidGlobPattern(ignore::Error), + /// Failed to format macro calls. + #[error("failed to format macro calls")] + MacroFormatError, } -impl ErrorKind { - fn is_comment(&self) -> bool { - match self { - ErrorKind::LostComment => true, - _ => false, - } +#[derive(Error, Clone, Debug, Hash, Eq, PartialEq)] +pub struct FormatError { + #[error(transparent)] + kind: ErrorKind, + line_num: Option, + line_str: Option, +} + +impl fmt::Display for FormatError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.kind.fmt(f) } } -impl From for ErrorKind { - fn from(e: io::Error) -> ErrorKind { - ErrorKind::IoError(e) +impl FormatError { + pub(crate) fn new(kind: ErrorKind, line_num: usize, line_str: String) -> Self { + FormatError { + kind, + line_num: Some(line_num), + line_str: Some(line_str), + } + } + + pub(crate) fn err_without_line_info(kind: ErrorKind) -> Self { + FormatError { + kind, + line_num: None, + line_str: None, + } + } + + pub(crate) fn from_span(kind: ErrorKind, parse_sess: &ParseSess, span: Span) -> Self { + FormatError { + kind, + line_num: Some(parse_sess.line_of_byte_pos(span.lo())), + line_str: Some(parse_sess.span_to_first_line_string(span)), + } + } + + // (space, target) + pub(crate) fn format_len(&self) -> Option<(usize, usize)> { + match self.kind { + ErrorKind::LineOverflow(found, max) => Some((max, found - max)), + ErrorKind::TrailingWhitespace + | ErrorKind::DeprecatedAttr + | ErrorKind::BadAttr + | ErrorKind::LicenseCheck => { + let len = self.line_str.as_ref().map_or(0, |s| s.len()); + let trailing_ws_start = self + .line_str + .as_ref() + .and_then(|s| s.rfind(|c: char| !c.is_whitespace())) + .map(|pos| pos + 1) + .unwrap_or(0); + Some((trailing_ws_start, len - trailing_ws_start)) + } + _ => None, + } } } /// Result of formatting a snippet of code along with ranges of lines that didn't get formatted, /// i.e., that got returned as they were originally. -#[derive(Debug)] +#[derive(Debug, Clone, Default)] struct FormattedSnippet { snippet: String, - non_formatted_ranges: Vec<(usize, usize)>, + non_formatted_ranges: Vec, } impl FormattedSnippet { /// In case the snippet needed to be wrapped in a function, this shifts down the ranges of /// non-formatted code. fn unwrap_code_block(&mut self) { - self.non_formatted_ranges - .iter_mut() - .for_each(|(low, high)| { - *low -= 1; - *high -= 1; - }); + self.non_formatted_ranges.iter_mut().for_each(|range| { + *range = range.shift_up(); + }); } /// Returns `true` if the line n did not get formatted. fn is_line_non_formatted(&self, n: usize) -> bool { self.non_formatted_ranges .iter() - .any(|(low, high)| *low <= n && n <= *high) + .any(|range| range.contains(n)) + } +} + +/// The result of formatting, including the formatted text and various +/// errors and warning arose while formatting. +#[derive(Debug, Clone, Default)] +pub struct FormatResult { + original_snippet: Option, + formatted_snippet: FormattedSnippet, + format_errors: HashSet, + newline_style: NewlineStyle, +} + +#[derive(Debug, Clone, Copy)] +struct NonFormattedRange { + lo: usize, + hi: usize, +} + +impl NonFormattedRange { + pub(crate) fn new(lo: usize, hi: usize) -> NonFormattedRange { + NonFormattedRange { lo, hi } + } + + fn shift_up(self) -> NonFormattedRange { + NonFormattedRange { + lo: self.lo - 1, + hi: self.hi - 1, + } + } + + fn contains(&self, line: usize) -> bool { + self.lo <= line && line <= self.hi + } +} + +#[derive(Error, Debug)] +pub enum OperationError { + /// The user mandated a version and the current version of rustfmt does not + /// satisfy that requirement. + #[error("version mismatch")] + VersionMismatch, + /// An io error during reading or writing. + #[error("io error: {0}")] + IoError(io::Error), + /// Invalid glob pattern in `ignore` configuration option. + #[error("invalid glob pattern found in ignore list: {0}")] + InvalidGlobPattern(ignore::Error), + /// Parse error occurred while parsing the input. + #[error("failed to parse {input:?}")] + ParseError { input: FileName, is_panic: bool }, +} + +impl OperationError { + #[cfg(test)] + pub fn is_parse_error(&self) -> bool { + match self { + OperationError::ParseError { .. } => true, + _ => false, + } + } +} + +impl FormatResult { + pub(crate) fn success( + snippet: String, + non_formatted_ranges: Vec, + original_snippet: Option, + newline_style: NewlineStyle, + ) -> Self { + let formatted_snippet = FormattedSnippet { + snippet, + non_formatted_ranges, + }; + FormatResult { + original_snippet, + formatted_snippet, + format_errors: HashSet::new(), + newline_style, + } + } + + pub(crate) fn errors(&self) -> impl Iterator { + self.format_errors + .iter() + .filter(|e| e.kind != ErrorKind::MacroFormatError) } } /// Reports on any issues that occurred during a run of Rustfmt. /// /// Can be reported to the user using the `Display` impl on [`FormatReportFormatter`]. -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct FormatReport { - // Maps stringified file paths to their associated formatting errors. - internal: Rc>, - non_formatted_ranges: Vec<(usize, usize)>, + format_result: Rc>>, + ignored_files: Rc>>, } impl FormatReport { - fn new() -> FormatReport { + pub fn new() -> FormatReport { FormatReport { - internal: Rc::new(RefCell::new((HashMap::new(), ReportedErrors::default()))), - non_formatted_ranges: Vec::new(), + format_result: Rc::new(RefCell::new(BTreeMap::new())), + ignored_files: Rc::new(RefCell::new(BTreeSet::new())), } } - fn add_non_formatted_ranges(&mut self, mut ranges: Vec<(usize, usize)>) { - self.non_formatted_ranges.append(&mut ranges); + pub fn format_result(&self) -> impl Iterator { + Ref::leak(RefCell::borrow(&self.format_result)).iter() } - fn append(&self, f: FileName, mut v: Vec) { - self.track_errors(&v); - self.internal + /// FIXME(topecongiro): reduce visibility. + pub fn merge(&mut self, other: Self) { + self.format_result + .borrow_mut() + .append(&mut other.format_result.borrow_mut()); + self.ignored_files .borrow_mut() - .0 - .entry(f) - .and_modify(|fe| fe.append(&mut v)) - .or_insert(v); + .append(&mut other.ignored_files.borrow_mut()); } - fn track_errors(&self, new_errors: &[FormattingError]) { - let errs = &mut self.internal.borrow_mut().1; - if !new_errors.is_empty() { - errs.has_formatting_errors = true; - } - if errs.has_operational_errors && errs.has_check_errors { - return; + pub(crate) fn add_ignored_file(&self, file_name: FileName) { + self.ignored_files.borrow_mut().insert(file_name); + } + + fn add_format_result(&self, file_name: FileName, format_result: FormatResult) { + let mut format_results = self.format_result.borrow_mut(); + let mut original_format_result = format_results.entry(file_name).or_default(); + original_format_result.formatted_snippet = format_result.formatted_snippet; + original_format_result + .format_errors + .extend(format_result.format_errors); + if original_format_result.original_snippet.is_none() { + original_format_result.original_snippet = format_result.original_snippet; } - for err in new_errors { - match err.kind { - ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace => { - errs.has_operational_errors = true; - } - ErrorKind::LicenseCheck - | ErrorKind::DeprecatedAttr - | ErrorKind::BadAttr - | ErrorKind::VersionMismatch => { - errs.has_check_errors = true; - } - _ => {} - } + } + + fn append_errors(&self, f: FileName, errors: impl Iterator) { + let mut format_result = self.format_result.borrow_mut(); + let format_errors = &mut format_result.entry(f).or_default().format_errors; + for err in errors { + format_errors.insert(err); } } - fn add_diff(&mut self) { - self.internal.borrow_mut().1.has_diff = true; + pub(crate) fn add_macro_format_failure(&self, file_name: FileName) { + self.add_format_error( + file_name, + FormatError::err_without_line_info(ErrorKind::MacroFormatError), + ); } - fn add_macro_format_failure(&mut self) { - self.internal.borrow_mut().1.has_macro_format_failure = true; + pub(crate) fn add_license_failure(&self, file_name: FileName) { + self.add_format_error( + file_name, + FormatError::err_without_line_info(ErrorKind::LicenseCheck), + ); } - fn add_parsing_error(&mut self) { - self.internal.borrow_mut().1.has_parsing_errors = true; + pub(crate) fn add_format_error(&self, file_name: FileName, format_error: FormatError) { + self.format_result + .borrow_mut() + .entry(file_name) + .or_default() + .format_errors + .insert(format_error); + } + + pub fn has_errors(&self) -> bool { + RefCell::borrow(&self.format_result) + .iter() + .any(|(_, format_result)| format_result.errors().count() > 0) } fn warning_count(&self) -> usize { - self.internal - .borrow() - .0 + RefCell::borrow(&self.format_result) .iter() - .map(|(_, errors)| errors.len()) + .map(|(_, format_result)| format_result.errors().count()) .sum() } /// Whether any warnings or errors are present in the report. pub fn has_warnings(&self) -> bool { - self.internal.borrow().1.has_formatting_errors + self.has_errors() } +} + +/// How chatty should Rustfmt be? +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum Verbosity { + /// Default. + Normal, + /// Emit more. + Verbose, + /// Emit as little as possible. + Quiet, +} - /// Print the report to a terminal using colours and potentially other - /// fancy output. - #[deprecated(note = "Use FormatReportFormatter with colors enabled instead")] - pub fn fancy_print( - &self, - mut t: Box>, - ) -> Result<(), term::Error> { - writeln!( - t, - "{}", - FormatReportFormatterBuilder::new(&self) - .enable_colors(true) - .build() - )?; - Ok(()) +impl Default for Verbosity { + fn default() -> Self { + Verbosity::Normal } } -#[deprecated(note = "Use FormatReportFormatter instead")] -impl fmt::Display for FormatReport { - // Prints all the formatting errors. - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - write!(fmt, "{}", FormatReportFormatterBuilder::new(&self).build())?; - Ok(()) +/// Client-preference for coloured output. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum Color { + /// Always use color, whether it is a piped or terminal output + Always, + /// Never use color + Never, + /// Automatically use color, if supported by terminal + Auto, +} + +impl Color { + /// Whether we should use a coloured terminal. + pub fn use_colored_tty(self) -> bool { + match self { + Color::Always | Color::Auto => true, + Color::Never => false, + } } } @@ -272,30 +414,38 @@ impl fmt::Display for FormatReport { /// When we cannot parse the given snippet, this function returns `None`. fn format_snippet(snippet: &str, config: &Config) -> Option { let mut config = config.clone(); - panic::catch_unwind(|| { - let mut out: Vec = Vec::with_capacity(snippet.len() * 2); - config.set().emit_mode(config::EmitMode::Stdout); - config.set().verbose(Verbosity::Quiet); + panic::catch_unwind(move || { config.set().hide_parse_errors(true); - let (formatting_error, result) = { + let result = { let input = Input::Text(snippet.into()); - let mut session = Session::new(config, Some(&mut out)); - let result = session.format(input); - ( - session.errors.has_macro_format_failure - || session.out.as_ref().unwrap().is_empty() && !snippet.is_empty() - || result.is_err(), - result, - ) + let mut session = RustFormatterBuilder::default() + .verbosity(Verbosity::Quiet) + .build(); + session.format(input, &config) }; - if formatting_error { - None - } else { - String::from_utf8(out).ok().map(|snippet| FormattedSnippet { - snippet, - non_formatted_ranges: result.unwrap().non_formatted_ranges, - }) + match result { + Ok(report) if !report.has_errors() => { + match (*report.format_result) + .clone() + .into_inner() + .into_iter() + .next() + { + Some(( + _, + FormatResult { + formatted_snippet, + format_errors, + .. + }, + )) if format_errors.is_empty() && !formatted_snippet.snippet.is_empty() => { + Some(formatted_snippet) + } + _ => None, + } + } + _ => None, } }) // Discard panics encountered while formatting the snippet @@ -391,99 +541,116 @@ fn format_code_block(code_snippet: &str, config: &Config) -> Option { - pub config: Config, - pub out: Option<&'b mut T>, - pub(crate) errors: ReportedErrors, - source_file: SourceFile, - emitter: Box, +#[derive(Default)] +pub struct Session { + /// If set to `true`, format sub-modules which are defined in the given input. + /// Defaults to `false`. + recursive: bool, + verbosity: Verbosity, } -impl<'b, T: Write + 'b> Session<'b, T> { - pub fn new(config: Config, mut out: Option<&'b mut T>) -> Session<'b, T> { - let emitter = create_emitter(&config); - - if let Some(ref mut out) = out { - let _ = emitter.emit_header(out); - } +#[derive(Clone, Copy, Default)] +pub struct RustFormatterBuilder { + /// If set to `true`, format sub-modules which are defined in the given input. + recursive: bool, + verbosity: Verbosity, +} +impl RustFormatterBuilder { + /// Build a new `Session` from the current configuration. + pub fn build(self) -> Session { Session { - config, - out, - emitter, - errors: ReportedErrors::default(), - source_file: SourceFile::new(), + recursive: self.recursive, + verbosity: self.verbosity, } } - /// The main entry point for Rustfmt. Formats the given input according to the - /// given config. `out` is only necessary if required by the configuration. - pub fn format(&mut self, input: Input) -> Result { - self.format_input_inner(input) - } - - pub fn override_config(&mut self, mut config: Config, f: F) -> U - where - F: FnOnce(&mut Session<'b, T>) -> U, - { - mem::swap(&mut config, &mut self.config); - let result = f(self); - mem::swap(&mut config, &mut self.config); - result + pub fn recursive(&mut self, recursive: bool) -> &mut Self { + self.recursive = recursive; + self } - pub fn add_operational_error(&mut self) { - self.errors.has_operational_errors = true; + pub fn verbosity(&mut self, verbosity: Verbosity) -> &mut Self { + self.verbosity = verbosity; + self } +} - pub fn has_operational_errors(&self) -> bool { - self.errors.has_operational_errors +impl Session { + /// The main entry point for Rustfmt. Formats the given input according to the + /// given config. `out` is only necessary if required by the configuration. + pub fn format( + &mut self, + input: Input, + config: &Config, + ) -> Result { + self.format_input_inner(input, config) } +} - pub fn has_parsing_errors(&self) -> bool { - self.errors.has_parsing_errors - } +/// What Rustfmt should emit. Mostly corresponds to the `--emit` command line +/// option. +#[derive(Clone, Copy, Debug)] +pub enum EmitMode { + /// Emits to files. + Files, + /// Writes the output to stdout. + Stdout, + /// Unfancy stdout + Checkstyle, + /// Writes the resulting diffs in a JSON format. Returns an empty array + /// `[]` if there were no diffs. + Json, + /// Output the changed lines (for internal value only) + ModifiedLines, + /// Checks if a diff can be generated. If so, rustfmt outputs a diff and + /// quits with exit code 1. + /// This option is designed to be run in CI where a non-zero exit signifies + /// non-standard code formatting. Used for `--check`. + Diff, +} - pub fn has_formatting_errors(&self) -> bool { - self.errors.has_formatting_errors - } +impl FromStr for EmitMode { + type Err = String; - pub fn has_check_errors(&self) -> bool { - self.errors.has_check_errors + fn from_str(s: &str) -> Result { + match s { + "files" => Ok(EmitMode::Files), + "stdout" => Ok(EmitMode::Stdout), + "checkstyle" => Ok(EmitMode::Checkstyle), + "json" => Ok(EmitMode::Json), + _ => Err(format!("unknown emit mode `{}`", s)), + } } +} - pub fn has_diff(&self) -> bool { - self.errors.has_diff - } +#[derive(Clone, Copy, Debug)] +pub struct EmitterConfig { + pub emit_mode: EmitMode, + pub color: Color, + pub verbosity: Verbosity, + pub print_filename: bool, +} - pub fn has_no_errors(&self) -> bool { - !(self.has_operational_errors() - || self.has_parsing_errors() - || self.has_formatting_errors() - || self.has_check_errors() - || self.has_diff()) - || self.errors.has_macro_format_failure +impl Default for EmitterConfig { + fn default() -> Self { + EmitterConfig { + emit_mode: EmitMode::Files, + color: Color::Auto, + verbosity: Verbosity::Normal, + print_filename: false, + } } } -pub(crate) fn create_emitter<'a>(config: &Config) -> Box { - match config.emit_mode() { - EmitMode::Files => Box::new(emitter::FilesEmitter::new( - config.print_misformatted_file_names(), - )), - EmitMode::Stdout => Box::new(emitter::StdoutEmitter::new(config.verbose())), +pub(crate) fn create_emitter(emitter_config: EmitterConfig) -> Box { + match emitter_config.emit_mode { + EmitMode::Files => Box::new(emitter::FilesEmitter::new(emitter_config)), + EmitMode::Stdout => Box::new(emitter::StdoutEmitter::new(emitter_config)), EmitMode::Json => Box::new(emitter::JsonEmitter::default()), EmitMode::ModifiedLines => Box::new(emitter::ModifiedLinesEmitter::default()), EmitMode::Checkstyle => Box::new(emitter::CheckstyleEmitter::default()), - EmitMode::Diff => Box::new(emitter::DiffEmitter::new(config.clone())), - } -} - -impl<'b, T: Write + 'b> Drop for Session<'b, T> { - fn drop(&mut self) { - if let Some(ref mut out) = self.out { - let _ = self.emitter.emit_footer(out); - } + EmitMode::Diff => Box::new(emitter::DiffEmitter::new(emitter_config)), } } diff --git a/rustfmt-core/rustfmt-lib/src/macros.rs b/rustfmt-core/rustfmt-lib/src/macros.rs index 919c29185d3..82d9bc4567c 100644 --- a/rustfmt-core/rustfmt-lib/src/macros.rs +++ b/rustfmt-core/rustfmt-lib/src/macros.rs @@ -28,7 +28,6 @@ use crate::comment::{ use crate::config::lists::*; use crate::expr::rewrite_array; use crate::lists::{itemize_list, write_list, ListFormatting}; -use crate::overflow; use crate::rewrite::{Rewrite, RewriteContext}; use crate::shape::{Indent, Shape}; use crate::source_map::SpanUtils; @@ -38,6 +37,7 @@ use crate::utils::{ remove_trailing_white_spaces, rewrite_ident, trim_left_preserve_layout, wrap_str, NodeIdExt, }; use crate::visitor::FmtVisitor; +use crate::{overflow, NonFormattedRange}; const FORCED_BRACKET_MACROS: &[&str] = &["vec!"]; @@ -180,10 +180,13 @@ fn return_macro_parse_failure_fallback( return trim_left_preserve_layout(context.snippet(span), indent, &context.config); } - context.skipped_range.borrow_mut().push(( - context.parse_sess.line_of_byte_pos(span.lo()), - context.parse_sess.line_of_byte_pos(span.hi()), - )); + context + .skipped_range + .borrow_mut() + .push(NonFormattedRange::new( + context.parse_sess.line_of_byte_pos(span.lo()), + context.parse_sess.line_of_byte_pos(span.hi()), + )); // Return the snippet unmodified if the macro is not block-like Some(context.snippet(span).to_owned()) diff --git a/rustfmt-core/rustfmt-lib/src/rewrite.rs b/rustfmt-core/rustfmt-lib/src/rewrite.rs index 86b2e9ded1c..6e984fda9b1 100644 --- a/rustfmt-core/rustfmt-lib/src/rewrite.rs +++ b/rustfmt-core/rustfmt-lib/src/rewrite.rs @@ -11,7 +11,7 @@ use crate::shape::Shape; use crate::skip::SkipContext; use crate::syntux::session::ParseSess; use crate::visitor::SnippetProvider; -use crate::FormatReport; +use crate::{FormatReport, NonFormattedRange}; pub(crate) trait Rewrite { /// Rewrite self into shape. @@ -41,7 +41,7 @@ pub(crate) struct RewriteContext<'a> { pub(crate) macro_rewrite_failure: Cell, pub(crate) report: FormatReport, pub(crate) skip_context: SkipContext, - pub(crate) skipped_range: Rc>>, + pub(crate) skipped_range: Rc>>, } pub(crate) struct InsideMacroGuard { diff --git a/rustfmt-core/rustfmt-lib/src/source_file.rs b/rustfmt-core/rustfmt-lib/src/source_file.rs index c60d518b7ae..cb5facfe0dc 100644 --- a/rustfmt-core/rustfmt-lib/src/source_file.rs +++ b/rustfmt-core/rustfmt-lib/src/source_file.rs @@ -4,57 +4,42 @@ use std::path::Path; use std::rc::Rc; use crate::config::FileName; -use crate::syntux::session::ParseSess; -use crate::NewlineStyle; - -#[cfg(test)] -use crate::config::Config; -#[cfg(test)] -use crate::create_emitter; -#[cfg(test)] -use crate::formatting::FileRecord; - use crate::emitter::{self, Emitter}; +use crate::syntux::session::ParseSess; +use crate::{create_emitter, EmitterConfig}; +use crate::{FormatReport, FormatResult, NewlineStyle}; // Append a newline to the end of each file. pub(crate) fn append_newline(s: &mut String) { s.push_str("\n"); } -#[cfg(test)] -pub(crate) fn write_all_files( - source_file: &[FileRecord], +pub fn write_all_files( + format_report: FormatReport, out: &mut T, - config: &Config, -) -> Result<(), io::Error> + config: EmitterConfig, +) -> Result where T: Write, { let mut emitter = create_emitter(config); + let mut has_diff = false; emitter.emit_header(out)?; - for &(ref filename, ref text) in source_file { - write_file( - None, - filename, - text, - out, - &mut *emitter, - config.newline_style(), - )?; + for (filename, format_result) in format_report.format_result.borrow().iter() { + has_diff |= write_file(None, filename, &format_result, out, &mut *emitter)?.has_diff; } emitter.emit_footer(out)?; - Ok(()) + Ok(has_diff) } pub(crate) fn write_file( parse_sess: Option<&ParseSess>, filename: &FileName, - formatted_text: &str, + formatted_result: &FormatResult, out: &mut T, emitter: &mut dyn Emitter, - newline_style: NewlineStyle, ) -> Result where T: Write, @@ -75,19 +60,23 @@ where // left as the default value, then try getting source from the parse session // source map instead of hitting the file system. This also supports getting // original text for `FileName::Stdin`. - let original_text = if newline_style != NewlineStyle::Auto && *filename != FileName::Stdin { - Rc::new(fs::read_to_string(ensure_real_path(filename))?) - } else { - match parse_sess.and_then(|sess| sess.get_original_snippet(filename)) { - Some(ori) => ori, - None => Rc::new(fs::read_to_string(ensure_real_path(filename))?), - } - }; + let original_text = + if formatted_result.newline_style != NewlineStyle::Auto && *filename != FileName::Stdin { + Rc::new(fs::read_to_string(ensure_real_path(filename))?) + } else { + match &formatted_result.original_snippet { + Some(original_snippet) => Rc::new(original_snippet.to_owned()), + None => match parse_sess.and_then(|sess| sess.get_original_snippet(filename)) { + Some(ori) => ori, + None => Rc::new(fs::read_to_string(ensure_real_path(filename))?), + }, + } + }; let formatted_file = emitter::FormattedFile { filename, original_text: original_text.as_str(), - formatted_text, + formatted_text: &formatted_result.formatted_snippet.snippet, }; emitter.emit_formatted_file(out, formatted_file) diff --git a/rustfmt-core/rustfmt-lib/src/syntux/session.rs b/rustfmt-core/rustfmt-lib/src/syntux/session.rs index 00f12b32237..399bac87834 100644 --- a/rustfmt-core/rustfmt-lib/src/syntux/session.rs +++ b/rustfmt-core/rustfmt-lib/src/syntux/session.rs @@ -16,7 +16,7 @@ use crate::ignore_path::IgnorePathSet; use crate::source_map::LineRangeUtils; use crate::utils::starts_with_newline; use crate::visitor::SnippetProvider; -use crate::{Config, ErrorKind, FileName}; +use crate::{Config, FileName, OperationError}; /// ParseSess holds structs necessary for constructing a parser. pub(crate) struct ParseSess { @@ -121,10 +121,10 @@ fn default_handler( } impl ParseSess { - pub(crate) fn new(config: &Config) -> Result { + pub(crate) fn new(config: &Config) -> Result { let ignore_path_set = match IgnorePathSet::from_ignore_list(&config.ignore()) { Ok(ignore_path_set) => Rc::new(ignore_path_set), - Err(e) => return Err(ErrorKind::InvalidGlobPattern(e)), + Err(e) => return Err(OperationError::InvalidGlobPattern(e)), }; let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); let can_reset_errors = Rc::new(RefCell::new(false)); diff --git a/rustfmt-core/rustfmt-lib/src/test/configuration_snippet.rs b/rustfmt-core/rustfmt-lib/src/test/configuration_snippet.rs index b352eb0d20f..44c4dfef92c 100644 --- a/rustfmt-core/rustfmt-lib/src/test/configuration_snippet.rs +++ b/rustfmt-core/rustfmt-lib/src/test/configuration_snippet.rs @@ -1,14 +1,14 @@ use std::collections::{HashMap, HashSet}; use std::fs; -use std::io::{BufRead, BufReader, Write}; +use std::io::{BufRead, BufReader}; use std::iter::Enumerate; use std::path::{Path, PathBuf}; use crate::emitter::rustfmt_diff::{make_diff, Mismatch}; use super::{print_mismatches, write_message, DIFF_CONTEXT_SIZE}; -use crate::config::{Config, EmitMode, Verbosity}; -use crate::{Input, Session}; +use crate::config::Config; +use crate::{Input, RustFormatterBuilder, Verbosity}; const CONFIGURATIONS_FILE_NAME: &str = "../../Configurations.md"; @@ -96,7 +96,6 @@ impl ConfigCodeBlock { fn get_block_config(&self) -> Config { let mut config = Config::default(); - config.set().verbose(Verbosity::Quiet); if self.config_name.is_some() && self.config_value.is_some() { config.override_value( self.config_name.as_ref().unwrap(), @@ -139,19 +138,6 @@ impl ConfigCodeBlock { true } - fn has_parsing_errors(&self, session: &Session<'_, T>) -> bool { - if session.has_parsing_errors() { - write_message(&format!( - "\u{261d}\u{1f3fd} Cannot format {}:{}", - CONFIGURATIONS_FILE_NAME, - self.code_block_start.unwrap() - )); - return true; - } - - false - } - fn print_diff(&self, compare: Vec) { let mut mismatches = HashMap::new(); mismatches.insert(PathBuf::from(CONFIGURATIONS_FILE_NAME), compare); @@ -184,19 +170,25 @@ impl ConfigCodeBlock { } let input = Input::Text(self.code_block.as_ref().unwrap().to_owned()); - let mut config = self.get_block_config(); - config.set().emit_mode(EmitMode::Stdout); - let mut buf: Vec = vec![]; - - { - let mut session = Session::new(config, Some(&mut buf)); - session.format(input).unwrap(); - if self.has_parsing_errors(&session) { - return false; - } + let config = self.get_block_config(); + + let mut session = RustFormatterBuilder::default() + .verbosity(Verbosity::Quiet) + .build(); + let report = session.format(input, &config); + if report.is_err() { + write_message(&format!( + "\u{261d}\u{1f3fd} Cannot format {}:{}", + CONFIGURATIONS_FILE_NAME, + self.code_block_start.unwrap() + )); + return false; } - !self.formatted_has_diff(&String::from_utf8(buf).unwrap()) + let report = report.unwrap(); + let result = report.format_result().next().unwrap(); + let text = &result.1.formatted_snippet.snippet; + !self.formatted_has_diff(text) } // Extract a code block from the iterator. Behavior: diff --git a/rustfmt-core/rustfmt-lib/src/test/mod.rs b/rustfmt-core/rustfmt-lib/src/test/mod.rs index d5af64292bd..0689a215416 100644 --- a/rustfmt-core/rustfmt-lib/src/test/mod.rs +++ b/rustfmt-core/rustfmt-lib/src/test/mod.rs @@ -1,19 +1,17 @@ use std::collections::HashMap; use std::fs; -use std::io::{self, BufRead, BufReader, Read}; +use std::io::{BufRead, BufReader, Read}; use std::iter::Peekable; -use std::mem; use std::path::{Path, PathBuf}; use std::str::Chars; use std::thread; use crate::emitter::rustfmt_diff::{make_diff, print_diff, Mismatch, ModifiedChunk, OutputWriter}; -use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle}; -use crate::formatting::{ReportedErrors, SourceFile}; -use crate::is_nightly_channel; -use crate::source_file; -use crate::{FormatReport, FormatReportFormatterBuilder, Input, Session}; +use crate::config::{Config, FileName, NewlineStyle}; +use crate::{is_nightly_channel, write_all_files, EmitterConfig, OperationError}; +use crate::{source_file, RustFormatterBuilder}; +use crate::{Color, EmitMode, FormatReport, FormatReportFormatterBuilder, Input, Session}; mod configuration_snippet; @@ -217,16 +215,22 @@ fn modified_test() { // Test "modified" output let filename = "tests/writemode/source/modified.rs"; - let mut data = Vec::new(); - let mut config = Config::default(); - config - .set() - .emit_mode(crate::config::EmitMode::ModifiedLines); - - { - let mut session = Session::new(config, Some(&mut data)); - session.format(Input::File(filename.into())).unwrap(); - } + let config = Config::default(); + + let mut session = Session::default(); + let report = session + .format(Input::File(filename.into()), &config) + .unwrap(); + let mut data = vec![]; + write_all_files( + report, + &mut data, + EmitterConfig { + emit_mode: EmitMode::ModifiedLines, + ..EmitterConfig::default() + }, + ) + .unwrap(); let mut lines = data.lines(); let mut chunks = Vec::new(); @@ -271,12 +275,12 @@ fn modified_test() { // Helper function for comparing the results of rustfmt // to a known output file generated by one of the write modes. fn assert_output(source: &Path, expected_filename: &Path) { - let config = read_config(source); - let (_, source_file, _) = format_file(source, config.clone()); + let (config, builder, emitter_config) = read_config(source); + let report = format_file(source, builder, config).unwrap(); // Populate output by writing to a vec. let mut out = vec![]; - let _ = source_file::write_all_files(&source_file, &mut out, &config); + let _ = source_file::write_all_files(report, &mut out, emitter_config); let output = String::from_utf8(out).unwrap(); let mut expected_file = fs::File::open(&expected_filename).expect("couldn't open target"); @@ -304,7 +308,6 @@ fn assert_stdin_output( ) { let mut config = Config::default(); config.set().newline_style(NewlineStyle::Unix); - config.set().emit_mode(emit_mode); let mut source_file = fs::File::open(&source).expect("couldn't open source"); let mut source_text = String::new(); @@ -316,13 +319,18 @@ fn assert_stdin_output( // Populate output by writing to a vec. let mut buf: Vec = vec![]; { - let mut session = Session::new(config, Some(&mut buf)); - session.format(input).unwrap(); - let errors = ReportedErrors { - has_diff: has_diff, - ..Default::default() - }; - assert_eq!(session.errors, errors); + let mut session = Session::default(); + let report = session.format(input, &config).unwrap(); + let format_has_diff = write_all_files( + report, + &mut buf, + EmitterConfig { + emit_mode, + ..EmitterConfig::default() + }, + ) + .unwrap(); + assert_eq!(has_diff, format_has_diff); } let mut expected_file = fs::File::open(&expected_filename).expect("couldn't open target"); @@ -403,14 +411,19 @@ fn self_tests() { fn stdin_formatting_smoke_test() { init_log(); let input = Input::Text("fn main () {}".to_owned()); - let mut config = Config::default(); - config.set().emit_mode(EmitMode::Stdout); + let mut session = RustFormatterBuilder::default().build(); + let report = session.format(input, &Config::default()).unwrap(); + assert!(!report.has_errors()); let mut buf: Vec = vec![]; - { - let mut session = Session::new(config, Some(&mut buf)); - session.format(input).unwrap(); - assert!(session.has_no_errors()); - } + write_all_files( + report, + &mut buf, + EmitterConfig { + emit_mode: EmitMode::Stdout, + ..EmitterConfig::default() + }, + ) + .unwrap(); #[cfg(not(windows))] assert_eq!(buf, b"stdin:\n\nfn main() {}\n"); @@ -423,11 +436,10 @@ fn stdin_parser_panic_caught() { init_log(); // See issue #3239. for text in ["{", "}"].iter().cloned().map(String::from) { - let mut buf = vec![]; - let mut session = Session::new(Default::default(), Some(&mut buf)); - let _ = session.format(Input::Text(text)); + let mut session = Session::default(); + let format_result = session.format(Input::Text(text), &Config::default()); - assert!(session.has_parsing_errors()); + assert!(format_result.err().unwrap().is_parse_error()); } } @@ -442,16 +454,20 @@ fn stdin_works_with_modified_lines() { let input = Input::Text(input.to_owned()); let mut config = Config::default(); config.set().newline_style(NewlineStyle::Unix); - config.set().emit_mode(EmitMode::ModifiedLines); let mut buf: Vec = vec![]; { - let mut session = Session::new(config, Some(&mut buf)); - session.format(input).unwrap(); - let errors = ReportedErrors { - has_diff: true, - ..Default::default() - }; - assert_eq!(session.errors, errors); + let mut session = Session::default(); + let report = session.format(input, &config).unwrap(); + let format_has_diff = write_all_files( + report, + &mut buf, + EmitterConfig { + emit_mode: EmitMode::ModifiedLines, + ..EmitterConfig::default() + }, + ) + .unwrap(); + assert!(format_has_diff); } assert_eq!(buf, output); } @@ -487,9 +503,9 @@ fn format_lines_errors_are_reported() { let input = Input::Text(format!("fn {}() {{}}", long_identifier)); let mut config = Config::default(); config.set().error_on_line_overflow(true); - let mut session = Session::::new(config, None); - session.format(input).unwrap(); - assert!(session.has_formatting_errors()); + let mut session = Session::default(); + let report = session.format(input, &config).unwrap(); + assert!(report.has_errors()); } #[test] @@ -500,9 +516,9 @@ fn format_lines_errors_are_reported_with_tabs() { let mut config = Config::default(); config.set().error_on_line_overflow(true); config.set().hard_tabs(true); - let mut session = Session::::new(config, None); - session.format(input).unwrap(); - assert!(session.has_formatting_errors()); + let mut session = Session::default(); + let report = session.format(input, &config).unwrap(); + assert!(report.has_errors()); } // For each file, run rustfmt and collect the output. @@ -549,7 +565,12 @@ fn print_mismatches_default_message(result: HashMap>) { for (file_name, diff) in result { let mismatch_msg_formatter = |line_num| format!("\nMismatch at {}:{}:", file_name.display(), line_num); - print_diff(diff, &mismatch_msg_formatter, &Default::default()); + print_diff( + diff, + &mismatch_msg_formatter, + Color::Auto, + Default::default(), + ); } if let Some(mut t) = term::stdout() { @@ -562,7 +583,12 @@ fn print_mismatches String>( mismatch_msg_formatter: T, ) { for (_file_name, diff) in result { - print_diff(diff, &mismatch_msg_formatter, &Default::default()); + print_diff( + diff, + &mismatch_msg_formatter, + Color::Auto, + Default::default(), + ); } if let Some(mut t) = term::stdout() { @@ -570,7 +596,7 @@ fn print_mismatches String>( } } -fn read_config(filename: &Path) -> Config { +fn read_config(filename: &Path) -> (Config, RustFormatterBuilder, EmitterConfig) { let sig_comments = read_significant_comments(filename); // Look for a config file. If there is a 'config' property in the significant comments, use // that. Otherwise, if there are no significant comments at all, look for a config file with @@ -581,8 +607,14 @@ fn read_config(filename: &Path) -> Config { get_config(filename.with_extension("toml").file_name().map(Path::new)) }; + let mut rustfmt_builder = RustFormatterBuilder::default(); + let mut emitter_config = EmitterConfig::default(); for (key, val) in &sig_comments { - if key != "target" && key != "config" && key != "unstable" { + if key == "recursive" { + rustfmt_builder.recursive(val.parse::().unwrap()); + } else if key == "emit_mode" { + emitter_config.emit_mode = val.parse::().unwrap() + } else if key != "target" && key != "config" && key != "unstable" { config.override_value(key, val); if config.is_default(key) { warn!("Default value {} used explicitly for {}", val, key); @@ -590,18 +622,18 @@ fn read_config(filename: &Path) -> Config { } } - config + (config, rustfmt_builder, emitter_config) } -fn format_file>(filepath: P, config: Config) -> (bool, SourceFile, FormatReport) { +fn format_file>( + filepath: P, + rustfmt_builder: RustFormatterBuilder, + config: Config, +) -> Result { let filepath = filepath.into(); let input = Input::File(filepath); - let mut session = Session::::new(config, None); - let result = session.format(input).unwrap(); - let parsing_errors = session.has_parsing_errors(); - let mut source_file = SourceFile::new(); - mem::swap(&mut session.source_file, &mut source_file); - (parsing_errors, source_file, result) + let mut session = rustfmt_builder.build(); + session.format(input, &config) } enum IdempotentCheckError { @@ -614,20 +646,23 @@ fn idempotent_check( opt_config: &Option, ) -> Result { let sig_comments = read_significant_comments(filename); - let config = if let Some(ref config_file_path) = opt_config { - Config::from_toml_path(config_file_path).expect("`rustfmt.toml` not found") + let (config, builder, _) = if let Some(ref config_file_path) = opt_config { + let config = Config::from_toml_path(config_file_path).expect("`rustfmt.toml` not found"); + let builder = RustFormatterBuilder::default(); + let emitter_config = EmitterConfig::default(); + (config, builder, emitter_config) } else { read_config(filename) }; - let (parsing_errors, source_file, format_report) = format_file(filename, config); - if parsing_errors { - return Err(IdempotentCheckError::Parse); - } + let format_report = match format_file(filename, builder, config) { + Ok(report) => report, + Err(_) => return Err(IdempotentCheckError::Parse), + }; let mut write_result = HashMap::new(); - for (filename, text) in source_file { + for (filename, text) in format_report.format_result() { if let FileName::Real(ref filename) = filename { - write_result.insert(filename.to_owned(), text); + write_result.insert(filename.to_owned(), text.formatted_snippet.snippet.clone()); } } diff --git a/rustfmt-core/rustfmt-lib/src/visitor.rs b/rustfmt-core/rustfmt-lib/src/visitor.rs index daf96ac34f8..3e7f21ea2f0 100644 --- a/rustfmt-core/rustfmt-lib/src/visitor.rs +++ b/rustfmt-core/rustfmt-lib/src/visitor.rs @@ -25,7 +25,7 @@ use crate::utils::{ last_line_contains_single_line_comment, last_line_width, mk_sp, ptr_vec_to_ref_vec, rewrite_ident, stmt_expr, }; -use crate::{ErrorKind, FormatReport, FormattingError}; +use crate::{ErrorKind, FormatError, FormatReport, NonFormattedRange}; /// Creates a string slice corresponding to the specified span. pub(crate) struct SnippetProvider { @@ -82,7 +82,7 @@ pub(crate) struct FmtVisitor<'a> { pub(crate) line_number: usize, /// List of 1-based line ranges which were annotated with skip /// Both bounds are inclusifs. - pub(crate) skipped_range: Rc>>, + pub(crate) skipped_range: Rc>>, pub(crate) macro_rewrite_failure: bool, pub(crate) report: FormatReport, pub(crate) skip_context: SkipContext, @@ -757,7 +757,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let lo = std::cmp::min(attrs_end + 1, first_line); self.push_rewrite_inner(item_span, None); let hi = self.line_number + 1; - self.skipped_range.borrow_mut().push((lo, hi)); + self.skipped_range + .borrow_mut() + .push(NonFormattedRange::new(lo, hi)); } pub(crate) fn from_context(ctx: &'a RewriteContext<'_>) -> FmtVisitor<'a> { @@ -812,13 +814,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { for attr in attrs { if attr.check_name(depr_skip_annotation()) { let file_name = self.parse_sess.span_to_filename(attr.span); - self.report.append( + self.report.add_format_error( file_name, - vec![FormattingError::from_span( - attr.span, - self.parse_sess, - ErrorKind::DeprecatedAttr, - )], + FormatError::from_span(ErrorKind::DeprecatedAttr, self.parse_sess, attr.span), ); } else { match &attr.kind { @@ -826,13 +824,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { if self.is_unknown_rustfmt_attr(&attribute_item.path.segments) => { let file_name = self.parse_sess.span_to_filename(attr.span); - self.report.append( + self.report.add_format_error( file_name, - vec![FormattingError::from_span( - attr.span, - self.parse_sess, - ErrorKind::BadAttr, - )], + FormatError::from_span(ErrorKind::BadAttr, self.parse_sess, attr.span), ); } _ => (), diff --git a/rustfmt-core/rustfmt-lib/tests/config/issue-3933.toml b/rustfmt-core/rustfmt-lib/tests/config/issue-3933.toml index 68c54af39b9..255ab6b2d2c 100644 --- a/rustfmt-core/rustfmt-lib/tests/config/issue-3933.toml +++ b/rustfmt-core/rustfmt-lib/tests/config/issue-3933.toml @@ -3,4 +3,3 @@ ignore = [ "tests/**/issue-3933/imp-b.rs", "tests/**/issue-3933/utils.rs" ] -recursive = true diff --git a/rustfmt-core/rustfmt-lib/tests/config/issue-3956.toml b/rustfmt-core/rustfmt-lib/tests/config/issue-3956.toml index 7669890586b..1679a39e3b7 100644 --- a/rustfmt-core/rustfmt-lib/tests/config/issue-3956.toml +++ b/rustfmt-core/rustfmt-lib/tests/config/issue-3956.toml @@ -2,4 +2,3 @@ ignore = [ "tests/**/issue-3956/graphics.rs", "tests/**/issue-3956/graphics_emu.rs" ] -recursive = true diff --git a/rustfmt-core/rustfmt-lib/tests/source/issue-3933/lib.rs b/rustfmt-core/rustfmt-lib/tests/source/issue-3933/lib.rs index a2b9aa01e11..e7924fe9754 100644 --- a/rustfmt-core/rustfmt-lib/tests/source/issue-3933/lib.rs +++ b/rustfmt-core/rustfmt-lib/tests/source/issue-3933/lib.rs @@ -1,4 +1,5 @@ // rustfmt-config: issue-3933.toml +// rustfmt-recursive: true #[cfg_attr(windows, path = "imp-a.rs" )] #[cfg_attr(not(windows), path = "imp-b.rs")] mod imp; diff --git a/rustfmt-core/rustfmt-lib/tests/target/issue-3933/lib.rs b/rustfmt-core/rustfmt-lib/tests/target/issue-3933/lib.rs index 65800485217..2fd53d5685e 100644 --- a/rustfmt-core/rustfmt-lib/tests/target/issue-3933/lib.rs +++ b/rustfmt-core/rustfmt-lib/tests/target/issue-3933/lib.rs @@ -1,4 +1,5 @@ // rustfmt-config: issue-3933.toml +// rustfmt-recursive: true #[cfg_attr(windows, path = "imp-a.rs")] #[cfg_attr(not(windows), path = "imp-b.rs")] mod imp; diff --git a/rustfmt-core/rustfmt-lib/tests/target/issue-3956/lib.rs b/rustfmt-core/rustfmt-lib/tests/target/issue-3956/lib.rs index b0a26c9f0ba..1714995a6be 100644 --- a/rustfmt-core/rustfmt-lib/tests/target/issue-3956/lib.rs +++ b/rustfmt-core/rustfmt-lib/tests/target/issue-3956/lib.rs @@ -1,4 +1,5 @@ // rustfmt-config: issue-3956.toml +// rustfmt-recursive: true #[cfg_attr(windows, path = "graphics.rs")] #[cfg_attr(not(windows), path = "graphics_emu.rs")] mod graphics; From 9a79fcafd561c766788c328e62bce55eafaca450 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 7 May 2020 22:17:17 +0900 Subject: [PATCH 30/59] Rename --- rustfmt-core/rustfmt-bin/src/bin/main.rs | 10 +- .../rustfmt-bin/src/git-rustfmt/main.rs | 6 +- rustfmt-core/rustfmt-lib/src/emitter.rs | 196 +++++++++++++++++- .../rustfmt-lib/src/emitter/checkstyle.rs | 13 +- rustfmt-core/rustfmt-lib/src/emitter/diff.rs | 4 +- rustfmt-core/rustfmt-lib/src/emitter/files.rs | 9 +- rustfmt-core/rustfmt-lib/src/emitter/json.rs | 11 +- .../rustfmt-lib/src/emitter/modified_lines.rs | 2 +- .../rustfmt-lib/src/emitter/stdout.rs | 4 +- rustfmt-core/rustfmt-lib/src/formatting.rs | 6 +- rustfmt-core/rustfmt-lib/src/lib.rs | 130 +----------- rustfmt-core/rustfmt-lib/src/source_file.rs | 83 -------- rustfmt-core/rustfmt-lib/src/test/mod.rs | 18 +- 13 files changed, 242 insertions(+), 250 deletions(-) delete mode 100644 rustfmt-core/rustfmt-lib/src/source_file.rs diff --git a/rustfmt-core/rustfmt-bin/src/bin/main.rs b/rustfmt-core/rustfmt-bin/src/bin/main.rs index 7f9b65664a9..b0776c4d819 100644 --- a/rustfmt-core/rustfmt-bin/src/bin/main.rs +++ b/rustfmt-core/rustfmt-bin/src/bin/main.rs @@ -14,9 +14,9 @@ use structopt::StructOpt; use thiserror::Error; use rustfmt_lib::{ - load_config, write_all_files, CliOptions, Config, Edition, EmitMode, EmitterConfig, FileLines, - FileName, FormatReport, FormatReportFormatterBuilder, Input, RustFormatterBuilder, Session, - Verbosity, + emitter::{emit_format_report, EmitMode, EmitterConfig, Verbosity}, + load_config, CliOptions, Config, Edition, FileLines, FileName, FormatReport, + FormatReportFormatterBuilder, Input, RustFormatterBuilder, Session, }; fn main() { @@ -426,7 +426,7 @@ fn format_string(input: String, opt: Opt) -> Result { &config, &mut format_report, ); - let has_diff = write_all_files(format_report, out, opt.emitter_config(EmitMode::Stdout))?; + let has_diff = emit_format_report(format_report, out, opt.emitter_config(EmitMode::Stdout))?; Ok(if opt.check && has_diff { 1 } else { 0 }) } @@ -544,7 +544,7 @@ fn format(opt: Opt) -> Result { } let out = &mut stdout(); - let has_diff = write_all_files(format_report, out, opt.emitter_config(EmitMode::Files))?; + let has_diff = emit_format_report(format_report, out, opt.emitter_config(EmitMode::Files))?; Ok(if opt.check && has_diff { 1 } else { 0 }) } diff --git a/rustfmt-core/rustfmt-bin/src/git-rustfmt/main.rs b/rustfmt-core/rustfmt-bin/src/git-rustfmt/main.rs index 495db9679a5..1c7e3f6f5b9 100644 --- a/rustfmt-core/rustfmt-bin/src/git-rustfmt/main.rs +++ b/rustfmt-core/rustfmt-bin/src/git-rustfmt/main.rs @@ -8,8 +8,8 @@ use std::process::Command; use structopt::StructOpt; use rustfmt_lib::{ - load_config, write_all_files, CliOptions, EmitterConfig, FormatReportFormatterBuilder, Input, - Session, + emitter::{emit_format_report, EmitterConfig}, + load_config, CliOptions, FormatReportFormatterBuilder, Input, Session, }; fn prune_files(files: Vec<&str>) -> Vec<&str> { @@ -69,7 +69,7 @@ fn fmt_files(files: &[&str]) -> i32 { if report.has_warnings() { eprintln!("{}", FormatReportFormatterBuilder::new(&report).build()); } - write_all_files(report, &mut out, EmitterConfig::default()).unwrap(); + emit_format_report(report, &mut out, EmitterConfig::default()).unwrap(); } todo!("Fix error handling") diff --git a/rustfmt-core/rustfmt-lib/src/emitter.rs b/rustfmt-core/rustfmt-lib/src/emitter.rs index cc835d344b6..12334d2edd4 100644 --- a/rustfmt-core/rustfmt-lib/src/emitter.rs +++ b/rustfmt-core/rustfmt-lib/src/emitter.rs @@ -5,10 +5,15 @@ pub use self::json::*; pub use self::modified_lines::*; pub use self::stdout::*; +use std::fs; use std::io::{self, Write}; use std::path::Path; +use std::rc::Rc; -use crate::config::FileName; +use thiserror::Error; + +use crate::syntux::session::ParseSess; +use crate::{config::FileName, FormatReport, FormatResult, NewlineStyle}; pub mod checkstyle; pub mod diff; @@ -29,25 +34,200 @@ pub struct EmitterResult { pub has_diff: bool, } +#[derive(Debug, Error)] +pub enum EmitterError { + #[error("{0}")] + IoError(#[from] io::Error), + #[error("{0}")] + JsonError(#[from] serde_json::Error), + #[error("invalid input for EmitMode::Files")] + InvalidInputForFiles, +} + pub trait Emitter { fn emit_formatted_file( &mut self, output: &mut dyn Write, formatted_file: FormattedFile<'_>, - ) -> Result; + ) -> Result; - fn emit_header(&self, _output: &mut dyn Write) -> Result<(), io::Error> { + fn emit_header(&self, _output: &mut dyn Write) -> Result<(), EmitterError> { Ok(()) } - fn emit_footer(&self, _output: &mut dyn Write) -> Result<(), io::Error> { + fn emit_footer(&self, _output: &mut dyn Write) -> Result<(), EmitterError> { Ok(()) } } -fn ensure_real_path(filename: &FileName) -> &Path { - match *filename { - FileName::Real(ref path) => path, - _ => panic!("cannot format `{}` and emit to files", filename), +/// What Rustfmt should emit. Mostly corresponds to the `--emit` command line +/// option. +#[derive(Clone, Copy, Debug)] +pub enum EmitMode { + /// Emits to files. + Files, + /// Writes the output to stdout. + Stdout, + /// Unfancy stdout + Checkstyle, + /// Writes the resulting diffs in a JSON format. Returns an empty array + /// `[]` if there were no diffs. + Json, + /// Output the changed lines (for internal value only) + ModifiedLines, + /// Checks if a diff can be generated. If so, rustfmt outputs a diff and + /// quits with exit code 1. + /// This option is designed to be run in CI where a non-zero exit signifies + /// non-standard code formatting. Used for `--check`. + Diff, +} + +/// Client-preference for coloured output. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum Color { + /// Always use color, whether it is a piped or terminal output + Always, + /// Never use color + Never, + /// Automatically use color, if supported by terminal + Auto, +} + +impl Color { + /// Whether we should use a coloured terminal. + pub fn use_colored_tty(self) -> bool { + match self { + Color::Always | Color::Auto => true, + Color::Never => false, + } + } +} + +/// How chatty should Rustfmt be? +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum Verbosity { + /// Default. + Normal, + /// Emit more. + Verbose, + /// Emit as little as possible. + Quiet, +} + +impl Default for Verbosity { + fn default() -> Self { + Verbosity::Normal + } +} + +impl std::str::FromStr for EmitMode { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "files" => Ok(EmitMode::Files), + "stdout" => Ok(EmitMode::Stdout), + "checkstyle" => Ok(EmitMode::Checkstyle), + "json" => Ok(EmitMode::Json), + _ => Err(format!("unknown emit mode `{}`", s)), + } + } +} + +#[derive(Clone, Copy, Debug)] +pub struct EmitterConfig { + pub emit_mode: EmitMode, + pub color: Color, + pub verbosity: Verbosity, + pub print_filename: bool, +} + +impl Default for EmitterConfig { + fn default() -> Self { + EmitterConfig { + emit_mode: EmitMode::Files, + color: Color::Auto, + verbosity: Verbosity::Normal, + print_filename: false, + } + } +} + +pub fn emit_format_report( + format_report: FormatReport, + out: &mut T, + config: EmitterConfig, +) -> Result +where + T: Write, +{ + let mut emitter = create_emitter(config); + let mut has_diff = false; + + emitter.emit_header(out)?; + for (filename, format_result) in format_report.format_result.borrow().iter() { + has_diff |= write_file(None, filename, &format_result, out, &mut *emitter)?.has_diff; + } + emitter.emit_footer(out)?; + + Ok(has_diff) +} + +pub(crate) fn write_file( + parse_sess: Option<&ParseSess>, + filename: &FileName, + formatted_result: &FormatResult, + out: &mut T, + emitter: &mut dyn Emitter, +) -> Result +where + T: Write, +{ + fn ensure_real_path(filename: &FileName) -> &Path { + match *filename { + FileName::Real(ref path) => path, + _ => panic!("cannot format `{}` and emit to files", filename), + } + } + + // SourceFile's in the SourceMap will always have Unix-style line endings + // See: https://github.com/rust-lang/rustfmt/issues/3850 + // So if the user has explicitly overridden the rustfmt `newline_style` + // config and `filename` is FileName::Real, then we must check the file system + // to get the original file value in order to detect newline_style conflicts. + // Otherwise, parse session is around (cfg(not(test))) and newline_style has been + // left as the default value, then try getting source from the parse session + // source map instead of hitting the file system. This also supports getting + // original text for `FileName::Stdin`. + let original_text = + if formatted_result.newline_style != NewlineStyle::Auto && *filename != FileName::Stdin { + Rc::new(fs::read_to_string(ensure_real_path(filename))?) + } else { + match &formatted_result.original_snippet { + Some(original_snippet) => Rc::new(original_snippet.to_owned()), + None => match parse_sess.and_then(|sess| sess.get_original_snippet(filename)) { + Some(ori) => ori, + None => Rc::new(fs::read_to_string(ensure_real_path(filename))?), + }, + } + }; + + let formatted_file = FormattedFile { + filename, + original_text: original_text.as_str(), + formatted_text: &formatted_result.formatted_snippet.snippet, + }; + + emitter.emit_formatted_file(out, formatted_file) +} + +fn create_emitter(emitter_config: EmitterConfig) -> Box { + match emitter_config.emit_mode { + EmitMode::Files => Box::new(FilesEmitter::new(emitter_config)), + EmitMode::Stdout => Box::new(StdoutEmitter::new(emitter_config)), + EmitMode::Json => Box::new(JsonEmitter::default()), + EmitMode::ModifiedLines => Box::new(ModifiedLinesEmitter::default()), + EmitMode::Checkstyle => Box::new(CheckstyleEmitter::default()), + EmitMode::Diff => Box::new(DiffEmitter::new(emitter_config)), } } diff --git a/rustfmt-core/rustfmt-lib/src/emitter/checkstyle.rs b/rustfmt-core/rustfmt-lib/src/emitter/checkstyle.rs index b0f9d50f661..c686580ed0a 100644 --- a/rustfmt-core/rustfmt-lib/src/emitter/checkstyle.rs +++ b/rustfmt-core/rustfmt-lib/src/emitter/checkstyle.rs @@ -1,7 +1,7 @@ use self::xml::XmlEscaped; use super::*; use rustfmt_diff::{make_diff, DiffLine, Mismatch}; -use std::io::{self, Write}; +use std::io::Write; mod xml; @@ -9,14 +9,15 @@ mod xml; pub struct CheckstyleEmitter; impl Emitter for CheckstyleEmitter { - fn emit_header(&self, output: &mut dyn Write) -> Result<(), io::Error> { + fn emit_header(&self, output: &mut dyn Write) -> Result<(), EmitterError> { writeln!(output, r#""#)?; write!(output, r#""#)?; Ok(()) } - fn emit_footer(&self, output: &mut dyn Write) -> Result<(), io::Error> { - writeln!(output, "") + fn emit_footer(&self, output: &mut dyn Write) -> Result<(), EmitterError> { + writeln!(output, "")?; + Ok(()) } fn emit_formatted_file( @@ -27,7 +28,7 @@ impl Emitter for CheckstyleEmitter { original_text, formatted_text, }: FormattedFile<'_>, - ) -> Result { + ) -> Result { const CONTEXT_SIZE: usize = 0; let diff = make_diff(original_text, formatted_text, CONTEXT_SIZE); output_checkstyle_file(output, filename, diff)?; @@ -39,7 +40,7 @@ pub fn output_checkstyle_file( mut writer: T, filename: &FileName, diff: Vec, -) -> Result<(), io::Error> +) -> Result<(), EmitterError> where T: Write, { diff --git a/rustfmt-core/rustfmt-lib/src/emitter/diff.rs b/rustfmt-core/rustfmt-lib/src/emitter/diff.rs index 4f72211bdc0..995e18b9c22 100644 --- a/rustfmt-core/rustfmt-lib/src/emitter/diff.rs +++ b/rustfmt-core/rustfmt-lib/src/emitter/diff.rs @@ -1,5 +1,5 @@ use super::*; -use crate::{Color, EmitterConfig, Verbosity}; +use crate::emitter::{Color, EmitterConfig, Verbosity}; use rustfmt_diff::{make_diff, print_diff}; pub struct DiffEmitter { @@ -34,7 +34,7 @@ impl Emitter for DiffEmitter { original_text, formatted_text, }: FormattedFile<'_>, - ) -> Result { + ) -> Result { const CONTEXT_SIZE: usize = 3; let mismatch = make_diff(&original_text, formatted_text, CONTEXT_SIZE); let has_diff = !mismatch.is_empty(); diff --git a/rustfmt-core/rustfmt-lib/src/emitter/files.rs b/rustfmt-core/rustfmt-lib/src/emitter/files.rs index 6106c742e6a..660059ae0a1 100644 --- a/rustfmt-core/rustfmt-lib/src/emitter/files.rs +++ b/rustfmt-core/rustfmt-lib/src/emitter/files.rs @@ -1,5 +1,5 @@ use super::*; -use crate::EmitterConfig; +use crate::emitter::EmitterConfig; use std::fs; #[derive(Debug, Default)] @@ -24,9 +24,12 @@ impl Emitter for FilesEmitter { original_text, formatted_text, }: FormattedFile<'_>, - ) -> Result { + ) -> Result { // Write text directly over original file if there is a diff. - let filename = ensure_real_path(filename); + let filename = match filename { + FileName::Stdin => return Err(EmitterError::InvalidInputForFiles), + FileName::Real(path_buf) => path_buf, + }; if original_text != formatted_text { fs::write(filename, formatted_text)?; if self.print_misformatted_file_names { diff --git a/rustfmt-core/rustfmt-lib/src/emitter/json.rs b/rustfmt-core/rustfmt-lib/src/emitter/json.rs index 7512be1a8b7..c77f2995489 100644 --- a/rustfmt-core/rustfmt-lib/src/emitter/json.rs +++ b/rustfmt-core/rustfmt-lib/src/emitter/json.rs @@ -1,4 +1,4 @@ -use std::io::{self, Write}; +use std::io::Write; use super::*; use rustfmt_diff::{make_diff, DiffLine, Mismatch}; @@ -27,8 +27,9 @@ struct MismatchedFile { } impl Emitter for JsonEmitter { - fn emit_footer(&self, output: &mut dyn Write) -> Result<(), io::Error> { - writeln!(output, "{}", &to_json_string(&self.mismatched_files)?) + fn emit_footer(&self, output: &mut dyn Write) -> Result<(), EmitterError> { + writeln!(output, "{}", &to_json_string(&self.mismatched_files)?)?; + Ok(()) } fn emit_formatted_file( @@ -39,7 +40,7 @@ impl Emitter for JsonEmitter { original_text, formatted_text, }: FormattedFile<'_>, - ) -> Result { + ) -> Result { const CONTEXT_SIZE: usize = 0; let diff = make_diff(original_text, formatted_text, CONTEXT_SIZE); let has_diff = !diff.is_empty(); @@ -57,7 +58,7 @@ impl JsonEmitter { &mut self, filename: &FileName, diff: Vec, - ) -> Result<(), io::Error> { + ) -> Result<(), EmitterError> { let mut mismatches = vec![]; for mismatch in diff { let original_begin_line = mismatch.line_number_orig; diff --git a/rustfmt-core/rustfmt-lib/src/emitter/modified_lines.rs b/rustfmt-core/rustfmt-lib/src/emitter/modified_lines.rs index 76a6f7434f5..70be0bcd193 100644 --- a/rustfmt-core/rustfmt-lib/src/emitter/modified_lines.rs +++ b/rustfmt-core/rustfmt-lib/src/emitter/modified_lines.rs @@ -13,7 +13,7 @@ impl Emitter for ModifiedLinesEmitter { formatted_text, .. }: FormattedFile<'_>, - ) -> Result { + ) -> Result { const CONTEXT_SIZE: usize = 0; let mismatch = make_diff(original_text, formatted_text, CONTEXT_SIZE); let has_diff = !mismatch.is_empty(); diff --git a/rustfmt-core/rustfmt-lib/src/emitter/stdout.rs b/rustfmt-core/rustfmt-lib/src/emitter/stdout.rs index 1673b9537b3..e2cd1fd19bb 100644 --- a/rustfmt-core/rustfmt-lib/src/emitter/stdout.rs +++ b/rustfmt-core/rustfmt-lib/src/emitter/stdout.rs @@ -1,7 +1,7 @@ use std::io::Write; use super::*; -use crate::{EmitterConfig, Verbosity}; +use crate::emitter::{EmitterConfig, Verbosity}; #[derive(Debug)] pub struct StdoutEmitter { @@ -25,7 +25,7 @@ impl Emitter for StdoutEmitter { formatted_text, .. }: FormattedFile<'_>, - ) -> Result { + ) -> Result { if self.verbosity != Verbosity::Quiet { writeln!(output, "{}:\n", filename)?; } diff --git a/rustfmt-core/rustfmt-lib/src/formatting.rs b/rustfmt-core/rustfmt-lib/src/formatting.rs index e2f3fa4a3b4..f24b1a338db 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting.rs @@ -13,8 +13,8 @@ use crate::syntux::session::ParseSess; use crate::utils::count_newlines; use crate::visitor::FmtVisitor; use crate::{ - modules, source_file, ErrorKind, FormatError, FormatReport, FormatResult, Input, - NonFormattedRange, OperationError, Session, Verbosity, + modules, ErrorKind, FormatError, FormatReport, FormatResult, Input, NonFormattedRange, + OperationError, Session, Verbosity, }; mod newline_style; @@ -157,7 +157,7 @@ impl Session { // For some reason, the source_map does not include terminating // newlines so we must add one on for each file. This is sad. - source_file::append_newline(&mut visitor.buffer); + visitor.buffer.push('\n'); format_lines( &mut visitor.buffer, diff --git a/rustfmt-core/rustfmt-lib/src/lib.rs b/rustfmt-core/rustfmt-lib/src/lib.rs index c3e2043d010..fd9e32af158 100644 --- a/rustfmt-core/rustfmt-lib/src/lib.rs +++ b/rustfmt-core/rustfmt-lib/src/lib.rs @@ -9,7 +9,6 @@ extern crate log; use std::cell::{Ref, RefCell}; use std::collections::{BTreeMap, BTreeSet, HashSet}; -use std::fmt; use std::io; use std::panic; use std::path::PathBuf; @@ -24,15 +23,15 @@ pub use crate::config::{ }; pub use crate::emitter::rustfmt_diff::{ModifiedChunk, ModifiedLines}; pub use crate::format_report_formatter::{FormatReportFormatter, FormatReportFormatterBuilder}; -pub use crate::source_file::write_all_files; -use crate::comment::LineClasses; -use crate::emitter::Emitter; -use crate::shape::Indent; -use crate::syntux::parser::DirectoryOwnership; -use crate::syntux::session::ParseSess; -use crate::utils::indent_next_line; -use std::str::FromStr; +use crate::{ + comment::LineClasses, + emitter::{Color, Verbosity}, + shape::Indent, + syntux::parser::DirectoryOwnership, + syntux::session::ParseSess, + utils::indent_next_line, +}; #[macro_use] mod utils; @@ -65,7 +64,6 @@ mod reorder; mod rewrite; mod shape; mod skip; -pub(crate) mod source_file; pub(crate) mod source_map; mod spanned; mod stmt; @@ -104,19 +102,13 @@ pub enum ErrorKind { } #[derive(Error, Clone, Debug, Hash, Eq, PartialEq)] +#[error("{kind}")] pub struct FormatError { - #[error(transparent)] kind: ErrorKind, line_num: Option, line_str: Option, } -impl fmt::Display for FormatError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.kind.fmt(f) - } -} - impl FormatError { pub(crate) fn new(kind: ErrorKind, line_num: usize, line_str: String) -> Self { FormatError { @@ -372,44 +364,6 @@ impl FormatReport { } } -/// How chatty should Rustfmt be? -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum Verbosity { - /// Default. - Normal, - /// Emit more. - Verbose, - /// Emit as little as possible. - Quiet, -} - -impl Default for Verbosity { - fn default() -> Self { - Verbosity::Normal - } -} - -/// Client-preference for coloured output. -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum Color { - /// Always use color, whether it is a piped or terminal output - Always, - /// Never use color - Never, - /// Automatically use color, if supported by terminal - Auto, -} - -impl Color { - /// Whether we should use a coloured terminal. - pub fn use_colored_tty(self) -> bool { - match self { - Color::Always | Color::Auto => true, - Color::Never => false, - } - } -} - /// Format the given snippet. The snippet is expected to be *complete* code. /// When we cannot parse the given snippet, this function returns `None`. fn format_snippet(snippet: &str, config: &Config) -> Option { @@ -588,72 +542,6 @@ impl Session { } } -/// What Rustfmt should emit. Mostly corresponds to the `--emit` command line -/// option. -#[derive(Clone, Copy, Debug)] -pub enum EmitMode { - /// Emits to files. - Files, - /// Writes the output to stdout. - Stdout, - /// Unfancy stdout - Checkstyle, - /// Writes the resulting diffs in a JSON format. Returns an empty array - /// `[]` if there were no diffs. - Json, - /// Output the changed lines (for internal value only) - ModifiedLines, - /// Checks if a diff can be generated. If so, rustfmt outputs a diff and - /// quits with exit code 1. - /// This option is designed to be run in CI where a non-zero exit signifies - /// non-standard code formatting. Used for `--check`. - Diff, -} - -impl FromStr for EmitMode { - type Err = String; - - fn from_str(s: &str) -> Result { - match s { - "files" => Ok(EmitMode::Files), - "stdout" => Ok(EmitMode::Stdout), - "checkstyle" => Ok(EmitMode::Checkstyle), - "json" => Ok(EmitMode::Json), - _ => Err(format!("unknown emit mode `{}`", s)), - } - } -} - -#[derive(Clone, Copy, Debug)] -pub struct EmitterConfig { - pub emit_mode: EmitMode, - pub color: Color, - pub verbosity: Verbosity, - pub print_filename: bool, -} - -impl Default for EmitterConfig { - fn default() -> Self { - EmitterConfig { - emit_mode: EmitMode::Files, - color: Color::Auto, - verbosity: Verbosity::Normal, - print_filename: false, - } - } -} - -pub(crate) fn create_emitter(emitter_config: EmitterConfig) -> Box { - match emitter_config.emit_mode { - EmitMode::Files => Box::new(emitter::FilesEmitter::new(emitter_config)), - EmitMode::Stdout => Box::new(emitter::StdoutEmitter::new(emitter_config)), - EmitMode::Json => Box::new(emitter::JsonEmitter::default()), - EmitMode::ModifiedLines => Box::new(emitter::ModifiedLinesEmitter::default()), - EmitMode::Checkstyle => Box::new(emitter::CheckstyleEmitter::default()), - EmitMode::Diff => Box::new(emitter::DiffEmitter::new(emitter_config)), - } -} - #[derive(Debug)] pub enum Input { File(PathBuf), diff --git a/rustfmt-core/rustfmt-lib/src/source_file.rs b/rustfmt-core/rustfmt-lib/src/source_file.rs deleted file mode 100644 index cb5facfe0dc..00000000000 --- a/rustfmt-core/rustfmt-lib/src/source_file.rs +++ /dev/null @@ -1,83 +0,0 @@ -use std::fs; -use std::io::{self, Write}; -use std::path::Path; -use std::rc::Rc; - -use crate::config::FileName; -use crate::emitter::{self, Emitter}; -use crate::syntux::session::ParseSess; -use crate::{create_emitter, EmitterConfig}; -use crate::{FormatReport, FormatResult, NewlineStyle}; - -// Append a newline to the end of each file. -pub(crate) fn append_newline(s: &mut String) { - s.push_str("\n"); -} - -pub fn write_all_files( - format_report: FormatReport, - out: &mut T, - config: EmitterConfig, -) -> Result -where - T: Write, -{ - let mut emitter = create_emitter(config); - let mut has_diff = false; - - emitter.emit_header(out)?; - for (filename, format_result) in format_report.format_result.borrow().iter() { - has_diff |= write_file(None, filename, &format_result, out, &mut *emitter)?.has_diff; - } - emitter.emit_footer(out)?; - - Ok(has_diff) -} - -pub(crate) fn write_file( - parse_sess: Option<&ParseSess>, - filename: &FileName, - formatted_result: &FormatResult, - out: &mut T, - emitter: &mut dyn Emitter, -) -> Result -where - T: Write, -{ - fn ensure_real_path(filename: &FileName) -> &Path { - match *filename { - FileName::Real(ref path) => path, - _ => panic!("cannot format `{}` and emit to files", filename), - } - } - - // SourceFile's in the SourceMap will always have Unix-style line endings - // See: https://github.com/rust-lang/rustfmt/issues/3850 - // So if the user has explicitly overridden the rustfmt `newline_style` - // config and `filename` is FileName::Real, then we must check the file system - // to get the original file value in order to detect newline_style conflicts. - // Otherwise, parse session is around (cfg(not(test))) and newline_style has been - // left as the default value, then try getting source from the parse session - // source map instead of hitting the file system. This also supports getting - // original text for `FileName::Stdin`. - let original_text = - if formatted_result.newline_style != NewlineStyle::Auto && *filename != FileName::Stdin { - Rc::new(fs::read_to_string(ensure_real_path(filename))?) - } else { - match &formatted_result.original_snippet { - Some(original_snippet) => Rc::new(original_snippet.to_owned()), - None => match parse_sess.and_then(|sess| sess.get_original_snippet(filename)) { - Some(ori) => ori, - None => Rc::new(fs::read_to_string(ensure_real_path(filename))?), - }, - } - }; - - let formatted_file = emitter::FormattedFile { - filename, - original_text: original_text.as_str(), - formatted_text: &formatted_result.formatted_snippet.snippet, - }; - - emitter.emit_formatted_file(out, formatted_file) -} diff --git a/rustfmt-core/rustfmt-lib/src/test/mod.rs b/rustfmt-core/rustfmt-lib/src/test/mod.rs index 0689a215416..7b9bcbf640d 100644 --- a/rustfmt-core/rustfmt-lib/src/test/mod.rs +++ b/rustfmt-core/rustfmt-lib/src/test/mod.rs @@ -9,9 +9,11 @@ use std::thread; use crate::emitter::rustfmt_diff::{make_diff, print_diff, Mismatch, ModifiedChunk, OutputWriter}; use crate::config::{Config, FileName, NewlineStyle}; -use crate::{is_nightly_channel, write_all_files, EmitterConfig, OperationError}; -use crate::{source_file, RustFormatterBuilder}; -use crate::{Color, EmitMode, FormatReport, FormatReportFormatterBuilder, Input, Session}; +use crate::{ + emitter::{emit_format_report, EmitMode, EmitterConfig}, + is_nightly_channel, Color, FormatReport, FormatReportFormatterBuilder, Input, OperationError, + RustFormatterBuilder, Session, +}; mod configuration_snippet; @@ -222,7 +224,7 @@ fn modified_test() { .format(Input::File(filename.into()), &config) .unwrap(); let mut data = vec![]; - write_all_files( + emit_format_report( report, &mut data, EmitterConfig { @@ -280,7 +282,7 @@ fn assert_output(source: &Path, expected_filename: &Path) { // Populate output by writing to a vec. let mut out = vec![]; - let _ = source_file::write_all_files(report, &mut out, emitter_config); + let _ = emit_format_report(report, &mut out, emitter_config); let output = String::from_utf8(out).unwrap(); let mut expected_file = fs::File::open(&expected_filename).expect("couldn't open target"); @@ -321,7 +323,7 @@ fn assert_stdin_output( { let mut session = Session::default(); let report = session.format(input, &config).unwrap(); - let format_has_diff = write_all_files( + let format_has_diff = emit_format_report( report, &mut buf, EmitterConfig { @@ -415,7 +417,7 @@ fn stdin_formatting_smoke_test() { let report = session.format(input, &Config::default()).unwrap(); assert!(!report.has_errors()); let mut buf: Vec = vec![]; - write_all_files( + emit_format_report( report, &mut buf, EmitterConfig { @@ -458,7 +460,7 @@ fn stdin_works_with_modified_lines() { { let mut session = Session::default(); let report = session.format(input, &config).unwrap(); - let format_has_diff = write_all_files( + let format_has_diff = emit_format_report( report, &mut buf, EmitterConfig { From b9c5fe13651f78a0e6f93a77ad6ee0c170ef77e5 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 10 May 2020 10:19:43 +0900 Subject: [PATCH 31/59] Remove Session --- rustfmt-core/rustfmt-bin/src/bin/main.rs | 33 +- .../rustfmt-bin/src/git-rustfmt/main.rs | 8 +- rustfmt-core/rustfmt-lib/src/formatting.rs | 293 +++++++++--------- rustfmt-core/rustfmt-lib/src/lib.rs | 66 ++-- .../src/test/configuration_snippet.rs | 11 +- rustfmt-core/rustfmt-lib/src/test/mod.rs | 47 ++- 6 files changed, 207 insertions(+), 251 deletions(-) diff --git a/rustfmt-core/rustfmt-bin/src/bin/main.rs b/rustfmt-core/rustfmt-bin/src/bin/main.rs index b0776c4d819..97432ce4b10 100644 --- a/rustfmt-core/rustfmt-bin/src/bin/main.rs +++ b/rustfmt-core/rustfmt-bin/src/bin/main.rs @@ -16,7 +16,7 @@ use thiserror::Error; use rustfmt_lib::{ emitter::{emit_format_report, EmitMode, EmitterConfig, Verbosity}, load_config, CliOptions, Config, Edition, FileLines, FileName, FormatReport, - FormatReportFormatterBuilder, Input, RustFormatterBuilder, Session, + FormatReportFormatterBuilder, Input, OperationSetting, }; fn main() { @@ -414,18 +414,13 @@ fn format_string(input: String, opt: Opt) -> Result { } let out = &mut stdout(); - let mut session = RustFormatterBuilder::default() - .recursive(opt.recursive) - .verbosity(Verbosity::Quiet) - .build(); + let setting = OperationSetting { + recursive: opt.recursive, + verbosity: Verbosity::Quiet, + }; let mut format_report = FormatReport::new(); // FIXME: Add error handling. - format_and_emit_report( - &mut session, - Input::Text(input), - &config, - &mut format_report, - ); + format_and_emit_report(Input::Text(input), &config, setting, &mut format_report); let has_diff = emit_format_report(format_report, out, opt.emitter_config(EmitMode::Stdout))?; Ok(if opt.check && has_diff { 1 } else { 0 }) } @@ -498,10 +493,10 @@ fn format(opt: Opt) -> Result { } } - let mut session = RustFormatterBuilder::default() - .recursive(opt.recursive) - .verbosity(opt.verbosity()) - .build(); + let setting = OperationSetting { + recursive: opt.recursive, + verbosity: opt.verbosity(), + }; let mut format_report = FormatReport::new(); for pair in FileConfigPairIter::new(&opt, config_path.is_some()) { @@ -519,16 +514,16 @@ fn format(opt: Opt) -> Result { } format_and_emit_report( - &mut session, Input::File(file.to_path_buf()), &local_config, + setting, &mut format_report, ); } else { format_and_emit_report( - &mut session, Input::File(file.to_path_buf()), &config, + setting, &mut format_report, ); } @@ -550,12 +545,12 @@ fn format(opt: Opt) -> Result { } fn format_and_emit_report( - session: &mut Session, input: Input, config: &Config, + operation_setting: OperationSetting, format_report: &mut FormatReport, ) { - match session.format(input, config) { + match rustfmt_lib::format(input, config, operation_setting) { Ok(report) => { format_report.merge(report); } diff --git a/rustfmt-core/rustfmt-bin/src/git-rustfmt/main.rs b/rustfmt-core/rustfmt-bin/src/git-rustfmt/main.rs index 1c7e3f6f5b9..55a70405a9b 100644 --- a/rustfmt-core/rustfmt-bin/src/git-rustfmt/main.rs +++ b/rustfmt-core/rustfmt-bin/src/git-rustfmt/main.rs @@ -9,7 +9,7 @@ use structopt::StructOpt; use rustfmt_lib::{ emitter::{emit_format_report, EmitterConfig}, - load_config, CliOptions, FormatReportFormatterBuilder, Input, Session, + format, load_config, CliOptions, FormatReportFormatterBuilder, Input, OperationSetting, }; fn prune_files(files: Vec<&str>) -> Vec<&str> { @@ -59,13 +59,11 @@ fn get_files(input: &str) -> Vec<&str> { fn fmt_files(files: &[&str]) -> i32 { let (config, _) = load_config::(Some(Path::new(".")), None).expect("couldn't load config"); + let setting = OperationSetting::default(); let mut out = stdout(); - let mut session = Session::default(); for file in files { - let report = session - .format(Input::File(PathBuf::from(file)), &config) - .unwrap(); + let report = format(Input::File(PathBuf::from(file)), &config, setting).unwrap(); if report.has_warnings() { eprintln!("{}", FormatReportFormatterBuilder::new(&report).build()); } diff --git a/rustfmt-core/rustfmt-lib/src/formatting.rs b/rustfmt-core/rustfmt-lib/src/formatting.rs index f24b1a338db..8c1f879abcf 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting.rs @@ -14,176 +14,169 @@ use crate::utils::count_newlines; use crate::visitor::FmtVisitor; use crate::{ modules, ErrorKind, FormatError, FormatReport, FormatResult, Input, NonFormattedRange, - OperationError, Session, Verbosity, + OperationError, OperationSetting, Verbosity, }; mod newline_style; -impl Session { - pub(crate) fn format_input_inner( - &mut self, - input: Input, - config: &Config, - ) -> Result { - if !config.version_meets_requirement() { - return Err(OperationError::VersionMismatch); - } - - rustc_ast::with_globals(config.edition().into(), || { - self.format_project(input, config) - }) +pub(crate) fn format_input_inner( + input: Input, + config: &Config, + operation_setting: OperationSetting, +) -> Result { + if !config.version_meets_requirement() { + return Err(OperationError::VersionMismatch); } - fn format_project( - &mut self, - input: Input, - config: &Config, - ) -> Result { - let mut timer = Timer::start(); - - let format_report = FormatReport::new(); - - let main_file = input.file_name(); - let input_is_stdin = main_file == FileName::Stdin; - - let mut parse_session = ParseSess::new(config)?; - if !self.recursive && parse_session.ignore_file(&main_file) { - format_report.add_ignored_file(main_file); - return Ok(format_report); - } - - // Parse the crate. - let directory_ownership = input.to_directory_ownership(); - let original_snippet = if let Input::Text(ref str) = input { - Some(str.to_owned()) - } else { - None - }; + rustc_ast::with_globals(config.edition().into(), || { + format_project(input, config, operation_setting) + }) +} +fn format_project( + input: Input, + config: &Config, + operation_setting: OperationSetting, +) -> Result { + let mut timer = Timer::start(); - let krate = match Parser::parse_crate(config, input, directory_ownership, &parse_session) { - Ok(krate) => krate, - Err(e) => { - return Err(OperationError::ParseError { - input: main_file, - is_panic: e == ParserError::ParsePanicError, - }); - } - }; - timer = timer.done_parsing(); + let format_report = FormatReport::new(); - // Suppress error output if we have to do any further parsing. - parse_session.set_silent_emitter(); + let main_file = input.file_name(); + let input_is_stdin = main_file == FileName::Stdin; - let files = modules::ModResolver::new( - &parse_session, - directory_ownership.unwrap_or(DirectoryOwnership::UnownedViaMod), - !input_is_stdin && self.recursive, - ) - .visit_crate(&krate) - .map_err(|e| OperationError::IoError(io::Error::new(io::ErrorKind::Other, e)))?; + let mut parse_session = ParseSess::new(config)?; + if !operation_setting.recursive && parse_session.ignore_file(&main_file) { + format_report.add_ignored_file(main_file); + return Ok(format_report); + } - for (path, module) in files { - let should_ignore = !input_is_stdin && parse_session.ignore_file(&path); - if (!self.recursive && path != main_file) || should_ignore { - continue; - } - should_emit_verbose(input_is_stdin, self.verbosity, || { - println!("Formatting {}", path) + // Parse the crate. + let directory_ownership = input.to_directory_ownership(); + let original_snippet = if let Input::Text(ref str) = input { + Some(str.to_owned()) + } else { + None + }; + + let krate = match Parser::parse_crate(config, input, directory_ownership, &parse_session) { + Ok(krate) => krate, + Err(e) => { + return Err(OperationError::ParseError { + input: main_file, + is_panic: e == ParserError::ParsePanicError, }); - let is_root = path == main_file; - self.format_file( - &parse_session, - config, - &krate, - path, - &module, - is_root, - &format_report, - original_snippet.clone(), - ); } - timer = timer.done_formatting(); - - should_emit_verbose(input_is_stdin, self.verbosity, || { - println!( - "Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase", - timer.get_parse_time(), - timer.get_format_time(), - ) + }; + timer = timer.done_parsing(); + + // Suppress error output if we have to do any further parsing. + parse_session.set_silent_emitter(); + + let files = modules::ModResolver::new( + &parse_session, + directory_ownership.unwrap_or(DirectoryOwnership::UnownedViaMod), + !input_is_stdin && operation_setting.recursive, + ) + .visit_crate(&krate) + .map_err(|e| OperationError::IoError(io::Error::new(io::ErrorKind::Other, e)))?; + + for (path, module) in files { + let should_ignore = !input_is_stdin && parse_session.ignore_file(&path); + if (!operation_setting.recursive && path != main_file) || should_ignore { + continue; + } + should_emit_verbose(input_is_stdin, operation_setting.verbosity, || { + println!("Formatting {}", path) }); - - Ok(format_report) + let is_root = path == main_file; + format_file( + &parse_session, + config, + &krate, + path, + &module, + is_root, + &format_report, + original_snippet.clone(), + ); } + timer = timer.done_formatting(); + + should_emit_verbose(input_is_stdin, operation_setting.verbosity, || { + println!( + "Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase", + timer.get_parse_time(), + timer.get_format_time(), + ) + }); + + Ok(format_report) } -impl Session { - // Formats a single file/module. - fn format_file( - &mut self, - parse_session: &ParseSess, - config: &Config, - krate: &ast::Crate, - path: FileName, - module: &ast::Mod, - is_root: bool, - report: &FormatReport, - original_snippet: Option, - ) { - let snippet_provider = parse_session.snippet_provider(module.inner); - let mut visitor = - FmtVisitor::from_parse_sess(&parse_session, config, &snippet_provider, report.clone()); - visitor.skip_context.update_with_attrs(&krate.attrs); - - // Format inner attributes if available. - if !krate.attrs.is_empty() && is_root { - visitor.skip_empty_lines(snippet_provider.end_pos()); - if visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner) { - visitor.push_rewrite(module.inner, None); - } else { - visitor.format_separate_mod(module, snippet_provider.end_pos()); - } +fn format_file( + parse_session: &ParseSess, + config: &Config, + krate: &ast::Crate, + path: FileName, + module: &ast::Mod, + is_root: bool, + report: &FormatReport, + original_snippet: Option, +) { + let snippet_provider = parse_session.snippet_provider(module.inner); + let mut visitor = + FmtVisitor::from_parse_sess(&parse_session, config, &snippet_provider, report.clone()); + visitor.skip_context.update_with_attrs(&krate.attrs); + + // Format inner attributes if available. + if !krate.attrs.is_empty() && is_root { + visitor.skip_empty_lines(snippet_provider.end_pos()); + if visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner) { + visitor.push_rewrite(module.inner, None); } else { - visitor.last_pos = snippet_provider.start_pos(); - visitor.skip_empty_lines(snippet_provider.end_pos()); visitor.format_separate_mod(module, snippet_provider.end_pos()); - }; - - debug_assert_eq!( - visitor.line_number, - count_newlines(&visitor.buffer), - "failed in format_file visitor.buffer:\n {:?}", - &visitor.buffer - ); - - // For some reason, the source_map does not include terminating - // newlines so we must add one on for each file. This is sad. - visitor.buffer.push('\n'); - - format_lines( - &mut visitor.buffer, - &path, - &visitor.skipped_range.borrow(), - config, - report.clone(), - ); - - apply_newline_style( - config.newline_style(), - &mut visitor.buffer, - snippet_provider.entire_snippet(), - ); - - if visitor.macro_rewrite_failure { - report.add_macro_format_failure(path.clone()); } - let format_result = FormatResult::success( - visitor.buffer.to_owned(), - visitor.skipped_range.borrow().clone(), - original_snippet, - config.newline_style(), - ); - report.add_format_result(path, format_result); + } else { + visitor.last_pos = snippet_provider.start_pos(); + visitor.skip_empty_lines(snippet_provider.end_pos()); + visitor.format_separate_mod(module, snippet_provider.end_pos()); + }; + + debug_assert_eq!( + visitor.line_number, + count_newlines(&visitor.buffer), + "failed in format_file visitor.buffer:\n {:?}", + &visitor.buffer + ); + + // For some reason, the source_map does not include terminating + // newlines so we must add one on for each file. This is sad. + visitor.buffer.push('\n'); + + format_lines( + &mut visitor.buffer, + &path, + &visitor.skipped_range.borrow(), + config, + report.clone(), + ); + + apply_newline_style( + config.newline_style(), + &mut visitor.buffer, + snippet_provider.entire_snippet(), + ); + + if visitor.macro_rewrite_failure { + report.add_macro_format_failure(path.clone()); } + let format_result = FormatResult::success( + visitor.buffer.to_owned(), + visitor.skipped_range.borrow().clone(), + original_snippet, + config.newline_style(), + ); + report.add_format_result(path, format_result); } #[derive(Clone, Copy, Debug)] diff --git a/rustfmt-core/rustfmt-lib/src/lib.rs b/rustfmt-core/rustfmt-lib/src/lib.rs index fd9e32af158..d503c17d25c 100644 --- a/rustfmt-core/rustfmt-lib/src/lib.rs +++ b/rustfmt-core/rustfmt-lib/src/lib.rs @@ -24,6 +24,7 @@ pub use crate::config::{ pub use crate::emitter::rustfmt_diff::{ModifiedChunk, ModifiedLines}; pub use crate::format_report_formatter::{FormatReportFormatter, FormatReportFormatterBuilder}; +use crate::formatting::format_input_inner; use crate::{ comment::LineClasses, emitter::{Color, Verbosity}, @@ -373,10 +374,14 @@ fn format_snippet(snippet: &str, config: &Config) -> Option { let result = { let input = Input::Text(snippet.into()); - let mut session = RustFormatterBuilder::default() - .verbosity(Verbosity::Quiet) - .build(); - session.format(input, &config) + format( + input, + &config, + OperationSetting { + verbosity: Verbosity::Quiet, + ..OperationSetting::default() + }, + ) }; match result { Ok(report) if !report.has_errors() => { @@ -494,52 +499,21 @@ fn format_code_block(code_snippet: &str, config: &Config) -> Option Session { - Session { - recursive: self.recursive, - verbosity: self.verbosity, - } - } - - pub fn recursive(&mut self, recursive: bool) -> &mut Self { - self.recursive = recursive; - self - } - - pub fn verbosity(&mut self, verbosity: Verbosity) -> &mut Self { - self.verbosity = verbosity; - self - } + pub recursive: bool, + pub verbosity: Verbosity, } -impl Session { - /// The main entry point for Rustfmt. Formats the given input according to the - /// given config. `out` is only necessary if required by the configuration. - pub fn format( - &mut self, - input: Input, - config: &Config, - ) -> Result { - self.format_input_inner(input, config) - } +/// The main entry point for Rustfmt. Formats the given input according to the +/// given config. `out` is only necessary if required by the configuration. +pub fn format( + input: Input, + config: &Config, + operation_setting: OperationSetting, +) -> Result { + format_input_inner(input, config, operation_setting) } #[derive(Debug)] diff --git a/rustfmt-core/rustfmt-lib/src/test/configuration_snippet.rs b/rustfmt-core/rustfmt-lib/src/test/configuration_snippet.rs index 44c4dfef92c..5e49633dd9b 100644 --- a/rustfmt-core/rustfmt-lib/src/test/configuration_snippet.rs +++ b/rustfmt-core/rustfmt-lib/src/test/configuration_snippet.rs @@ -8,7 +8,7 @@ use crate::emitter::rustfmt_diff::{make_diff, Mismatch}; use super::{print_mismatches, write_message, DIFF_CONTEXT_SIZE}; use crate::config::Config; -use crate::{Input, RustFormatterBuilder, Verbosity}; +use crate::{Input, OperationSetting, Verbosity}; const CONFIGURATIONS_FILE_NAME: &str = "../../Configurations.md"; @@ -172,10 +172,11 @@ impl ConfigCodeBlock { let input = Input::Text(self.code_block.as_ref().unwrap().to_owned()); let config = self.get_block_config(); - let mut session = RustFormatterBuilder::default() - .verbosity(Verbosity::Quiet) - .build(); - let report = session.format(input, &config); + let operation_setting = OperationSetting { + verbosity: Verbosity::Quiet, + ..OperationSetting::default() + }; + let report = crate::format(input, &config, operation_setting); if report.is_err() { write_message(&format!( "\u{261d}\u{1f3fd} Cannot format {}:{}", diff --git a/rustfmt-core/rustfmt-lib/src/test/mod.rs b/rustfmt-core/rustfmt-lib/src/test/mod.rs index 7b9bcbf640d..d4f0d63625f 100644 --- a/rustfmt-core/rustfmt-lib/src/test/mod.rs +++ b/rustfmt-core/rustfmt-lib/src/test/mod.rs @@ -11,8 +11,8 @@ use crate::emitter::rustfmt_diff::{make_diff, print_diff, Mismatch, ModifiedChun use crate::config::{Config, FileName, NewlineStyle}; use crate::{ emitter::{emit_format_report, EmitMode, EmitterConfig}, - is_nightly_channel, Color, FormatReport, FormatReportFormatterBuilder, Input, OperationError, - RustFormatterBuilder, Session, + format, is_nightly_channel, Color, FormatReport, FormatReportFormatterBuilder, Input, + OperationError, OperationSetting, }; mod configuration_snippet; @@ -218,11 +218,9 @@ fn modified_test() { // Test "modified" output let filename = "tests/writemode/source/modified.rs"; let config = Config::default(); + let setting = OperationSetting::default(); - let mut session = Session::default(); - let report = session - .format(Input::File(filename.into()), &config) - .unwrap(); + let report = format(Input::File(filename.into()), &config, setting).unwrap(); let mut data = vec![]; emit_format_report( report, @@ -321,8 +319,7 @@ fn assert_stdin_output( // Populate output by writing to a vec. let mut buf: Vec = vec![]; { - let mut session = Session::default(); - let report = session.format(input, &config).unwrap(); + let report = format(input, &config, OperationSetting::default()).unwrap(); let format_has_diff = emit_format_report( report, &mut buf, @@ -413,8 +410,7 @@ fn self_tests() { fn stdin_formatting_smoke_test() { init_log(); let input = Input::Text("fn main () {}".to_owned()); - let mut session = RustFormatterBuilder::default().build(); - let report = session.format(input, &Config::default()).unwrap(); + let report = format(input, &Config::default(), OperationSetting::default()).unwrap(); assert!(!report.has_errors()); let mut buf: Vec = vec![]; emit_format_report( @@ -438,8 +434,11 @@ fn stdin_parser_panic_caught() { init_log(); // See issue #3239. for text in ["{", "}"].iter().cloned().map(String::from) { - let mut session = Session::default(); - let format_result = session.format(Input::Text(text), &Config::default()); + let format_result = format( + Input::Text(text), + &Config::default(), + OperationSetting::default(), + ); assert!(format_result.err().unwrap().is_parse_error()); } @@ -458,8 +457,7 @@ fn stdin_works_with_modified_lines() { config.set().newline_style(NewlineStyle::Unix); let mut buf: Vec = vec![]; { - let mut session = Session::default(); - let report = session.format(input, &config).unwrap(); + let report = format(input, &config, OperationSetting::default()).unwrap(); let format_has_diff = emit_format_report( report, &mut buf, @@ -505,8 +503,7 @@ fn format_lines_errors_are_reported() { let input = Input::Text(format!("fn {}() {{}}", long_identifier)); let mut config = Config::default(); config.set().error_on_line_overflow(true); - let mut session = Session::default(); - let report = session.format(input, &config).unwrap(); + let report = format(input, &config, OperationSetting::default()).unwrap(); assert!(report.has_errors()); } @@ -518,8 +515,7 @@ fn format_lines_errors_are_reported_with_tabs() { let mut config = Config::default(); config.set().error_on_line_overflow(true); config.set().hard_tabs(true); - let mut session = Session::default(); - let report = session.format(input, &config).unwrap(); + let report = format(input, &config, OperationSetting::default()).unwrap(); assert!(report.has_errors()); } @@ -598,7 +594,7 @@ fn print_mismatches String>( } } -fn read_config(filename: &Path) -> (Config, RustFormatterBuilder, EmitterConfig) { +fn read_config(filename: &Path) -> (Config, OperationSetting, EmitterConfig) { let sig_comments = read_significant_comments(filename); // Look for a config file. If there is a 'config' property in the significant comments, use // that. Otherwise, if there are no significant comments at all, look for a config file with @@ -609,11 +605,11 @@ fn read_config(filename: &Path) -> (Config, RustFormatterBuilder, EmitterConfig) get_config(filename.with_extension("toml").file_name().map(Path::new)) }; - let mut rustfmt_builder = RustFormatterBuilder::default(); + let mut operation_setting = OperationSetting::default(); let mut emitter_config = EmitterConfig::default(); for (key, val) in &sig_comments { if key == "recursive" { - rustfmt_builder.recursive(val.parse::().unwrap()); + operation_setting.recursive = val.parse::().unwrap(); } else if key == "emit_mode" { emitter_config.emit_mode = val.parse::().unwrap() } else if key != "target" && key != "config" && key != "unstable" { @@ -624,18 +620,17 @@ fn read_config(filename: &Path) -> (Config, RustFormatterBuilder, EmitterConfig) } } - (config, rustfmt_builder, emitter_config) + (config, operation_setting, emitter_config) } fn format_file>( filepath: P, - rustfmt_builder: RustFormatterBuilder, + operation_setting: OperationSetting, config: Config, ) -> Result { let filepath = filepath.into(); let input = Input::File(filepath); - let mut session = rustfmt_builder.build(); - session.format(input, &config) + format(input, &config, operation_setting) } enum IdempotentCheckError { @@ -650,7 +645,7 @@ fn idempotent_check( let sig_comments = read_significant_comments(filename); let (config, builder, _) = if let Some(ref config_file_path) = opt_config { let config = Config::from_toml_path(config_file_path).expect("`rustfmt.toml` not found"); - let builder = RustFormatterBuilder::default(); + let builder = OperationSetting::default(); let emitter_config = EmitterConfig::default(); (config, builder, emitter_config) } else { From 474ca535b6fbe2766a5ed7ac790341f068a91dcd Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 10 May 2020 17:31:13 +0900 Subject: [PATCH 32/59] Move formatting-related modules under formatting --- rustfmt-core/rustfmt-lib/Cargo.toml | 3 +- rustfmt-core/rustfmt-lib/src/emitter.rs | 10 +- .../src/format_report_formatter.rs | 14 +- rustfmt-core/rustfmt-lib/src/formatting.rs | 110 +++- .../rustfmt-lib/src/{ => formatting}/attr.rs | 35 +- .../src/{ => formatting}/attr/doc_comment.rs | 3 +- .../src/{ => formatting}/chains.rs | 22 +- .../src/{ => formatting}/closures.rs | 30 +- .../src/{ => formatting}/comment.rs | 25 +- .../rustfmt-lib/src/{ => formatting}/expr.rs | 58 ++- .../src/{ => formatting}/imports.rs | 24 +- .../rustfmt-lib/src/{ => formatting}/items.rs | 44 +- .../rustfmt-lib/src/{ => formatting}/lists.rs | 23 +- .../src/{ => formatting}/macros.rs | 44 +- .../src/{ => formatting}/matches.rs | 32 +- .../src/{ => formatting}/missed_spans.rs | 21 +- .../src/{ => formatting}/modules.rs | 12 +- .../src/{ => formatting}/modules/visitor.rs | 8 +- .../src/{ => formatting}/overflow.rs | 37 +- .../rustfmt-lib/src/{ => formatting}/pairs.rs | 10 +- .../src/{ => formatting}/patterns.rs | 30 +- .../src/{ => formatting}/reorder.rs | 20 +- .../rustfmt-lib/src/formatting/report.rs | 194 +++++++ .../src/{ => formatting}/rewrite.rs | 12 +- .../rustfmt-lib/src/{ => formatting}/shape.rs | 0 .../rustfmt-lib/src/{ => formatting}/skip.rs | 0 .../src/{ => formatting}/source_map.rs | 6 +- .../src/{ => formatting}/spanned.rs | 11 +- .../rustfmt-lib/src/{ => formatting}/stmt.rs | 16 +- .../src/{ => formatting}/string.rs | 8 +- .../src/{ => formatting}/syntux.rs | 0 .../src/{ => formatting}/syntux/parser.rs | 2 +- .../src/{ => formatting}/syntux/session.rs | 36 +- .../rustfmt-lib/src/{ => formatting}/types.rs | 38 +- .../rustfmt-lib/src/formatting/util.rs | 227 +++++++++ .../rustfmt-lib/src/{ => formatting}/utils.rs | 8 +- .../src/{ => formatting}/vertical.rs | 28 +- .../src/{ => formatting}/visitor.rs | 43 +- rustfmt-core/rustfmt-lib/src/lib.rs | 474 +----------------- rustfmt-core/rustfmt-lib/src/result.rs | 132 +++++ .../src/test/configuration_snippet.rs | 2 +- rustfmt-core/rustfmt-lib/src/test/mod.rs | 2 +- 42 files changed, 1063 insertions(+), 791 deletions(-) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/attr.rs (95%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/attr/doc_comment.rs (98%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/chains.rs (98%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/closures.rs (95%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/comment.rs (99%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/expr.rs (98%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/imports.rs (98%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/items.rs (99%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/lists.rs (98%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/macros.rs (98%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/matches.rs (96%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/missed_spans.rs (96%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/modules.rs (98%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/modules/visitor.rs (95%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/overflow.rs (97%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/pairs.rs (98%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/patterns.rs (96%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/reorder.rs (97%) create mode 100644 rustfmt-core/rustfmt-lib/src/formatting/report.rs rename rustfmt-core/rustfmt-lib/src/{ => formatting}/rewrite.rs (94%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/shape.rs (100%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/skip.rs (100%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/source_map.rs (97%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/spanned.rs (95%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/stmt.rs (91%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/string.rs (99%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/syntux.rs (100%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/syntux/parser.rs (99%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/syntux/session.rs (97%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/types.rs (97%) create mode 100644 rustfmt-core/rustfmt-lib/src/formatting/util.rs rename rustfmt-core/rustfmt-lib/src/{ => formatting}/utils.rs (99%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/vertical.rs (94%) rename rustfmt-core/rustfmt-lib/src/{ => formatting}/visitor.rs (97%) create mode 100644 rustfmt-core/rustfmt-lib/src/result.rs diff --git a/rustfmt-core/rustfmt-lib/Cargo.toml b/rustfmt-core/rustfmt-lib/Cargo.toml index 6296eebe192..ecf4bfe6f8e 100644 --- a/rustfmt-core/rustfmt-lib/Cargo.toml +++ b/rustfmt-core/rustfmt-lib/Cargo.toml @@ -25,6 +25,7 @@ emitter = [ "diff", "serde", "serde_json", + "term", ] [dependencies] @@ -37,7 +38,6 @@ itertools = "0.8" lazy_static = "1.0.0" log = "0.4" regex = "1.0" -term = "0.6" thiserror = "1.0" unicode_categories = "0.1.1" unicode-segmentation = "1.0.0" @@ -49,6 +49,7 @@ dirs = { version = "2.0", optional = true } rustfmt-config_proc_macro = { version = "0.5", path = "config_proc_macro", optional = true } serde = { version = "1.0", features = ["derive"], optional = true } serde_json = { version = "1.0", optional = true } +term = { version = "0.6", optional = true } toml = { version = "0.5", optional = true } [target.'cfg(windows)'.dependencies] diff --git a/rustfmt-core/rustfmt-lib/src/emitter.rs b/rustfmt-core/rustfmt-lib/src/emitter.rs index 12334d2edd4..c49e413f0b8 100644 --- a/rustfmt-core/rustfmt-lib/src/emitter.rs +++ b/rustfmt-core/rustfmt-lib/src/emitter.rs @@ -12,7 +12,7 @@ use std::rc::Rc; use thiserror::Error; -use crate::syntux::session::ParseSess; +use crate::formatting::ParseSess; use crate::{config::FileName, FormatReport, FormatResult, NewlineStyle}; pub mod checkstyle; @@ -165,7 +165,7 @@ where let mut has_diff = false; emitter.emit_header(out)?; - for (filename, format_result) in format_report.format_result.borrow().iter() { + for (filename, format_result) in format_report.format_result_as_rc().borrow().iter() { has_diff |= write_file(None, filename, &format_result, out, &mut *emitter)?.has_diff; } emitter.emit_footer(out)?; @@ -200,10 +200,10 @@ where // source map instead of hitting the file system. This also supports getting // original text for `FileName::Stdin`. let original_text = - if formatted_result.newline_style != NewlineStyle::Auto && *filename != FileName::Stdin { + if formatted_result.newline_style() != NewlineStyle::Auto && *filename != FileName::Stdin { Rc::new(fs::read_to_string(ensure_real_path(filename))?) } else { - match &formatted_result.original_snippet { + match formatted_result.original_text() { Some(original_snippet) => Rc::new(original_snippet.to_owned()), None => match parse_sess.and_then(|sess| sess.get_original_snippet(filename)) { Some(ori) => ori, @@ -215,7 +215,7 @@ where let formatted_file = FormattedFile { filename, original_text: original_text.as_str(), - formatted_text: &formatted_result.formatted_snippet.snippet, + formatted_text: formatted_result.formatted_text(), }; emitter.emit_formatted_file(out, formatted_file) diff --git a/rustfmt-core/rustfmt-lib/src/format_report_formatter.rs b/rustfmt-core/rustfmt-lib/src/format_report_formatter.rs index fc57d1b7985..5d3fabb70dc 100644 --- a/rustfmt-core/rustfmt-lib/src/format_report_formatter.rs +++ b/rustfmt-core/rustfmt-lib/src/format_report_formatter.rs @@ -49,8 +49,8 @@ impl<'a> Display for FormatReportFormatter<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let formatter = DisplayListFormatter::new(self.enable_colors, false); - for (file, errors) in self.report.format_result.borrow().iter() { - for error in errors.errors() { + for (file, errors) in self.report.format_result_as_rc().borrow().iter() { + for error in errors.errors_excluding_macro() { let snippet = formatting_error_to_snippet(file, error); writeln!(f, "{}\n", formatter.format(&DisplayList::from(snippet)))?; } @@ -92,11 +92,11 @@ fn formatting_error_to_snippet(file: &FileName, error: &FormatError) -> Snippet } fn snippet_title(error: &FormatError) -> Annotation { - let annotation_type = error_kind_to_snippet_annotation_type(&error.kind); + let annotation_type = error_kind_to_snippet_annotation_type(&error.kind()); Annotation { id: None, - label: Some(error.kind.to_string()), + label: Some(error.kind().to_string()), annotation_type, } } @@ -104,14 +104,14 @@ fn snippet_title(error: &FormatError) -> Annotation { fn snippet_code_slice(file: &FileName, error: &FormatError) -> Slice { let annotations = slice_annotation(error).into_iter().collect(); let origin = error - .line_num + .line_num() .as_ref() .map(|line_num| format!("{}:{}", file, line_num)); - let source = error.line_str.clone().unwrap_or_else(|| String::new()); + let source = error.line_str().unwrap_or("").to_owned(); Slice { source, - line_start: error.line_num.unwrap_or(0), + line_start: error.line_num().unwrap_or(0), origin, fold: false, annotations, diff --git a/rustfmt-core/rustfmt-lib/src/formatting.rs b/rustfmt-core/rustfmt-lib/src/formatting.rs index 8c1f879abcf..b6f2259d475 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting.rs @@ -5,19 +5,56 @@ use std::time::{Duration, Instant}; use rustc_ast::ast; +pub(crate) use syntux::session::ParseSess; + use self::newline_style::apply_newline_style; -use crate::comment::{CharClasses, FullCodeCharKind}; +use crate::formatting::{ + comment::{CharClasses, FullCodeCharKind}, + report::NonFormattedRange, + syntux::parser::{DirectoryOwnership, Parser, ParserError}, + utils::count_newlines, + visitor::FmtVisitor, +}; use crate::config::{Config, FileName}; -use crate::syntux::parser::{DirectoryOwnership, Parser, ParserError}; -use crate::syntux::session::ParseSess; -use crate::utils::count_newlines; -use crate::visitor::FmtVisitor; +use crate::result::OperationError; use crate::{ - modules, ErrorKind, FormatError, FormatReport, FormatResult, Input, NonFormattedRange, - OperationError, OperationSetting, Verbosity, + ErrorKind, FormatError, FormatReport, FormatResult, Input, OperationSetting, Verbosity, }; +#[macro_use] +mod utils; + +mod attr; +mod chains; +mod closures; +mod comment; +mod expr; +mod imports; +mod items; +mod lists; +mod macros; +mod matches; +mod missed_spans; +pub(crate) mod modules; mod newline_style; +mod overflow; +mod pairs; +mod patterns; +mod reorder; +mod rewrite; +mod shape; +mod skip; +pub(crate) mod source_map; +mod spanned; +mod stmt; +mod string; +mod syntux; +mod types; +mod vertical; +pub(crate) mod visitor; + +pub(crate) mod report; +pub(crate) mod util; pub(crate) fn format_input_inner( input: Input, @@ -32,6 +69,7 @@ pub(crate) fn format_input_inner( format_project(input, config, operation_setting) }) } + fn format_project( input: Input, config: &Config, @@ -412,3 +450,61 @@ where f(); } } + +/// Result of formatting a snippet of code along with ranges of lines that didn't get formatted, +/// i.e., that got returned as they were originally. +#[derive(Debug, Clone, Default)] +pub(crate) struct FormattedSnippet { + snippet: String, + non_formatted_ranges: Vec, +} + +impl FormattedSnippet { + /// In case the snippet needed to be wrapped in a function, this shifts down the ranges of + /// non-formatted code. + fn unwrap_code_block(&mut self) { + self.non_formatted_ranges.iter_mut().for_each(|range| { + *range = range.shift_up(); + }); + } + + /// Returns `true` if the line n did not get formatted. + pub(crate) fn is_line_non_formatted(&self, n: usize) -> bool { + self.non_formatted_ranges + .iter() + .any(|range| range.contains(n)) + } +} + +impl AsRef for FormattedSnippet { + fn as_ref(&self) -> &str { + self.snippet.as_str() + } +} + +impl Input { + fn file_name(&self) -> FileName { + match *self { + Input::File(ref file) => FileName::Real(file.clone()), + Input::Text(..) => FileName::Stdin, + } + } + + fn to_directory_ownership(&self) -> Option { + match self { + Input::File(ref file) => { + // If there exists a directory with the same name as an input, + // then the input should be parsed as a sub module. + let file_stem = file.file_stem()?; + if file.parent()?.to_path_buf().join(file_stem).is_dir() { + Some(DirectoryOwnership::Owned { + relative: file_stem.to_str().map(ast::Ident::from_str), + }) + } else { + None + } + } + _ => None, + } + } +} diff --git a/rustfmt-core/rustfmt-lib/src/attr.rs b/rustfmt-core/rustfmt-lib/src/formatting/attr.rs similarity index 95% rename from rustfmt-core/rustfmt-lib/src/attr.rs rename to rustfmt-core/rustfmt-lib/src/formatting/attr.rs index 6976168ce0a..563b3a2b20f 100644 --- a/rustfmt-core/rustfmt-lib/src/attr.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/attr.rs @@ -4,17 +4,22 @@ use rustc_ast::ast; use rustc_ast::attr::HasAttrs; use rustc_span::{symbol::sym, Span}; -use self::doc_comment::DocCommentFormatter; -use crate::comment::{contains_comment, rewrite_doc_comment, CommentStyle}; -use crate::config::lists::*; -use crate::config::IndentStyle; -use crate::expr::rewrite_literal; -use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; -use crate::overflow; -use crate::rewrite::{Rewrite, RewriteContext}; -use crate::shape::Shape; -use crate::types::{rewrite_path, PathContext}; -use crate::utils::{count_newlines, mk_sp}; +use doc_comment::DocCommentFormatter; +use crate::config::{ + lists::*, + IndentStyle, +}; + +use crate::formatting::{ + comment::{contains_comment, rewrite_doc_comment, CommentStyle, recover_missing_comment_in_span}, + expr::{rewrite_literal, span_ends_with_comma}, + lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}, + overflow, + rewrite::{Rewrite, RewriteContext}, + shape::Shape, + types::{rewrite_path, PathContext}, + utils::{count_newlines, mk_sp}, +}; mod doc_comment; @@ -279,7 +284,7 @@ impl Rewrite for ast::MetaItem { } ast::MetaItemKind::List(ref list) => { let path = rewrite_path(context, PathContext::Type, None, &self.path, shape)?; - let has_trailing_comma = crate::expr::span_ends_with_comma(context, self.span); + let has_trailing_comma = span_ends_with_comma(context, self.span); overflow::rewrite_with_parens( context, &path, @@ -398,7 +403,7 @@ impl<'a> Rewrite for [ast::Attribute] { if let Some(missing_span) = missing_span { let snippet = context.snippet(missing_span); let (mla, mlb) = has_newlines_before_after_comment(snippet); - let comment = crate::comment::recover_missing_comment_in_span( + let comment = recover_missing_comment_in_span( missing_span, shape.with_max_width(context.config), context, @@ -428,7 +433,7 @@ impl<'a> Rewrite for [ast::Attribute] { .get(derives.len()) .map(|next| mk_sp(attrs[derives.len() - 1].span.hi(), next.span.lo())); if let Some(missing_span) = missing_span { - let comment = crate::comment::recover_missing_comment_in_span( + let comment = recover_missing_comment_in_span( missing_span, shape.with_max_width(context.config), context, @@ -461,7 +466,7 @@ impl<'a> Rewrite for [ast::Attribute] { .get(1) .map(|next| mk_sp(attrs[0].span.hi(), next.span.lo())); if let Some(missing_span) = missing_span { - let comment = crate::comment::recover_missing_comment_in_span( + let comment = recover_missing_comment_in_span( missing_span, shape.with_max_width(context.config), context, diff --git a/rustfmt-core/rustfmt-lib/src/attr/doc_comment.rs b/rustfmt-core/rustfmt-lib/src/formatting/attr/doc_comment.rs similarity index 98% rename from rustfmt-core/rustfmt-lib/src/attr/doc_comment.rs rename to rustfmt-core/rustfmt-lib/src/formatting/attr/doc_comment.rs index 80434ebbfd4..22fa06fa238 100644 --- a/rustfmt-core/rustfmt-lib/src/attr/doc_comment.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/attr/doc_comment.rs @@ -1,6 +1,7 @@ -use crate::comment::CommentStyle; use std::fmt::{self, Display}; +use crate::formatting::comment::CommentStyle; + /// Formats a string as a doc comment using the given [`CommentStyle`]. pub(super) struct DocCommentFormatter<'a> { literal: &'a str, diff --git a/rustfmt-core/rustfmt-lib/src/chains.rs b/rustfmt-core/rustfmt-lib/src/formatting/chains.rs similarity index 98% rename from rustfmt-core/rustfmt-lib/src/chains.rs rename to rustfmt-core/rustfmt-lib/src/formatting/chains.rs index 2f938ae340d..d86ce92fc11 100644 --- a/rustfmt-core/rustfmt-lib/src/chains.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/chains.rs @@ -61,17 +61,19 @@ use std::cmp::min; use rustc_ast::{ast, ptr}; use rustc_span::{symbol, BytePos, Span}; -use crate::comment::{rewrite_comment, CharClasses, FullCodeCharKind, RichChar}; use crate::config::IndentStyle; -use crate::expr::rewrite_call; -use crate::lists::extract_pre_comment; -use crate::macros::convert_try_mac; -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, +use crate::formatting::{ + comment::{rewrite_comment, CharClasses, FullCodeCharKind, RichChar}, + expr::rewrite_call, + lists::extract_pre_comment, + macros::convert_try_mac, + rewrite::{Rewrite, RewriteContext}, + shape::Shape, + source_map::SpanUtils, + utils::{ + self, first_line_width, last_line_extendable, last_line_width, mk_sp, rewrite_ident, + trimmed_last_line_width, wrap_str, + }, }; pub(crate) fn rewrite_chain( diff --git a/rustfmt-core/rustfmt-lib/src/closures.rs b/rustfmt-core/rustfmt-lib/src/formatting/closures.rs similarity index 95% rename from rustfmt-core/rustfmt-lib/src/closures.rs rename to rustfmt-core/rustfmt-lib/src/formatting/closures.rs index 6b3140947b1..76ecc8550d1 100644 --- a/rustfmt-core/rustfmt-lib/src/closures.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/closures.rs @@ -1,17 +1,23 @@ use rustc_ast::{ast, ptr}; use rustc_span::Span; -use crate::attr::get_attrs_from_stmt; -use crate::config::lists::*; -use crate::config::{IndentStyle, SeparatorTactic}; -use crate::expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond}; -use crate::items::{span_hi_for_param, span_lo_for_param}; -use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; -use crate::overflow::OverflowableItem; -use crate::rewrite::{Rewrite, RewriteContext}; -use crate::shape::Shape; -use crate::source_map::SpanUtils; -use crate::utils::{last_line_width, left_most_sub_expr, stmt_expr, NodeIdExt}; +use crate::config::{ + lists::*, + IndentStyle, + SeparatorTactic, +}; +use crate::formatting::{ + attr::get_attrs_from_stmt, + expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond, + rewrite_block_with_visitor}, + items::{span_hi_for_param, span_lo_for_param}, + lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}, + overflow::OverflowableItem, + rewrite::{Rewrite, RewriteContext}, + shape::Shape, + source_map::SpanUtils, + utils::{last_line_width, left_most_sub_expr, stmt_expr, NodeIdExt}, +}; // This module is pretty messy because of the rules around closures and blocks: // FIXME - the below is probably no longer true in full. @@ -156,7 +162,7 @@ fn rewrite_closure_with_block( rules: ast::BlockCheckMode::Default, span: body.span, }; - let block = crate::expr::rewrite_block_with_visitor( + let block = rewrite_block_with_visitor( context, "", &block, diff --git a/rustfmt-core/rustfmt-lib/src/comment.rs b/rustfmt-core/rustfmt-lib/src/formatting/comment.rs similarity index 99% rename from rustfmt-core/rustfmt-lib/src/comment.rs rename to rustfmt-core/rustfmt-lib/src/formatting/comment.rs index 95ed499af6d..b9ad5422c44 100644 --- a/rustfmt-core/rustfmt-lib/src/comment.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/comment.rs @@ -6,12 +6,14 @@ use itertools::{multipeek, MultiPeek}; use rustc_span::Span; use crate::config::Config; -use crate::rewrite::RewriteContext; -use crate::shape::{Indent, Shape}; -use crate::string::{rewrite_string, StringFormat}; -use crate::utils::{ - count_newlines, first_line_width, last_line_width, tab_to_spaces, trim_left_preserve_layout, - unicode_str_width, +use crate::formatting::{ + rewrite::RewriteContext, + shape::{Indent, Shape}, + string::{rewrite_string, StringFormat}, + utils::{ + count_newlines, first_line_width, last_line_width, tab_to_spaces, trim_left_preserve_layout, + unicode_str_width, + }, }; fn is_custom_comment(comment: &str) -> bool { @@ -667,10 +669,11 @@ impl<'a> CommentRewrite<'a> { let mut config = self.fmt.config.clone(); config.set().wrap_comments(false); if config.format_code_in_doc_comments() { - if let Some(s) = - crate::format_code_block(&self.code_block_buffer, &config) - { - trim_custom_comment_prefix(&s.snippet) + if let Some(s) = crate::formatting::util::format_code_block( + &self.code_block_buffer, + &config, + ) { + trim_custom_comment_prefix(s.as_ref()) } else { trim_custom_comment_prefix(&self.code_block_buffer) } @@ -1697,7 +1700,7 @@ fn remove_comment_header(comment: &str) -> &str { #[cfg(test)] mod test { use super::*; - use crate::shape::{Indent, Shape}; + use crate::formatting::shape::{Indent, Shape}; #[test] fn char_classes() { diff --git a/rustfmt-core/rustfmt-lib/src/expr.rs b/rustfmt-core/rustfmt-lib/src/formatting/expr.rs similarity index 98% rename from rustfmt-core/rustfmt-lib/src/expr.rs rename to rustfmt-core/rustfmt-lib/src/formatting/expr.rs index 1d7c07b6eb3..574812c202b 100644 --- a/rustfmt-core/rustfmt-lib/src/expr.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/expr.rs @@ -6,35 +6,39 @@ use rustc_ast::token::{DelimToken, LitKind}; use rustc_ast::{ast, ptr}; use rustc_span::{BytePos, Span}; -use crate::chains::rewrite_chain; -use crate::closures; -use crate::comment::{ - combine_strs_with_missing_comments, comment_style, contains_comment, recover_comment_removed, - rewrite_comment, rewrite_missing_comment, CharClasses, FindUncommented, +use crate::config::{ + lists::*, + Config, ControlBraceStyle, IndentStyle, }; -use crate::config::lists::*; -use crate::config::{Config, ControlBraceStyle, IndentStyle}; -use crate::lists::{ - definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, - struct_lit_tactic, write_list, ListFormatting, Separator, +use crate::formatting::{ + chains::rewrite_chain, + closures, + comment::{ + combine_strs_with_missing_comments, comment_style, contains_comment, recover_comment_removed, + rewrite_comment, rewrite_missing_comment, CharClasses, FindUncommented, + }, + lists::{ + definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, + struct_lit_tactic, write_list, ListFormatting, Separator, + }, + macros::{rewrite_macro, MacroPosition}, + matches::rewrite_match, + overflow::{self, IntoOverflowableItem, OverflowableItem}, + pairs::{rewrite_all_pairs, rewrite_pair, PairParts}, + rewrite::{Rewrite, RewriteContext}, + shape::{Indent, Shape}, + source_map::{LineRangeUtils, SpanUtils}, + spanned::Spanned, + string::{rewrite_string, StringFormat}, + types::{rewrite_path, PathContext}, + 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, + }, + vertical::rewrite_with_alignment, + visitor::FmtVisitor, }; -use crate::macros::{rewrite_macro, MacroPosition}; -use crate::matches::rewrite_match; -use crate::overflow::{self, IntoOverflowableItem, OverflowableItem}; -use crate::pairs::{rewrite_all_pairs, rewrite_pair, PairParts}; -use crate::rewrite::{Rewrite, RewriteContext}; -use crate::shape::{Indent, Shape}; -use crate::source_map::{LineRangeUtils, SpanUtils}; -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, -}; -use crate::vertical::rewrite_with_alignment; -use crate::visitor::FmtVisitor; impl Rewrite for ast::Expr { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { diff --git a/rustfmt-core/rustfmt-lib/src/imports.rs b/rustfmt-core/rustfmt-lib/src/formatting/imports.rs similarity index 98% rename from rustfmt-core/rustfmt-lib/src/imports.rs rename to rustfmt-core/rustfmt-lib/src/formatting/imports.rs index 17a173e39cb..6e365fcbfc2 100644 --- a/rustfmt-core/rustfmt-lib/src/imports.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/imports.rs @@ -9,19 +9,21 @@ use rustc_span::{ BytePos, Span, DUMMY_SP, }; -use crate::comment::combine_strs_with_missing_comments; use crate::config::lists::*; use crate::config::{Edition, IndentStyle}; -use crate::lists::{ - definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, +use crate::formatting::{ + comment::combine_strs_with_missing_comments, + lists::{ + definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, + }, + reorder::{compare_as_versions, compare_opt_ident_as_versions}, + rewrite::{Rewrite, RewriteContext}, + shape::Shape, + source_map::SpanUtils, + spanned::Spanned, + utils::{is_same_visibility, mk_sp, rewrite_ident, format_visibility}, + visitor::FmtVisitor, }; -use crate::reorder::{compare_as_versions, compare_opt_ident_as_versions}; -use crate::rewrite::{Rewrite, RewriteContext}; -use crate::shape::Shape; -use crate::source_map::SpanUtils; -use crate::spanned::Spanned; -use crate::utils::{is_same_visibility, mk_sp, rewrite_ident}; -use crate::visitor::FmtVisitor; /// Returns a name imported by a `use` declaration. /// E.g., returns `Ordering` for `std::cmp::Ordering` and `self` for `std::cmp::self`. @@ -233,7 +235,7 @@ impl UseTree { shape: Shape, ) -> Option { let vis = self.visibility.as_ref().map_or(Cow::from(""), |vis| { - crate::utils::format_visibility(context, &vis) + format_visibility(context, &vis) }); let use_str = self .rewrite(context, shape.offset_left(vis.len())?) diff --git a/rustfmt-core/rustfmt-lib/src/items.rs b/rustfmt-core/rustfmt-lib/src/formatting/items.rs similarity index 99% rename from rustfmt-core/rustfmt-lib/src/items.rs rename to rustfmt-core/rustfmt-lib/src/formatting/items.rs index 40395bbbbd5..146245d1026 100644 --- a/rustfmt-core/rustfmt-lib/src/items.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/items.rs @@ -8,30 +8,32 @@ use rustc_ast::visit; use rustc_ast::{ast, ptr}; use rustc_span::{source_map, symbol, BytePos, Span, DUMMY_SP}; -use crate::attr::filter_inline_attrs; -use crate::comment::{ - combine_strs_with_missing_comments, contains_comment, is_last_comment_block, - recover_comment_removed, recover_missing_comment_in_span, rewrite_missing_comment, - FindUncommented, -}; use crate::config::lists::*; use crate::config::{BraceStyle, Config, IndentStyle}; -use crate::expr::{ - is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_expr, - rewrite_assign_rhs_with, RhsTactics, +use crate::formatting::{ + attr::filter_inline_attrs, + comment::{ + combine_strs_with_missing_comments, contains_comment, is_last_comment_block, + recover_comment_removed, recover_missing_comment_in_span, rewrite_missing_comment, + FindUncommented, + }, + expr::{ + is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_expr, + rewrite_assign_rhs_with, RhsTactics, + }, + lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}, + macros::{rewrite_macro, MacroPosition}, + overflow, + reorder::compare_as_versions, + rewrite::{Rewrite, RewriteContext}, + shape::{Indent, Shape}, + source_map::{LineRangeUtils, SpanUtils}, + spanned::Spanned, + stmt::Stmt, + utils::*, + vertical::rewrite_with_alignment, + visitor::FmtVisitor, }; -use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; -use crate::macros::{rewrite_macro, MacroPosition}; -use crate::overflow; -use crate::reorder::compare_as_versions; -use crate::rewrite::{Rewrite, RewriteContext}; -use crate::shape::{Indent, Shape}; -use crate::source_map::{LineRangeUtils, SpanUtils}; -use crate::spanned::Spanned; -use crate::stmt::Stmt; -use crate::utils::*; -use crate::vertical::rewrite_with_alignment; -use crate::visitor::FmtVisitor; const DEFAULT_VISIBILITY: ast::Visibility = source_map::Spanned { node: ast::VisibilityKind::Inherited, diff --git a/rustfmt-core/rustfmt-lib/src/lists.rs b/rustfmt-core/rustfmt-lib/src/formatting/lists.rs similarity index 98% rename from rustfmt-core/rustfmt-lib/src/lists.rs rename to rustfmt-core/rustfmt-lib/src/formatting/lists.rs index f67908a3b8c..2c7a2ea63a8 100644 --- a/rustfmt-core/rustfmt-lib/src/lists.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/lists.rs @@ -6,16 +6,21 @@ use std::iter::Peekable; use rustc_span::BytePos; use unicode_segmentation::UnicodeSegmentation; -use crate::comment::{find_comment_end, rewrite_comment, FindUncommented}; -use crate::config::lists::*; -use crate::config::{Config, IndentStyle}; -use crate::rewrite::RewriteContext; -use crate::shape::{Indent, Shape}; -use crate::utils::{ - count_newlines, first_line_width, last_line_width, mk_sp, starts_with_newline, - unicode_str_width, +use crate::config::{ + lists::*, + Config, + IndentStyle, +}; +use crate::formatting::{ + comment::{find_comment_end, rewrite_comment, FindUncommented}, + rewrite::RewriteContext, + shape::{Indent, Shape}, + utils::{ + count_newlines, first_line_width, last_line_width, mk_sp, starts_with_newline, + unicode_str_width, + }, + visitor::SnippetProvider, }; -use crate::visitor::SnippetProvider; pub(crate) struct ListFormatting<'a> { tactic: DefinitiveListTactic, diff --git a/rustfmt-core/rustfmt-lib/src/macros.rs b/rustfmt-core/rustfmt-lib/src/formatting/macros.rs similarity index 98% rename from rustfmt-core/rustfmt-lib/src/macros.rs rename to rustfmt-core/rustfmt-lib/src/formatting/macros.rs index 82d9bc4567c..c1492efc07c 100644 --- a/rustfmt-core/rustfmt-lib/src/macros.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/macros.rs @@ -22,22 +22,26 @@ use rustc_span::{ BytePos, Span, Symbol, DUMMY_SP, }; -use crate::comment::{ - contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses, +use crate::formatting::{ + comment::{ + contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses, + }, + expr::{rewrite_array, rewrite_assign_rhs}, + report::NonFormattedRange, + lists::{itemize_list, write_list, ListFormatting}, + overflow, + rewrite::{Rewrite, RewriteContext}, + shape::{Indent, Shape}, + source_map::SpanUtils, + spanned::Spanned, + util::{format_snippet, format_code_block}, + utils::{ + count_newlines, format_visibility, indent_next_line, is_empty_line, mk_sp, + remove_trailing_white_spaces, rewrite_ident, trim_left_preserve_layout, wrap_str, NodeIdExt, + }, + visitor::FmtVisitor, }; use crate::config::lists::*; -use crate::expr::rewrite_array; -use crate::lists::{itemize_list, write_list, ListFormatting}; -use crate::rewrite::{Rewrite, RewriteContext}; -use crate::shape::{Indent, Shape}; -use crate::source_map::SpanUtils; -use crate::spanned::Spanned; -use crate::utils::{ - count_newlines, format_visibility, indent_next_line, is_empty_line, mk_sp, - remove_trailing_white_spaces, rewrite_ident, trim_left_preserve_layout, wrap_str, NodeIdExt, -}; -use crate::visitor::FmtVisitor; -use crate::{overflow, NonFormattedRange}; const FORCED_BRACKET_MACROS: &[&str] = &["vec!"]; @@ -69,7 +73,7 @@ impl MacroArg { impl Rewrite for ast::Item { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - let mut visitor = crate::visitor::FmtVisitor::from_context(context); + let mut visitor = FmtVisitor::from_context(context); visitor.block_indent = shape.indent; visitor.last_pos = self.span().lo(); visitor.visit_item(self); @@ -1365,19 +1369,19 @@ impl MacroBranch { config.set().max_width(new_width); // First try to format as items, then as statements. - let new_body_snippet = match crate::format_snippet(&body_str, &config) { + let new_body_snippet = match format_snippet(&body_str, &config) { Some(new_body) => new_body, None => { let new_width = new_width + config.tab_spaces(); config.set().max_width(new_width); - match crate::format_code_block(&body_str, &config) { + match format_code_block(&body_str, &config) { Some(new_body) => new_body, None => return None, } } }; let new_body = wrap_str( - new_body_snippet.snippet.to_string(), + new_body_snippet.as_ref().to_owned(), config.max_width(), shape, )?; @@ -1472,7 +1476,7 @@ fn format_lazy_static( while parser.token.kind != TokenKind::Eof { // Parse a `lazy_static!` item. - let vis = crate::utils::format_visibility( + let vis = format_visibility( context, &parse_or!(parse_visibility, rustc_parse::parser::FollowedByType::No), ); @@ -1493,7 +1497,7 @@ fn format_lazy_static( id, ty.rewrite(context, nested_shape)? )); - result.push_str(&crate::expr::rewrite_assign_rhs( + result.push_str(&rewrite_assign_rhs( context, stmt, &expr, diff --git a/rustfmt-core/rustfmt-lib/src/matches.rs b/rustfmt-core/rustfmt-lib/src/formatting/matches.rs similarity index 96% rename from rustfmt-core/rustfmt-lib/src/matches.rs rename to rustfmt-core/rustfmt-lib/src/formatting/matches.rs index 0f3d835bcce..bb95cfe8d77 100644 --- a/rustfmt-core/rustfmt-lib/src/matches.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/matches.rs @@ -5,21 +5,25 @@ use std::iter::repeat; use rustc_ast::{ast, ptr}; use rustc_span::{BytePos, Span}; -use crate::comment::{combine_strs_with_missing_comments, rewrite_comment}; -use crate::config::lists::*; -use crate::config::{Config, ControlBraceStyle, IndentStyle, MatchArmLeadingPipe}; -use crate::expr::{ - format_expr, is_empty_block, is_simple_block, is_unsafe_block, prefer_next_line, rewrite_cond, - ExprType, RhsTactics, +use crate::formatting::{ + comment::{combine_strs_with_missing_comments, rewrite_comment}, + expr::{ + format_expr, is_empty_block, is_simple_block, is_unsafe_block, prefer_next_line, rewrite_cond, + ExprType, RhsTactics, + }, + lists::{itemize_list, write_list, ListFormatting}, + rewrite::{Rewrite, RewriteContext}, + shape::Shape, + source_map::SpanUtils, + spanned::Spanned, + utils::{ + contains_skip, extra_offset, first_line_width, inner_attributes, last_line_extendable, mk_sp, + semicolon_for_expr, trimmed_last_line_width, unicode_str_width, + }, }; -use crate::lists::{itemize_list, write_list, ListFormatting}; -use crate::rewrite::{Rewrite, RewriteContext}; -use crate::shape::Shape; -use crate::source_map::SpanUtils; -use crate::spanned::Spanned; -use crate::utils::{ - contains_skip, extra_offset, first_line_width, inner_attributes, last_line_extendable, mk_sp, - semicolon_for_expr, trimmed_last_line_width, unicode_str_width, +use crate::config::{ + lists::*, + Config, ControlBraceStyle, IndentStyle, MatchArmLeadingPipe, }; /// A simple wrapper type against `ast::Arm`. Used inside `write_list()`. diff --git a/rustfmt-core/rustfmt-lib/src/missed_spans.rs b/rustfmt-core/rustfmt-lib/src/formatting/missed_spans.rs similarity index 96% rename from rustfmt-core/rustfmt-lib/src/missed_spans.rs rename to rustfmt-core/rustfmt-lib/src/formatting/missed_spans.rs index f6fd7a5c81a..b80fa73dc6a 100644 --- a/rustfmt-core/rustfmt-lib/src/missed_spans.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/missed_spans.rs @@ -1,14 +1,19 @@ use rustc_span::{BytePos, Pos, Span}; -use crate::comment::{is_last_comment_block, rewrite_comment, CodeCharKind, CommentCodeSlices}; -use crate::config::file_lines::FileLines; -use crate::config::FileName; -use crate::shape::{Indent, Shape}; -use crate::source_map::LineRangeUtils; -use crate::utils::{ - count_lf_crlf, count_newlines, last_line_contains_single_line_comment, last_line_width, mk_sp, +use crate::config::{ + file_lines::FileLines, + FileName, +}; + +use crate::formatting::{ + comment::{is_last_comment_block, rewrite_comment, CodeCharKind, CommentCodeSlices}, + shape::{Indent, Shape}, + source_map::LineRangeUtils, + utils::{ + count_lf_crlf, count_newlines, last_line_contains_single_line_comment, last_line_width, mk_sp, + }, + visitor::FmtVisitor, }; -use crate::visitor::FmtVisitor; struct SnippetStatus { /// An offset to the current line from the beginning of the original snippet. diff --git a/rustfmt-core/rustfmt-lib/src/modules.rs b/rustfmt-core/rustfmt-lib/src/formatting/modules.rs similarity index 98% rename from rustfmt-core/rustfmt-lib/src/modules.rs rename to rustfmt-core/rustfmt-lib/src/formatting/modules.rs index d51ded36117..1dda132e4c4 100644 --- a/rustfmt-core/rustfmt-lib/src/modules.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/modules.rs @@ -6,12 +6,14 @@ use rustc_ast::ast; use rustc_ast::visit::Visitor; use rustc_span::symbol::{self, sym, Symbol}; -use crate::attr::MetaVisitor; +use crate::formatting::{ + attr::MetaVisitor, + items::is_mod_decl, + syntux::parser::{Directory, DirectoryOwnership, ModulePathSuccess, Parser}, + syntux::session::ParseSess, + utils::contains_skip, +}; use crate::config::FileName; -use crate::items::is_mod_decl; -use crate::syntux::parser::{Directory, DirectoryOwnership, ModulePathSuccess, Parser}; -use crate::syntux::session::ParseSess; -use crate::utils::contains_skip; mod visitor; diff --git a/rustfmt-core/rustfmt-lib/src/modules/visitor.rs b/rustfmt-core/rustfmt-lib/src/formatting/modules/visitor.rs similarity index 95% rename from rustfmt-core/rustfmt-lib/src/modules/visitor.rs rename to rustfmt-core/rustfmt-lib/src/formatting/modules/visitor.rs index 942e70d0e88..f4dd60f3c91 100644 --- a/rustfmt-core/rustfmt-lib/src/modules/visitor.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/modules/visitor.rs @@ -2,9 +2,11 @@ use rustc_ast::ast; use rustc_ast::visit::Visitor; use rustc_span::Symbol; -use crate::attr::MetaVisitor; -use crate::syntux::parser::Parser; -use crate::syntux::session::ParseSess; +use crate::formatting::{ + attr::MetaVisitor, + syntux::parser::Parser, + syntux::session::ParseSess, +}; pub(crate) struct ModItem { pub(crate) item: ast::Item, diff --git a/rustfmt-core/rustfmt-lib/src/overflow.rs b/rustfmt-core/rustfmt-lib/src/formatting/overflow.rs similarity index 97% rename from rustfmt-core/rustfmt-lib/src/overflow.rs rename to rustfmt-core/rustfmt-lib/src/formatting/overflow.rs index 7357da3dc88..c209fd15c60 100644 --- a/rustfmt-core/rustfmt-lib/src/overflow.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/overflow.rs @@ -7,23 +7,26 @@ use rustc_ast::token::DelimToken; use rustc_ast::{ast, ptr}; use rustc_span::Span; -use crate::closures; -use crate::config::lists::*; -use crate::expr::{ - can_be_overflowed_expr, is_every_expr_simple, is_method_call, is_nested_call, is_simple_expr, - rewrite_cond, -}; -use crate::lists::{ - definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, +use crate::formatting::{ + closures, + expr::{ + can_be_overflowed_expr, is_every_expr_simple, is_method_call, is_nested_call, is_simple_expr, + rewrite_cond, + }, + lists::{ + definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, + total_item_width, + }, + macros::MacroArg, + patterns::{can_be_overflowed_pat, TuplePatField}, + rewrite::{Rewrite, RewriteContext}, + shape::Shape, + source_map::SpanUtils, + spanned::Spanned, + types::{can_be_overflowed_type, SegmentParam}, + utils::{count_newlines, extra_offset, first_line_width, last_line_width, mk_sp}, }; -use crate::macros::MacroArg; -use crate::patterns::{can_be_overflowed_pat, TuplePatField}; -use crate::rewrite::{Rewrite, RewriteContext}; -use crate::shape::Shape; -use crate::source_map::SpanUtils; -use crate::spanned::Spanned; -use crate::types::{can_be_overflowed_type, SegmentParam}; -use crate::utils::{count_newlines, extra_offset, first_line_width, last_line_width, mk_sp}; +use crate::config::lists::*; const SHORT_ITEM_THRESHOLD: usize = 10; @@ -546,7 +549,7 @@ impl<'a> Context<'a> { && self.one_line_width != 0 && !list_items[0].has_comment() && !list_items[0].inner_as_ref().contains('\n') - && crate::lists::total_item_width(&list_items[0]) <= self.one_line_width + && total_item_width(&list_items[0]) <= self.one_line_width { tactic = DefinitiveListTactic::Horizontal; } else { diff --git a/rustfmt-core/rustfmt-lib/src/pairs.rs b/rustfmt-core/rustfmt-lib/src/formatting/pairs.rs similarity index 98% rename from rustfmt-core/rustfmt-lib/src/pairs.rs rename to rustfmt-core/rustfmt-lib/src/formatting/pairs.rs index 354e7a4e1d3..00f208be05c 100644 --- a/rustfmt-core/rustfmt-lib/src/pairs.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/pairs.rs @@ -2,10 +2,12 @@ use rustc_ast::ast; use crate::config::lists::*; use crate::config::IndentStyle; -use crate::rewrite::{Rewrite, RewriteContext}; -use crate::shape::Shape; -use crate::utils::{ - first_line_width, is_single_line, last_line_width, trimmed_last_line_width, wrap_str, +use crate::formatting::{ + rewrite::{Rewrite, RewriteContext}, + shape::Shape, + utils::{ + first_line_width, is_single_line, last_line_width, trimmed_last_line_width, wrap_str, + }, }; /// Sigils that decorate a binop pair. diff --git a/rustfmt-core/rustfmt-lib/src/patterns.rs b/rustfmt-core/rustfmt-lib/src/formatting/patterns.rs similarity index 96% rename from rustfmt-core/rustfmt-lib/src/patterns.rs rename to rustfmt-core/rustfmt-lib/src/formatting/patterns.rs index ef4b00b73c0..92a2c46b22b 100644 --- a/rustfmt-core/rustfmt-lib/src/patterns.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/patterns.rs @@ -2,22 +2,24 @@ use rustc_ast::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd, RangeS use rustc_ast::ptr; use rustc_span::{BytePos, Span}; -use crate::comment::{combine_strs_with_missing_comments, FindUncommented}; use crate::config::lists::*; -use crate::expr::{can_be_overflowed_expr, rewrite_unary_prefix, wrap_struct_field}; -use crate::lists::{ - definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, - struct_lit_tactic, write_list, ListFormatting, ListItem, Separator, +use crate::formatting::{ + comment::{combine_strs_with_missing_comments, FindUncommented}, + expr::{can_be_overflowed_expr, rewrite_unary_prefix, wrap_struct_field}, + lists::{ + definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, + struct_lit_tactic, write_list, ListFormatting, ListItem, Separator, + }, + macros::{rewrite_macro, MacroPosition}, + overflow, + pairs::{rewrite_pair, PairParts}, + rewrite::{Rewrite, RewriteContext}, + shape::Shape, + source_map::SpanUtils, + spanned::Spanned, + types::{rewrite_path, PathContext}, + utils::{format_mutability, mk_sp, rewrite_ident}, }; -use crate::macros::{rewrite_macro, MacroPosition}; -use crate::overflow; -use crate::pairs::{rewrite_pair, PairParts}; -use crate::rewrite::{Rewrite, RewriteContext}; -use crate::shape::Shape; -use crate::source_map::SpanUtils; -use crate::spanned::Spanned; -use crate::types::{rewrite_path, PathContext}; -use crate::utils::{format_mutability, mk_sp, rewrite_ident}; /// Returns `true` if the given pattern is "short". /// A short pattern is defined by the following grammar: diff --git a/rustfmt-core/rustfmt-lib/src/reorder.rs b/rustfmt-core/rustfmt-lib/src/formatting/reorder.rs similarity index 97% rename from rustfmt-core/rustfmt-lib/src/reorder.rs rename to rustfmt-core/rustfmt-lib/src/formatting/reorder.rs index 39094864e46..1f5312b2f73 100644 --- a/rustfmt-core/rustfmt-lib/src/reorder.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/reorder.rs @@ -12,15 +12,17 @@ use rustc_ast::{ast, attr}; use rustc_span::{symbol::sym, Span}; use crate::config::Config; -use crate::imports::{merge_use_trees, UseTree}; -use crate::items::{is_mod_decl, rewrite_extern_crate, rewrite_mod}; -use crate::lists::{itemize_list, write_list, ListFormatting, ListItem}; -use crate::rewrite::RewriteContext; -use crate::shape::Shape; -use crate::source_map::LineRangeUtils; -use crate::spanned::Spanned; -use crate::utils::{contains_skip, mk_sp}; -use crate::visitor::FmtVisitor; +use crate::formatting::{ + imports::{merge_use_trees, UseTree}, + items::{is_mod_decl, rewrite_extern_crate, rewrite_mod}, + lists::{itemize_list, write_list, ListFormatting, ListItem}, + rewrite::RewriteContext, + shape::Shape, + source_map::LineRangeUtils, + spanned::Spanned, + utils::{contains_skip, mk_sp}, + visitor::FmtVisitor, +}; /// Compare strings according to version sort (roughly equivalent to `strverscmp`) pub(crate) fn compare_as_versions(left: &str, right: &str) -> Ordering { diff --git a/rustfmt-core/rustfmt-lib/src/formatting/report.rs b/rustfmt-core/rustfmt-lib/src/formatting/report.rs new file mode 100644 index 00000000000..411d5e7078f --- /dev/null +++ b/rustfmt-core/rustfmt-lib/src/formatting/report.rs @@ -0,0 +1,194 @@ +use std::cell::{Ref, RefCell}; +use std::collections::{BTreeMap, BTreeSet, HashSet}; +use std::rc::Rc; + +use crate::formatting::FormattedSnippet; +use crate::result::{ErrorKind, FormatError}; +use crate::FileName; +use crate::NewlineStyle; + +/// Reports on any issues that occurred during a run of Rustfmt. +/// +/// Can be reported to the user using the `Display` impl on [`FormatReportFormatter`]. +#[derive(Debug, Clone)] +pub struct FormatReport { + format_result: Rc>>, + ignored_files: Rc>>, +} + +/// The result of formatting, including the formatted text and various +/// errors and warning arose while formatting. +#[derive(Debug, Clone, Default)] +pub struct FormatResult { + original_snippet: Option, + formatted_snippet: FormattedSnippet, + format_errors: HashSet, + newline_style: NewlineStyle, +} + +/// The inclusive range of the input which was not formatted, represented by a pair of line numbers. +#[derive(Debug, Clone, Copy)] +pub(crate) struct NonFormattedRange { + lo: usize, + hi: usize, +} + +impl FormatResult { + pub(crate) fn success( + snippet: String, + non_formatted_ranges: Vec, + original_snippet: Option, + newline_style: NewlineStyle, + ) -> Self { + let formatted_snippet = FormattedSnippet { + snippet, + non_formatted_ranges, + }; + FormatResult { + original_snippet, + formatted_snippet, + format_errors: HashSet::new(), + newline_style, + } + } + + pub(crate) fn all_errors(&self) -> impl Iterator { + self.format_errors.iter() + } + + pub(crate) fn errors_excluding_macro(&self) -> impl Iterator { + self.format_errors + .iter() + .filter(|e| e.kind() != ErrorKind::MacroFormatError) + } + + /// Return the newline style used to format the result. + pub fn newline_style(&self) -> NewlineStyle { + self.newline_style.clone() + } + + pub fn original_text(&self) -> Option<&str> { + self.original_snippet.as_ref().map(|s| s.as_str()) + } + + pub fn formatted_text(&self) -> &str { + &self.formatted_snippet.snippet + } + + pub(crate) fn formatted_snippet(&self) -> &FormattedSnippet { + &self.formatted_snippet + } +} + +impl FormatReport { + pub fn new() -> FormatReport { + FormatReport { + format_result: Rc::new(RefCell::new(BTreeMap::new())), + ignored_files: Rc::new(RefCell::new(BTreeSet::new())), + } + } + + /// Returns the result of formatting the given input, including the formatted text and + /// various warnings and errors encountered during formatting. + // + // NOTE: Avoid using this method internally: use `format_result_as_rc` instead. + pub fn format_result(&self) -> impl Iterator { + Ref::leak(RefCell::borrow(&self.format_result)).iter() + } + + pub(crate) fn format_result_as_rc(&self) -> Rc>> { + Rc::clone(&self.format_result) + } + + /// FIXME(topecongiro): reduce visibility. + pub fn merge(&mut self, other: Self) { + self.format_result + .borrow_mut() + .append(&mut other.format_result.borrow_mut()); + self.ignored_files + .borrow_mut() + .append(&mut other.ignored_files.borrow_mut()); + } + + pub(crate) fn add_ignored_file(&self, file_name: FileName) { + self.ignored_files.borrow_mut().insert(file_name); + } + + pub(crate) fn add_format_result(&self, file_name: FileName, format_result: FormatResult) { + let mut format_results = self.format_result.borrow_mut(); + let mut original_format_result = format_results.entry(file_name).or_default(); + original_format_result.formatted_snippet = format_result.formatted_snippet; + original_format_result + .format_errors + .extend(format_result.format_errors); + if original_format_result.original_snippet.is_none() { + original_format_result.original_snippet = format_result.original_snippet; + } + } + + pub(crate) fn append_errors(&self, f: FileName, errors: impl Iterator) { + let mut format_result = self.format_result.borrow_mut(); + let format_errors = &mut format_result.entry(f).or_default().format_errors; + for err in errors { + format_errors.insert(err); + } + } + + pub(crate) fn add_macro_format_failure(&self, file_name: FileName) { + self.add_format_error( + file_name, + FormatError::err_without_line_info(ErrorKind::MacroFormatError), + ); + } + + pub(crate) fn add_license_failure(&self, file_name: FileName) { + self.add_format_error( + file_name, + FormatError::err_without_line_info(ErrorKind::LicenseCheck), + ); + } + + pub(crate) fn add_format_error(&self, file_name: FileName, format_error: FormatError) { + self.format_result + .borrow_mut() + .entry(file_name) + .or_default() + .format_errors + .insert(format_error); + } + + pub fn has_errors(&self) -> bool { + RefCell::borrow(&self.format_result) + .iter() + .any(|(_, format_result)| format_result.errors_excluding_macro().count() > 0) + } + + pub(crate) fn warning_count(&self) -> usize { + RefCell::borrow(&self.format_result) + .iter() + .map(|(_, format_result)| format_result.errors_excluding_macro().count()) + .sum() + } + + /// Whether any warnings or errors are present in the report. + pub fn has_warnings(&self) -> bool { + self.has_errors() + } +} + +impl NonFormattedRange { + pub(crate) fn new(lo: usize, hi: usize) -> NonFormattedRange { + NonFormattedRange { lo, hi } + } + + pub(crate) fn shift_up(self) -> NonFormattedRange { + NonFormattedRange { + lo: self.lo - 1, + hi: self.hi - 1, + } + } + + pub(crate) fn contains(&self, line: usize) -> bool { + self.lo <= line && line <= self.hi + } +} diff --git a/rustfmt-core/rustfmt-lib/src/rewrite.rs b/rustfmt-core/rustfmt-lib/src/formatting/rewrite.rs similarity index 94% rename from rustfmt-core/rustfmt-lib/src/rewrite.rs rename to rustfmt-core/rustfmt-lib/src/formatting/rewrite.rs index 6e984fda9b1..306e4658b41 100644 --- a/rustfmt-core/rustfmt-lib/src/rewrite.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/rewrite.rs @@ -7,11 +7,13 @@ use rustc_ast::ptr; use rustc_span::Span; use crate::config::{Config, IndentStyle}; -use crate::shape::Shape; -use crate::skip::SkipContext; -use crate::syntux::session::ParseSess; -use crate::visitor::SnippetProvider; -use crate::{FormatReport, NonFormattedRange}; +use crate::formatting::{ + report::{FormatReport, NonFormattedRange}, + shape::Shape, + skip::SkipContext, + syntux::session::ParseSess, + visitor::SnippetProvider, +}; pub(crate) trait Rewrite { /// Rewrite self into shape. diff --git a/rustfmt-core/rustfmt-lib/src/shape.rs b/rustfmt-core/rustfmt-lib/src/formatting/shape.rs similarity index 100% rename from rustfmt-core/rustfmt-lib/src/shape.rs rename to rustfmt-core/rustfmt-lib/src/formatting/shape.rs diff --git a/rustfmt-core/rustfmt-lib/src/skip.rs b/rustfmt-core/rustfmt-lib/src/formatting/skip.rs similarity index 100% rename from rustfmt-core/rustfmt-lib/src/skip.rs rename to rustfmt-core/rustfmt-lib/src/formatting/skip.rs diff --git a/rustfmt-core/rustfmt-lib/src/source_map.rs b/rustfmt-core/rustfmt-lib/src/formatting/source_map.rs similarity index 97% rename from rustfmt-core/rustfmt-lib/src/source_map.rs rename to rustfmt-core/rustfmt-lib/src/formatting/source_map.rs index 76e0d24cf1e..68140f0108c 100644 --- a/rustfmt-core/rustfmt-lib/src/source_map.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/source_map.rs @@ -3,9 +3,11 @@ use rustc_span::{BytePos, Span}; -use crate::comment::FindUncommented; use crate::config::file_lines::LineRange; -use crate::visitor::SnippetProvider; +use crate::formatting::{ + comment::FindUncommented, + visitor::SnippetProvider, +}; pub(crate) trait SpanUtils { fn span_after(&self, original: Span, needle: &str) -> BytePos; diff --git a/rustfmt-core/rustfmt-lib/src/spanned.rs b/rustfmt-core/rustfmt-lib/src/formatting/spanned.rs similarity index 95% rename from rustfmt-core/rustfmt-lib/src/spanned.rs rename to rustfmt-core/rustfmt-lib/src/formatting/spanned.rs index 976af78e3d1..836fdcb0adf 100644 --- a/rustfmt-core/rustfmt-lib/src/spanned.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/spanned.rs @@ -3,8 +3,11 @@ use std::cmp::max; use rustc_ast::{ast, ptr}; use rustc_span::{source_map, Span}; -use crate::macros::MacroArg; -use crate::utils::{mk_sp, outer_attributes}; +use crate::formatting::{ + items::{is_named_param, span_lo_for_param}, + macros::MacroArg, + utils::{mk_sp, outer_attributes}, +}; /// Spanned returns a span including attributes, if available. pub(crate) trait Spanned { @@ -104,8 +107,8 @@ impl Spanned for ast::Arm { impl Spanned for ast::Param { fn span(&self) -> Span { - if crate::items::is_named_param(self) { - mk_sp(crate::items::span_lo_for_param(self), self.ty.span.hi()) + if is_named_param(self) { + mk_sp(span_lo_for_param(self), self.ty.span.hi()) } else { self.ty.span } diff --git a/rustfmt-core/rustfmt-lib/src/stmt.rs b/rustfmt-core/rustfmt-lib/src/formatting/stmt.rs similarity index 91% rename from rustfmt-core/rustfmt-lib/src/stmt.rs rename to rustfmt-core/rustfmt-lib/src/formatting/stmt.rs index 0c289bb4f3e..7e788581bc9 100644 --- a/rustfmt-core/rustfmt-lib/src/stmt.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/stmt.rs @@ -1,13 +1,15 @@ use rustc_ast::ast; use rustc_span::Span; -use crate::comment::recover_comment_removed; -use crate::expr::{format_expr, ExprType}; -use crate::rewrite::{Rewrite, RewriteContext}; -use crate::shape::Shape; -use crate::source_map::LineRangeUtils; -use crate::spanned::Spanned; -use crate::utils::semicolon_for_stmt; +use crate::formatting::{ + comment::recover_comment_removed, + expr::{format_expr, ExprType}, + rewrite::{Rewrite, RewriteContext}, + shape::Shape, + source_map::LineRangeUtils, + spanned::Spanned, + utils::semicolon_for_stmt, +}; pub(crate) struct Stmt<'a> { inner: &'a ast::Stmt, diff --git a/rustfmt-core/rustfmt-lib/src/string.rs b/rustfmt-core/rustfmt-lib/src/formatting/string.rs similarity index 99% rename from rustfmt-core/rustfmt-lib/src/string.rs rename to rustfmt-core/rustfmt-lib/src/formatting/string.rs index aade2f74d5f..08960959ebf 100644 --- a/rustfmt-core/rustfmt-lib/src/string.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/string.rs @@ -5,8 +5,10 @@ use unicode_categories::UnicodeCategories; use unicode_segmentation::UnicodeSegmentation; use crate::config::Config; -use crate::shape::Shape; -use crate::utils::{unicode_str_width, wrap_str}; +use crate::formatting::{ + shape::Shape, + utils::{unicode_str_width, wrap_str}, +}; const MIN_STRING: usize = 10; @@ -357,7 +359,7 @@ fn graphemes_width(graphemes: &[&str]) -> usize { mod test { use super::{break_string, detect_url, rewrite_string, SnippetState, StringFormat}; use crate::config::Config; - use crate::shape::{Indent, Shape}; + use crate::formatting::shape::{Indent, Shape}; use unicode_segmentation::UnicodeSegmentation; #[test] diff --git a/rustfmt-core/rustfmt-lib/src/syntux.rs b/rustfmt-core/rustfmt-lib/src/formatting/syntux.rs similarity index 100% rename from rustfmt-core/rustfmt-lib/src/syntux.rs rename to rustfmt-core/rustfmt-lib/src/formatting/syntux.rs diff --git a/rustfmt-core/rustfmt-lib/src/syntux/parser.rs b/rustfmt-core/rustfmt-lib/src/formatting/syntux/parser.rs similarity index 99% rename from rustfmt-core/rustfmt-lib/src/syntux/parser.rs rename to rustfmt-core/rustfmt-lib/src/formatting/syntux/parser.rs index 2964b530ad0..8b82e97f8fa 100644 --- a/rustfmt-core/rustfmt-lib/src/syntux/parser.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/syntux/parser.rs @@ -7,7 +7,7 @@ use rustc_errors::{Diagnostic, PResult}; use rustc_parse::{new_parser_from_file, parser::Parser as RawParser}; use rustc_span::{symbol::kw, Span}; -use crate::syntux::session::ParseSess; +use crate::formatting::syntux::session::ParseSess; use crate::{Config, Input}; pub(crate) type DirectoryOwnership = rustc_expand::module::DirectoryOwnership; diff --git a/rustfmt-core/rustfmt-lib/src/syntux/session.rs b/rustfmt-core/rustfmt-lib/src/formatting/syntux/session.rs similarity index 97% rename from rustfmt-core/rustfmt-lib/src/syntux/session.rs rename to rustfmt-core/rustfmt-lib/src/formatting/syntux/session.rs index 399bac87834..19415d4617e 100644 --- a/rustfmt-core/rustfmt-lib/src/syntux/session.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/syntux/session.rs @@ -11,12 +11,18 @@ use rustc_span::{ symbol, BytePos, Span, }; -use crate::config::file_lines::LineRange; +use crate::config::{ + Config, + FileName, + file_lines::LineRange, +}; use crate::ignore_path::IgnorePathSet; -use crate::source_map::LineRangeUtils; -use crate::utils::starts_with_newline; -use crate::visitor::SnippetProvider; -use crate::{Config, FileName, OperationError}; +use crate::result::OperationError; +use crate::formatting::{ + source_map::LineRangeUtils, + utils::starts_with_newline, + visitor::SnippetProvider, +}; /// ParseSess holds structs necessary for constructing a parser. pub(crate) struct ParseSess { @@ -29,10 +35,10 @@ pub(crate) struct ParseSess { struct SilentEmitter; impl Emitter for SilentEmitter { + fn emit_diagnostic(&mut self, _db: &Diagnostic) {} fn source_map(&self) -> Option<&Lrc> { None } - fn emit_diagnostic(&mut self, _db: &Diagnostic) {} } fn silent_emitter() -> Box { @@ -57,9 +63,6 @@ impl SilentOnIgnoredFilesEmitter { } impl Emitter for SilentOnIgnoredFilesEmitter { - fn source_map(&self) -> Option<&Lrc> { - None - } fn emit_diagnostic(&mut self, db: &Diagnostic) { if db.level == DiagnosticLevel::Fatal { return self.handle_non_ignoreable_error(db); @@ -80,6 +83,10 @@ impl Emitter for SilentOnIgnoredFilesEmitter { } self.handle_non_ignoreable_error(db); } + + fn source_map(&self) -> Option<&Lrc> { + None + } } fn default_handler( @@ -88,18 +95,11 @@ fn default_handler( can_reset: Rc>, hide_parse_errors: bool, ) -> Handler { - let supports_color = term::stderr().map_or(false, |term| term.supports_color()); - let color_cfg = if supports_color { - ColorConfig::Auto - } else { - ColorConfig::Never - }; - let emitter = if hide_parse_errors { silent_emitter() } else { Box::new(EmitterWriter::stderr( - color_cfg, + ColorConfig::Auto, Some(source_map.clone()), false, false, @@ -276,7 +276,7 @@ mod tests { use super::*; use crate::config::IgnoreList; use crate::is_nightly_channel; - use crate::utils::mk_sp; + use crate::formatting::utils::mk_sp; use rustc_span::{FileName as SourceMapFileName, MultiSpan, DUMMY_SP}; use std::path::PathBuf; diff --git a/rustfmt-core/rustfmt-lib/src/types.rs b/rustfmt-core/rustfmt-lib/src/formatting/types.rs similarity index 97% rename from rustfmt-core/rustfmt-lib/src/types.rs rename to rustfmt-core/rustfmt-lib/src/formatting/types.rs index ebf6d397ae7..081e4d031f0 100644 --- a/rustfmt-core/rustfmt-lib/src/types.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/types.rs @@ -4,22 +4,28 @@ use std::ops::Deref; use rustc_ast::ast::{self, FnRetTy, Mutability}; use rustc_span::{symbol::kw, BytePos, Span}; -use crate::config::lists::*; -use crate::config::{IndentStyle, TypeDensity}; -use crate::expr::{format_expr, rewrite_assign_rhs, rewrite_tuple, rewrite_unary_prefix, ExprType}; -use crate::lists::{ - definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, +use crate::config::{ + lists::*, + IndentStyle, + TypeDensity, }; -use crate::macros::{rewrite_macro, MacroPosition}; -use crate::overflow; -use crate::pairs::{rewrite_pair, PairParts}; -use crate::rewrite::{Rewrite, RewriteContext}; -use crate::shape::Shape; -use crate::source_map::SpanUtils; -use crate::spanned::Spanned; -use crate::utils::{ - colon_spaces, extra_offset, first_line_width, format_extern, format_mutability, - last_line_extendable, last_line_width, mk_sp, rewrite_ident, +use crate::formatting::{ + expr::{format_expr, rewrite_assign_rhs, rewrite_tuple, rewrite_unary_prefix, ExprType}, + lists::{ + definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, + }, + macros::{rewrite_macro, MacroPosition}, + overflow, + pairs::{rewrite_pair, PairParts}, + rewrite::{Rewrite, RewriteContext}, + shape::Shape, + source_map::SpanUtils, + spanned::Spanned, + utils::{ + colon_spaces, extra_offset, first_line_width, format_extern, format_mutability, + last_line_extendable, last_line_width, mk_sp, rewrite_ident, + format_unsafety, + }, }; #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -780,7 +786,7 @@ fn rewrite_bare_fn( result.push_str("> "); } - result.push_str(crate::utils::format_unsafety(bare_fn.unsafety)); + result.push_str(format_unsafety(bare_fn.unsafety)); result.push_str(&format_extern( bare_fn.ext, diff --git a/rustfmt-core/rustfmt-lib/src/formatting/util.rs b/rustfmt-core/rustfmt-lib/src/formatting/util.rs new file mode 100644 index 00000000000..4e4e03c3f5c --- /dev/null +++ b/rustfmt-core/rustfmt-lib/src/formatting/util.rs @@ -0,0 +1,227 @@ +use crate::{config::Config, emitter::Verbosity, Input, NewlineStyle, OperationSetting}; +use crate::formatting::{ + comment::LineClasses, + FormattedSnippet, + shape::Indent, + utils::indent_next_line, +}; + +/// Format the given snippet. The snippet is expected to be *complete* code. +/// When we cannot parse the given snippet, this function returns `None`. +pub(crate) fn format_snippet(snippet: &str, config: &Config) -> Option { + let mut config = config.clone(); + std::panic::catch_unwind(move || { + config.set().hide_parse_errors(true); + + let result = { + let input = Input::Text(snippet.into()); + crate::format( + input, + &config, + OperationSetting { + verbosity: Verbosity::Quiet, + ..OperationSetting::default() + }, + ) + }; + match result { + Ok(report) if !report.has_errors() => { + match report.format_result_as_rc().borrow().iter().next() { + Some((_, format_result)) + if format_result.all_errors().count() == 0 + && !format_result.formatted_text().is_empty() => + { + Some(format_result.formatted_snippet().clone()) + } + _ => None, + } + } + _ => None, + } + }) + // Discard panics encountered while formatting the snippet + // The ? operator is needed to remove the extra Option + .ok()? +} + +/// Format the given code block. Mainly targeted for code block in comment. +/// The code block may be incomplete (i.e., parser may be unable to parse it). +/// To avoid panic in parser, we wrap the code block with a dummy function. +/// The returned code block does **not** end with newline. +pub(crate) fn format_code_block(code_snippet: &str, config: &Config) -> Option { + const FN_MAIN_PREFIX: &str = "fn main() {\n"; + + fn enclose_in_main_block(s: &str, config: &Config) -> String { + let indent = Indent::from_width(config, config.tab_spaces()); + let mut result = String::with_capacity(s.len() * 2); + result.push_str(FN_MAIN_PREFIX); + let mut need_indent = true; + for (kind, line) in LineClasses::new(s) { + if need_indent { + result.push_str(&indent.to_string(config)); + } + result.push_str(&line); + result.push('\n'); + need_indent = indent_next_line(kind); + } + result.push('}'); + result + } + + // Wrap the given code block with `fn main()` if it does not have one. + let snippet = enclose_in_main_block(code_snippet, config); + let mut result = String::with_capacity(snippet.len()); + let mut is_first = true; + + // While formatting the code, ignore the config's newline style setting and always use "\n" + // instead of "\r\n" for the newline characters. This is ok because the output here is + // not directly outputted by rustfmt command, but used by the comment formatter's input. + // We have output-file-wide "\n" ==> "\r\n" conversion process after here if it's necessary. + let mut config_with_unix_newline = config.clone(); + config_with_unix_newline + .set() + .newline_style(NewlineStyle::Unix); + let mut formatted = format_snippet(&snippet, &config_with_unix_newline)?; + // Remove wrapping main block + formatted.unwrap_code_block(); + + // Trim "fn main() {" on the first line and "}" on the last line, + // then unindent the whole code block. + let block_len = formatted + .snippet + .rfind('}') + .unwrap_or_else(|| formatted.snippet.len()); + let mut is_indented = true; + let indent_str = Indent::from_width(config, config.tab_spaces()).to_string(config); + for (kind, ref line) in LineClasses::new(&formatted.snippet[FN_MAIN_PREFIX.len()..block_len]) { + if !is_first { + result.push('\n'); + } else { + is_first = false; + } + let trimmed_line = if !is_indented { + line + } else if line.len() > config.max_width() { + // If there are lines that are larger than max width, we cannot tell + // whether we have succeeded but have some comments or strings that + // are too long, or we have failed to format code block. We will be + // conservative and just return `None` in this case. + return None; + } else if line.len() > indent_str.len() { + // Make sure that the line has leading whitespaces. + if line.starts_with(indent_str.as_ref()) { + let offset = if config.hard_tabs() { + 1 + } else { + config.tab_spaces() + }; + &line[offset..] + } else { + line + } + } else { + line + }; + result.push_str(trimmed_line); + is_indented = indent_next_line(kind); + } + Some(FormattedSnippet { + snippet: result, + non_formatted_ranges: formatted.non_formatted_ranges, + }) +} + +#[cfg(test)] +mod unit_tests { + use super::*; + + #[test] + fn test_no_panic_on_format_snippet_and_format_code_block() { + // `format_snippet()` and `format_code_block()` should not panic + // even when we cannot parse the given snippet. + let snippet = "let"; + assert!(format_snippet(snippet, &Config::default()).is_none()); + assert!(format_code_block(snippet, &Config::default()).is_none()); + } + + fn test_format_inner(formatter: F, input: &str, expected: &str) -> bool + where + F: Fn(&str, &Config) -> Option, + { + let output = formatter(input, &Config::default()); + output.is_some() && output.unwrap().snippet == expected + } + + #[test] + fn test_format_snippet() { + let snippet = "fn main() { println!(\"hello, world\"); }"; + #[cfg(not(windows))] + let expected = "fn main() {\n \ + println!(\"hello, world\");\n\ + }\n"; + #[cfg(windows)] + let expected = "fn main() {\r\n \ + println!(\"hello, world\");\r\n\ + }\r\n"; + assert!(test_format_inner(format_snippet, snippet, expected)); + } + + #[test] + fn test_format_code_block_fail() { + #[rustfmt::skip] + let code_block = "this_line_is_100_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(x, y, z);"; + assert!(format_code_block(code_block, &Config::default()).is_none()); + } + + #[test] + fn test_format_code_block() { + // simple code block + let code_block = "let x=3;"; + let expected = "let x = 3;"; + assert!(test_format_inner(format_code_block, code_block, expected)); + + // more complex code block, taken from chains.rs. + let code_block = +"let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { +( +chain_indent(context, shape.add_offset(parent_rewrite.len())), +context.config.indent_style() == IndentStyle::Visual || is_small_parent, +) +} else if is_block_expr(context, &parent, &parent_rewrite) { +match context.config.indent_style() { +// Try to put the first child on the same line with parent's last line +IndentStyle::Block => (parent_shape.block_indent(context.config.tab_spaces()), true), +// The parent is a block, so align the rest of the chain with the closing +// brace. +IndentStyle::Visual => (parent_shape, false), +} +} else { +( +chain_indent(context, shape.add_offset(parent_rewrite.len())), +false, +) +}; +"; + let expected = +"let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { + ( + chain_indent(context, shape.add_offset(parent_rewrite.len())), + context.config.indent_style() == IndentStyle::Visual || is_small_parent, + ) +} else if is_block_expr(context, &parent, &parent_rewrite) { + match context.config.indent_style() { + // Try to put the first child on the same line with parent's last line + IndentStyle::Block => (parent_shape.block_indent(context.config.tab_spaces()), true), + // The parent is a block, so align the rest of the chain with the closing + // brace. + IndentStyle::Visual => (parent_shape, false), + } +} else { + ( + chain_indent(context, shape.add_offset(parent_rewrite.len())), + false, + ) +};"; + assert!(test_format_inner(format_code_block, code_block, expected)); + } +} diff --git a/rustfmt-core/rustfmt-lib/src/utils.rs b/rustfmt-core/rustfmt-lib/src/formatting/utils.rs similarity index 99% rename from rustfmt-core/rustfmt-lib/src/utils.rs rename to rustfmt-core/rustfmt-lib/src/formatting/utils.rs index c73eae5cd06..4c9bef7cb8a 100644 --- a/rustfmt-core/rustfmt-lib/src/utils.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/utils.rs @@ -9,10 +9,12 @@ use rustc_ast_pretty::pprust; use rustc_span::{sym, symbol, BytePos, ExpnId, Span, Symbol, SyntaxContext}; use unicode_width::UnicodeWidthStr; -use crate::comment::{filter_normal_code, CharClasses, FullCodeCharKind, LineClasses}; use crate::config::Config; -use crate::rewrite::RewriteContext; -use crate::shape::{Indent, Shape}; +use crate::formatting::{ + comment::{filter_normal_code, CharClasses, FullCodeCharKind, LineClasses}, + rewrite::RewriteContext, + shape::{Indent, Shape}, +}; #[inline] pub(crate) fn depr_skip_annotation() -> Symbol { diff --git a/rustfmt-core/rustfmt-lib/src/vertical.rs b/rustfmt-core/rustfmt-lib/src/formatting/vertical.rs similarity index 94% rename from rustfmt-core/rustfmt-lib/src/vertical.rs rename to rustfmt-core/rustfmt-lib/src/formatting/vertical.rs index 95d1d5c2d7e..f4cd14e8c01 100644 --- a/rustfmt-core/rustfmt-lib/src/vertical.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/vertical.rs @@ -6,20 +6,22 @@ use itertools::Itertools; use rustc_ast::ast; use rustc_span::{BytePos, Span}; -use crate::comment::combine_strs_with_missing_comments; -use crate::config::lists::*; -use crate::expr::rewrite_field; -use crate::items::{rewrite_struct_field, rewrite_struct_field_prefix}; -use crate::lists::{ - definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, -}; -use crate::rewrite::{Rewrite, RewriteContext}; -use crate::shape::{Indent, Shape}; -use crate::source_map::SpanUtils; -use crate::spanned::Spanned; -use crate::utils::{ - contains_skip, is_attributes_extendable, mk_sp, rewrite_ident, trimmed_last_line_width, +use crate::formatting::{ + comment::combine_strs_with_missing_comments, + expr::rewrite_field, + items::{rewrite_struct_field, rewrite_struct_field_prefix}, + lists::{ + definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, + }, + rewrite::{Rewrite, RewriteContext}, + shape::{Indent, Shape}, + source_map::SpanUtils, + spanned::Spanned, + utils::{ + contains_skip, is_attributes_extendable, mk_sp, rewrite_ident, trimmed_last_line_width, + }, }; +use crate::config::lists::*; pub(crate) trait AlignedItem { fn skip(&self) -> bool; diff --git a/rustfmt-core/rustfmt-lib/src/visitor.rs b/rustfmt-core/rustfmt-lib/src/formatting/visitor.rs similarity index 97% rename from rustfmt-core/rustfmt-lib/src/visitor.rs rename to rustfmt-core/rustfmt-lib/src/formatting/visitor.rs index 3e7f21ea2f0..6aad64dc238 100644 --- a/rustfmt-core/rustfmt-lib/src/visitor.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/visitor.rs @@ -4,28 +4,31 @@ use std::rc::Rc; use rustc_ast::{ast, token::DelimToken, visit}; use rustc_span::{symbol, BytePos, Pos, Span}; -use crate::attr::*; -use crate::comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; use crate::config::{BraceStyle, Config}; -use crate::items::{ - format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, - rewrite_associated_impl_type, rewrite_extern_crate, rewrite_opaque_impl_type, - rewrite_opaque_type, rewrite_type_alias, FnBraceStyle, FnSig, StaticParts, StructParts, +use crate::formatting::{ + attr::*, + comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}, + report::{FormatReport, NonFormattedRange}, + items::{ + format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, + rewrite_associated_impl_type, rewrite_extern_crate, rewrite_opaque_impl_type, + rewrite_opaque_type, rewrite_type_alias, FnBraceStyle, FnSig, StaticParts, StructParts, + }, + macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition}, + rewrite::{Rewrite, RewriteContext}, + shape::{Indent, Shape}, + skip::{is_skip_attr, SkipContext}, + source_map::{LineRangeUtils, SpanUtils}, + spanned::Spanned, + stmt::Stmt, + syntux::session::ParseSess, + utils::{ + self, contains_skip, count_newlines, depr_skip_annotation, inner_attributes, + last_line_contains_single_line_comment, last_line_width, mk_sp, ptr_vec_to_ref_vec, + rewrite_ident, stmt_expr, + }, }; -use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition}; -use crate::rewrite::{Rewrite, RewriteContext}; -use crate::shape::{Indent, Shape}; -use crate::skip::{is_skip_attr, SkipContext}; -use crate::source_map::{LineRangeUtils, SpanUtils}; -use crate::spanned::Spanned; -use crate::stmt::Stmt; -use crate::syntux::session::ParseSess; -use crate::utils::{ - self, contains_skip, count_newlines, depr_skip_annotation, inner_attributes, - last_line_contains_single_line_comment, last_line_width, mk_sp, ptr_vec_to_ref_vec, - rewrite_ident, stmt_expr, -}; -use crate::{ErrorKind, FormatError, FormatReport, NonFormattedRange}; +use crate::result::{ErrorKind, FormatError}; /// Creates a string slice corresponding to the specified span. pub(crate) struct SnippetProvider { diff --git a/rustfmt-core/rustfmt-lib/src/lib.rs b/rustfmt-core/rustfmt-lib/src/lib.rs index d503c17d25c..43dc6a8e2f7 100644 --- a/rustfmt-core/rustfmt-lib/src/lib.rs +++ b/rustfmt-core/rustfmt-lib/src/lib.rs @@ -7,498 +7,37 @@ extern crate lazy_static; #[macro_use] extern crate log; -use std::cell::{Ref, RefCell}; -use std::collections::{BTreeMap, BTreeSet, HashSet}; -use std::io; -use std::panic; use std::path::PathBuf; -use std::rc::Rc; use rustc_ast::ast; -use rustc_span::{symbol, Span}; -use thiserror::Error; pub use crate::config::{ load_config, CliOptions, Config, Edition, FileLines, FileName, NewlineStyle, Range, }; pub use crate::emitter::rustfmt_diff::{ModifiedChunk, ModifiedLines}; pub use crate::format_report_formatter::{FormatReportFormatter, FormatReportFormatterBuilder}; +pub use crate::formatting::report::{FormatReport, FormatResult}; use crate::formatting::format_input_inner; use crate::{ - comment::LineClasses, emitter::{Color, Verbosity}, - shape::Indent, - syntux::parser::DirectoryOwnership, - syntux::session::ParseSess, - utils::indent_next_line, + result::{ErrorKind, FormatError, OperationError}, }; -#[macro_use] -mod utils; - #[cfg(feature = "config")] pub mod config; #[cfg(feature = "emitter")] pub mod emitter; -mod attr; -mod chains; -mod closures; -mod comment; -mod expr; mod format_report_formatter; pub(crate) mod formatting; mod ignore_path; -mod imports; -mod items; -mod lists; -mod macros; -mod matches; -mod missed_spans; -pub(crate) mod modules; -mod overflow; -mod pairs; -mod patterns; mod release_channel; -mod reorder; -mod rewrite; -mod shape; -mod skip; -pub(crate) mod source_map; -mod spanned; -mod stmt; -mod string; -mod syntux; +pub mod result; #[cfg(test)] mod test; -mod types; -mod vertical; -pub(crate) mod visitor; - -/// The various errors that can occur during formatting. -#[derive(Error, Clone, Debug, Hash, Eq, PartialEq)] -pub enum ErrorKind { - /// Line has exceeded character limit (found, maximum). - #[error( - "line formatted, but exceeded maximum width \ - (maximum: {1} (see `max_width` option), found: {0})" - )] - LineOverflow(usize, usize), - /// Line ends in whitespace. - #[error("left behind trailing whitespace")] - TrailingWhitespace, - /// License check has failed. - #[error("license check failed")] - LicenseCheck, - /// Used deprecated skip attribute. - #[error("`rustfmt_skip` is deprecated; use `rustfmt::skip`")] - DeprecatedAttr, - /// Used a rustfmt:: attribute other than skip or skip::macros. - #[error("invalid attribute")] - BadAttr, - /// Failed to format macro calls. - #[error("failed to format macro calls")] - MacroFormatError, -} - -#[derive(Error, Clone, Debug, Hash, Eq, PartialEq)] -#[error("{kind}")] -pub struct FormatError { - kind: ErrorKind, - line_num: Option, - line_str: Option, -} - -impl FormatError { - pub(crate) fn new(kind: ErrorKind, line_num: usize, line_str: String) -> Self { - FormatError { - kind, - line_num: Some(line_num), - line_str: Some(line_str), - } - } - - pub(crate) fn err_without_line_info(kind: ErrorKind) -> Self { - FormatError { - kind, - line_num: None, - line_str: None, - } - } - - pub(crate) fn from_span(kind: ErrorKind, parse_sess: &ParseSess, span: Span) -> Self { - FormatError { - kind, - line_num: Some(parse_sess.line_of_byte_pos(span.lo())), - line_str: Some(parse_sess.span_to_first_line_string(span)), - } - } - - // (space, target) - pub(crate) fn format_len(&self) -> Option<(usize, usize)> { - match self.kind { - ErrorKind::LineOverflow(found, max) => Some((max, found - max)), - ErrorKind::TrailingWhitespace - | ErrorKind::DeprecatedAttr - | ErrorKind::BadAttr - | ErrorKind::LicenseCheck => { - let len = self.line_str.as_ref().map_or(0, |s| s.len()); - let trailing_ws_start = self - .line_str - .as_ref() - .and_then(|s| s.rfind(|c: char| !c.is_whitespace())) - .map(|pos| pos + 1) - .unwrap_or(0); - Some((trailing_ws_start, len - trailing_ws_start)) - } - _ => None, - } - } -} - -/// Result of formatting a snippet of code along with ranges of lines that didn't get formatted, -/// i.e., that got returned as they were originally. -#[derive(Debug, Clone, Default)] -struct FormattedSnippet { - snippet: String, - non_formatted_ranges: Vec, -} - -impl FormattedSnippet { - /// In case the snippet needed to be wrapped in a function, this shifts down the ranges of - /// non-formatted code. - fn unwrap_code_block(&mut self) { - self.non_formatted_ranges.iter_mut().for_each(|range| { - *range = range.shift_up(); - }); - } - - /// Returns `true` if the line n did not get formatted. - fn is_line_non_formatted(&self, n: usize) -> bool { - self.non_formatted_ranges - .iter() - .any(|range| range.contains(n)) - } -} - -/// The result of formatting, including the formatted text and various -/// errors and warning arose while formatting. -#[derive(Debug, Clone, Default)] -pub struct FormatResult { - original_snippet: Option, - formatted_snippet: FormattedSnippet, - format_errors: HashSet, - newline_style: NewlineStyle, -} - -#[derive(Debug, Clone, Copy)] -struct NonFormattedRange { - lo: usize, - hi: usize, -} - -impl NonFormattedRange { - pub(crate) fn new(lo: usize, hi: usize) -> NonFormattedRange { - NonFormattedRange { lo, hi } - } - - fn shift_up(self) -> NonFormattedRange { - NonFormattedRange { - lo: self.lo - 1, - hi: self.hi - 1, - } - } - - fn contains(&self, line: usize) -> bool { - self.lo <= line && line <= self.hi - } -} - -#[derive(Error, Debug)] -pub enum OperationError { - /// The user mandated a version and the current version of rustfmt does not - /// satisfy that requirement. - #[error("version mismatch")] - VersionMismatch, - /// An io error during reading or writing. - #[error("io error: {0}")] - IoError(io::Error), - /// Invalid glob pattern in `ignore` configuration option. - #[error("invalid glob pattern found in ignore list: {0}")] - InvalidGlobPattern(ignore::Error), - /// Parse error occurred while parsing the input. - #[error("failed to parse {input:?}")] - ParseError { input: FileName, is_panic: bool }, -} - -impl OperationError { - #[cfg(test)] - pub fn is_parse_error(&self) -> bool { - match self { - OperationError::ParseError { .. } => true, - _ => false, - } - } -} - -impl FormatResult { - pub(crate) fn success( - snippet: String, - non_formatted_ranges: Vec, - original_snippet: Option, - newline_style: NewlineStyle, - ) -> Self { - let formatted_snippet = FormattedSnippet { - snippet, - non_formatted_ranges, - }; - FormatResult { - original_snippet, - formatted_snippet, - format_errors: HashSet::new(), - newline_style, - } - } - - pub(crate) fn errors(&self) -> impl Iterator { - self.format_errors - .iter() - .filter(|e| e.kind != ErrorKind::MacroFormatError) - } -} - -/// Reports on any issues that occurred during a run of Rustfmt. -/// -/// Can be reported to the user using the `Display` impl on [`FormatReportFormatter`]. -#[derive(Debug, Clone)] -pub struct FormatReport { - format_result: Rc>>, - ignored_files: Rc>>, -} - -impl FormatReport { - pub fn new() -> FormatReport { - FormatReport { - format_result: Rc::new(RefCell::new(BTreeMap::new())), - ignored_files: Rc::new(RefCell::new(BTreeSet::new())), - } - } - - pub fn format_result(&self) -> impl Iterator { - Ref::leak(RefCell::borrow(&self.format_result)).iter() - } - - /// FIXME(topecongiro): reduce visibility. - pub fn merge(&mut self, other: Self) { - self.format_result - .borrow_mut() - .append(&mut other.format_result.borrow_mut()); - self.ignored_files - .borrow_mut() - .append(&mut other.ignored_files.borrow_mut()); - } - - pub(crate) fn add_ignored_file(&self, file_name: FileName) { - self.ignored_files.borrow_mut().insert(file_name); - } - - fn add_format_result(&self, file_name: FileName, format_result: FormatResult) { - let mut format_results = self.format_result.borrow_mut(); - let mut original_format_result = format_results.entry(file_name).or_default(); - original_format_result.formatted_snippet = format_result.formatted_snippet; - original_format_result - .format_errors - .extend(format_result.format_errors); - if original_format_result.original_snippet.is_none() { - original_format_result.original_snippet = format_result.original_snippet; - } - } - - fn append_errors(&self, f: FileName, errors: impl Iterator) { - let mut format_result = self.format_result.borrow_mut(); - let format_errors = &mut format_result.entry(f).or_default().format_errors; - for err in errors { - format_errors.insert(err); - } - } - - pub(crate) fn add_macro_format_failure(&self, file_name: FileName) { - self.add_format_error( - file_name, - FormatError::err_without_line_info(ErrorKind::MacroFormatError), - ); - } - - pub(crate) fn add_license_failure(&self, file_name: FileName) { - self.add_format_error( - file_name, - FormatError::err_without_line_info(ErrorKind::LicenseCheck), - ); - } - - pub(crate) fn add_format_error(&self, file_name: FileName, format_error: FormatError) { - self.format_result - .borrow_mut() - .entry(file_name) - .or_default() - .format_errors - .insert(format_error); - } - - pub fn has_errors(&self) -> bool { - RefCell::borrow(&self.format_result) - .iter() - .any(|(_, format_result)| format_result.errors().count() > 0) - } - - fn warning_count(&self) -> usize { - RefCell::borrow(&self.format_result) - .iter() - .map(|(_, format_result)| format_result.errors().count()) - .sum() - } - - /// Whether any warnings or errors are present in the report. - pub fn has_warnings(&self) -> bool { - self.has_errors() - } -} - -/// Format the given snippet. The snippet is expected to be *complete* code. -/// When we cannot parse the given snippet, this function returns `None`. -fn format_snippet(snippet: &str, config: &Config) -> Option { - let mut config = config.clone(); - panic::catch_unwind(move || { - config.set().hide_parse_errors(true); - - let result = { - let input = Input::Text(snippet.into()); - format( - input, - &config, - OperationSetting { - verbosity: Verbosity::Quiet, - ..OperationSetting::default() - }, - ) - }; - match result { - Ok(report) if !report.has_errors() => { - match (*report.format_result) - .clone() - .into_inner() - .into_iter() - .next() - { - Some(( - _, - FormatResult { - formatted_snippet, - format_errors, - .. - }, - )) if format_errors.is_empty() && !formatted_snippet.snippet.is_empty() => { - Some(formatted_snippet) - } - _ => None, - } - } - _ => None, - } - }) - // Discard panics encountered while formatting the snippet - // The ? operator is needed to remove the extra Option - .ok()? -} - -/// Format the given code block. Mainly targeted for code block in comment. -/// The code block may be incomplete (i.e., parser may be unable to parse it). -/// To avoid panic in parser, we wrap the code block with a dummy function. -/// The returned code block does **not** end with newline. -fn format_code_block(code_snippet: &str, config: &Config) -> Option { - const FN_MAIN_PREFIX: &str = "fn main() {\n"; - - fn enclose_in_main_block(s: &str, config: &Config) -> String { - let indent = Indent::from_width(config, config.tab_spaces()); - let mut result = String::with_capacity(s.len() * 2); - result.push_str(FN_MAIN_PREFIX); - let mut need_indent = true; - for (kind, line) in LineClasses::new(s) { - if need_indent { - result.push_str(&indent.to_string(config)); - } - result.push_str(&line); - result.push('\n'); - need_indent = indent_next_line(kind); - } - result.push('}'); - result - } - - // Wrap the given code block with `fn main()` if it does not have one. - let snippet = enclose_in_main_block(code_snippet, config); - let mut result = String::with_capacity(snippet.len()); - let mut is_first = true; - - // While formatting the code, ignore the config's newline style setting and always use "\n" - // instead of "\r\n" for the newline characters. This is ok because the output here is - // not directly outputted by rustfmt command, but used by the comment formatter's input. - // We have output-file-wide "\n" ==> "\r\n" conversion process after here if it's necessary. - let mut config_with_unix_newline = config.clone(); - config_with_unix_newline - .set() - .newline_style(NewlineStyle::Unix); - let mut formatted = format_snippet(&snippet, &config_with_unix_newline)?; - // Remove wrapping main block - formatted.unwrap_code_block(); - - // Trim "fn main() {" on the first line and "}" on the last line, - // then unindent the whole code block. - let block_len = formatted - .snippet - .rfind('}') - .unwrap_or_else(|| formatted.snippet.len()); - let mut is_indented = true; - let indent_str = Indent::from_width(config, config.tab_spaces()).to_string(config); - for (kind, ref line) in LineClasses::new(&formatted.snippet[FN_MAIN_PREFIX.len()..block_len]) { - if !is_first { - result.push('\n'); - } else { - is_first = false; - } - let trimmed_line = if !is_indented { - line - } else if line.len() > config.max_width() { - // If there are lines that are larger than max width, we cannot tell - // whether we have succeeded but have some comments or strings that - // are too long, or we have failed to format code block. We will be - // conservative and just return `None` in this case. - return None; - } else if line.len() > indent_str.len() { - // Make sure that the line has leading whitespaces. - if line.starts_with(indent_str.as_ref()) { - let offset = if config.hard_tabs() { - 1 - } else { - config.tab_spaces() - }; - &line[offset..] - } else { - line - } - } else { - line - }; - result.push_str(trimmed_line); - is_indented = indent_next_line(kind); - } - Some(FormattedSnippet { - snippet: result, - non_formatted_ranges: formatted.non_formatted_ranges, - }) -} +/// Configures how rustfmt operates during formatting. #[derive(Clone, Copy, Default)] pub struct OperationSetting { /// If set to `true`, format sub-modules which are defined in the given input. @@ -516,9 +55,12 @@ pub fn format( format_input_inner(input, config, operation_setting) } +/// The input to rustfmt. #[derive(Debug)] pub enum Input { + /// A file on the filesystem. File(PathBuf), + /// A UTF-8 string, in many cases from stdin. Text(String), } @@ -642,4 +184,4 @@ false, };"; assert!(test_format_inner(format_code_block, code_block, expected)); } -} +} \ No newline at end of file diff --git a/rustfmt-core/rustfmt-lib/src/result.rs b/rustfmt-core/rustfmt-lib/src/result.rs new file mode 100644 index 00000000000..f212811fc88 --- /dev/null +++ b/rustfmt-core/rustfmt-lib/src/result.rs @@ -0,0 +1,132 @@ +//! This module defines errors and functions related to working with `Result`. + +use rustc_span::Span; +use thiserror::Error; + +use crate::{formatting::ParseSess, FileName}; + +/// Represents the specific error kind of [`FormatError`]. +#[derive(Error, Clone, Copy, Debug, Hash, Eq, PartialEq)] +pub enum ErrorKind { + /// Line has exceeded character limit (found, maximum). + #[error( + "line formatted, but exceeded maximum width \ + (maximum: {1} (see `max_width` option), found: {0})" + )] + LineOverflow(usize, usize), + /// Line ends in whitespace. + #[error("left behind trailing whitespace")] + TrailingWhitespace, + /// License check has failed. + #[error("license check failed")] + LicenseCheck, + /// Used deprecated skip attribute. + #[error("`rustfmt_skip` is deprecated; use `rustfmt::skip`")] + DeprecatedAttr, + /// Used a rustfmt:: attribute other than skip or skip::macros. + #[error("invalid attribute")] + BadAttr, + /// Failed to format macro calls. + #[error("failed to format macro calls")] + MacroFormatError, +} + +/// Represents errors related to formatting issues. +#[derive(Error, Clone, Debug, Hash, Eq, PartialEq)] +#[error("{kind}")] +pub struct FormatError { + kind: ErrorKind, + line_num: Option, + line_str: Option, +} + +impl FormatError { + /// Return the specific kind of this error. + pub fn kind(&self) -> ErrorKind { + self.kind + } + + /// Return the line number on which this error arose. + pub fn line_num(&self) -> Option { + self.line_num + } + + /// Return the content of the line on which this error arose. + pub fn line_str(&self) -> Option<&str> { + self.line_str.as_ref().map(|s| s.as_str()) + } + + pub(crate) fn new(kind: ErrorKind, line_num: usize, line_str: String) -> Self { + FormatError { + kind, + line_num: Some(line_num), + line_str: Some(line_str), + } + } + + // FIXME(topecongiro): add line information in every case. + pub(crate) fn err_without_line_info(kind: ErrorKind) -> Self { + FormatError { + kind, + line_num: None, + line_str: None, + } + } + + pub(crate) fn from_span(kind: ErrorKind, parse_sess: &ParseSess, span: Span) -> Self { + FormatError { + kind, + line_num: Some(parse_sess.line_of_byte_pos(span.lo())), + line_str: Some(parse_sess.span_to_first_line_string(span)), + } + } + + // (space, target) + pub(crate) fn format_len(&self) -> Option<(usize, usize)> { + match self.kind { + ErrorKind::LineOverflow(found, max) => Some((max, found - max)), + ErrorKind::TrailingWhitespace + | ErrorKind::DeprecatedAttr + | ErrorKind::BadAttr + | ErrorKind::LicenseCheck => { + let len = self.line_str.as_ref().map_or(0, |s| s.len()); + let trailing_ws_start = self + .line_str + .as_ref() + .and_then(|s| s.rfind(|c: char| !c.is_whitespace())) + .map(|pos| pos + 1) + .unwrap_or(0); + Some((trailing_ws_start, len - trailing_ws_start)) + } + _ => None, + } + } +} + +/// Represent errors unrelated to formatting issues. +#[derive(Error, Debug)] +pub enum OperationError { + /// The user mandated a version and the current version of rustfmt does not + /// satisfy that requirement. + #[error("version mismatch")] + VersionMismatch, + /// An io error during reading or writing. + #[error("io error: {0}")] + IoError(std::io::Error), + /// Invalid glob pattern in `ignore` configuration option. + #[error("invalid glob pattern found in ignore list: {0}")] + InvalidGlobPattern(ignore::Error), + /// Parse error occurred while parsing the input. + #[error("failed to parse {input:?}")] + ParseError { input: FileName, is_panic: bool }, +} + +impl OperationError { + #[cfg(test)] + pub fn is_parse_error(&self) -> bool { + match self { + OperationError::ParseError { .. } => true, + _ => false, + } + } +} diff --git a/rustfmt-core/rustfmt-lib/src/test/configuration_snippet.rs b/rustfmt-core/rustfmt-lib/src/test/configuration_snippet.rs index 5e49633dd9b..3dd859b9e1b 100644 --- a/rustfmt-core/rustfmt-lib/src/test/configuration_snippet.rs +++ b/rustfmt-core/rustfmt-lib/src/test/configuration_snippet.rs @@ -188,7 +188,7 @@ impl ConfigCodeBlock { let report = report.unwrap(); let result = report.format_result().next().unwrap(); - let text = &result.1.formatted_snippet.snippet; + let text = result.1.formatted_text(); !self.formatted_has_diff(text) } diff --git a/rustfmt-core/rustfmt-lib/src/test/mod.rs b/rustfmt-core/rustfmt-lib/src/test/mod.rs index d4f0d63625f..66823a7226d 100644 --- a/rustfmt-core/rustfmt-lib/src/test/mod.rs +++ b/rustfmt-core/rustfmt-lib/src/test/mod.rs @@ -659,7 +659,7 @@ fn idempotent_check( let mut write_result = HashMap::new(); for (filename, text) in format_report.format_result() { if let FileName::Real(ref filename) = filename { - write_result.insert(filename.to_owned(), text.formatted_snippet.snippet.clone()); + write_result.insert(filename.to_owned(), text.formatted_text().to_owned()); } } From 5f5c9d1e970d9227851ac8814c60b3937320b975 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 10 May 2020 17:31:29 +0900 Subject: [PATCH 33/59] Cargo fmt --- rustfmt-core/rustfmt-lib/src/formatting.rs | 2 +- .../rustfmt-lib/src/formatting/attr.rs | 9 ++++---- .../rustfmt-lib/src/formatting/closures.rs | 23 ++++++------------- .../rustfmt-lib/src/formatting/comment.rs | 4 ++-- .../rustfmt-lib/src/formatting/expr.rs | 10 ++++---- .../rustfmt-lib/src/formatting/imports.rs | 13 +++++------ .../rustfmt-lib/src/formatting/lists.rs | 6 +---- .../rustfmt-lib/src/formatting/macros.rs | 13 +++++------ .../rustfmt-lib/src/formatting/matches.rs | 16 ++++++------- .../src/formatting/missed_spans.rs | 8 +++---- .../rustfmt-lib/src/formatting/modules.rs | 2 +- .../src/formatting/modules/visitor.rs | 6 +---- .../rustfmt-lib/src/formatting/overflow.rs | 10 ++++---- .../rustfmt-lib/src/formatting/pairs.rs | 4 +--- .../rustfmt-lib/src/formatting/source_map.rs | 5 +--- .../src/formatting/syntux/session.rs | 14 ++++------- .../rustfmt-lib/src/formatting/types.rs | 13 +++-------- .../rustfmt-lib/src/formatting/util.rs | 7 ++---- .../rustfmt-lib/src/formatting/vertical.rs | 6 ++--- .../rustfmt-lib/src/formatting/visitor.rs | 2 +- 20 files changed, 63 insertions(+), 110 deletions(-) diff --git a/rustfmt-core/rustfmt-lib/src/formatting.rs b/rustfmt-core/rustfmt-lib/src/formatting.rs index b6f2259d475..a112503c080 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting.rs @@ -8,6 +8,7 @@ use rustc_ast::ast; pub(crate) use syntux::session::ParseSess; use self::newline_style::apply_newline_style; +use crate::config::{Config, FileName}; use crate::formatting::{ comment::{CharClasses, FullCodeCharKind}, report::NonFormattedRange, @@ -15,7 +16,6 @@ use crate::formatting::{ utils::count_newlines, visitor::FmtVisitor, }; -use crate::config::{Config, FileName}; use crate::result::OperationError; use crate::{ ErrorKind, FormatError, FormatReport, FormatResult, Input, OperationSetting, Verbosity, diff --git a/rustfmt-core/rustfmt-lib/src/formatting/attr.rs b/rustfmt-core/rustfmt-lib/src/formatting/attr.rs index 563b3a2b20f..895384c6dda 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/attr.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/attr.rs @@ -4,14 +4,13 @@ use rustc_ast::ast; use rustc_ast::attr::HasAttrs; use rustc_span::{symbol::sym, Span}; +use crate::config::{lists::*, IndentStyle}; use doc_comment::DocCommentFormatter; -use crate::config::{ - lists::*, - IndentStyle, -}; use crate::formatting::{ - comment::{contains_comment, rewrite_doc_comment, CommentStyle, recover_missing_comment_in_span}, + comment::{ + contains_comment, recover_missing_comment_in_span, rewrite_doc_comment, CommentStyle, + }, expr::{rewrite_literal, span_ends_with_comma}, lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}, overflow, diff --git a/rustfmt-core/rustfmt-lib/src/formatting/closures.rs b/rustfmt-core/rustfmt-lib/src/formatting/closures.rs index 76ecc8550d1..da9c13f21cf 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/closures.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/closures.rs @@ -1,15 +1,13 @@ use rustc_ast::{ast, ptr}; use rustc_span::Span; -use crate::config::{ - lists::*, - IndentStyle, - SeparatorTactic, -}; +use crate::config::{lists::*, IndentStyle, SeparatorTactic}; use crate::formatting::{ attr::get_attrs_from_stmt, - expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond, - rewrite_block_with_visitor}, + expr::{ + block_contains_comment, is_simple_block, is_unsafe_block, rewrite_block_with_visitor, + rewrite_cond, + }, items::{span_hi_for_param, span_lo_for_param}, lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}, overflow::OverflowableItem, @@ -162,15 +160,8 @@ fn rewrite_closure_with_block( rules: ast::BlockCheckMode::Default, span: body.span, }; - let block = rewrite_block_with_visitor( - context, - "", - &block, - Some(&body.attrs), - None, - shape, - false, - )?; + let block = + rewrite_block_with_visitor(context, "", &block, Some(&body.attrs), None, shape, false)?; Some(format!("{} {}", prefix, block)) } diff --git a/rustfmt-core/rustfmt-lib/src/formatting/comment.rs b/rustfmt-core/rustfmt-lib/src/formatting/comment.rs index b9ad5422c44..5b298eb9a78 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/comment.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/comment.rs @@ -11,8 +11,8 @@ use crate::formatting::{ shape::{Indent, Shape}, string::{rewrite_string, StringFormat}, utils::{ - count_newlines, first_line_width, last_line_width, tab_to_spaces, trim_left_preserve_layout, - unicode_str_width, + count_newlines, first_line_width, last_line_width, tab_to_spaces, + trim_left_preserve_layout, unicode_str_width, }, }; diff --git a/rustfmt-core/rustfmt-lib/src/formatting/expr.rs b/rustfmt-core/rustfmt-lib/src/formatting/expr.rs index 574812c202b..c43b70d85b0 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/expr.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/expr.rs @@ -6,16 +6,14 @@ use rustc_ast::token::{DelimToken, LitKind}; use rustc_ast::{ast, ptr}; use rustc_span::{BytePos, Span}; -use crate::config::{ - lists::*, - Config, ControlBraceStyle, IndentStyle, -}; +use crate::config::{lists::*, Config, ControlBraceStyle, IndentStyle}; use crate::formatting::{ chains::rewrite_chain, closures, comment::{ - combine_strs_with_missing_comments, comment_style, contains_comment, recover_comment_removed, - rewrite_comment, rewrite_missing_comment, CharClasses, FindUncommented, + combine_strs_with_missing_comments, comment_style, contains_comment, + recover_comment_removed, rewrite_comment, rewrite_missing_comment, CharClasses, + FindUncommented, }, lists::{ definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, diff --git a/rustfmt-core/rustfmt-lib/src/formatting/imports.rs b/rustfmt-core/rustfmt-lib/src/formatting/imports.rs index 6e365fcbfc2..cf032100416 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/imports.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/imports.rs @@ -13,15 +13,13 @@ use crate::config::lists::*; use crate::config::{Edition, IndentStyle}; use crate::formatting::{ comment::combine_strs_with_missing_comments, - lists::{ - definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, - }, + lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}, reorder::{compare_as_versions, compare_opt_ident_as_versions}, rewrite::{Rewrite, RewriteContext}, shape::Shape, source_map::SpanUtils, spanned::Spanned, - utils::{is_same_visibility, mk_sp, rewrite_ident, format_visibility}, + utils::{format_visibility, is_same_visibility, mk_sp, rewrite_ident}, visitor::FmtVisitor, }; @@ -234,9 +232,10 @@ impl UseTree { context: &RewriteContext<'_>, shape: Shape, ) -> Option { - let vis = self.visibility.as_ref().map_or(Cow::from(""), |vis| { - format_visibility(context, &vis) - }); + let vis = self + .visibility + .as_ref() + .map_or(Cow::from(""), |vis| format_visibility(context, &vis)); let use_str = self .rewrite(context, shape.offset_left(vis.len())?) .map(|s| { diff --git a/rustfmt-core/rustfmt-lib/src/formatting/lists.rs b/rustfmt-core/rustfmt-lib/src/formatting/lists.rs index 2c7a2ea63a8..f63b3a06eef 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/lists.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/lists.rs @@ -6,11 +6,7 @@ use std::iter::Peekable; use rustc_span::BytePos; use unicode_segmentation::UnicodeSegmentation; -use crate::config::{ - lists::*, - Config, - IndentStyle, -}; +use crate::config::{lists::*, Config, IndentStyle}; use crate::formatting::{ comment::{find_comment_end, rewrite_comment, FindUncommented}, rewrite::RewriteContext, diff --git a/rustfmt-core/rustfmt-lib/src/formatting/macros.rs b/rustfmt-core/rustfmt-lib/src/formatting/macros.rs index c1492efc07c..c8fc0f0a0ce 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/macros.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/macros.rs @@ -22,26 +22,25 @@ use rustc_span::{ BytePos, Span, Symbol, DUMMY_SP, }; +use crate::config::lists::*; use crate::formatting::{ - comment::{ - contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses, - }, + comment::{contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses}, expr::{rewrite_array, rewrite_assign_rhs}, - report::NonFormattedRange, lists::{itemize_list, write_list, ListFormatting}, overflow, + report::NonFormattedRange, rewrite::{Rewrite, RewriteContext}, shape::{Indent, Shape}, source_map::SpanUtils, spanned::Spanned, - util::{format_snippet, format_code_block}, + util::{format_code_block, format_snippet}, utils::{ count_newlines, format_visibility, indent_next_line, is_empty_line, mk_sp, - remove_trailing_white_spaces, rewrite_ident, trim_left_preserve_layout, wrap_str, NodeIdExt, + remove_trailing_white_spaces, rewrite_ident, trim_left_preserve_layout, wrap_str, + NodeIdExt, }, visitor::FmtVisitor, }; -use crate::config::lists::*; const FORCED_BRACKET_MACROS: &[&str] = &["vec!"]; diff --git a/rustfmt-core/rustfmt-lib/src/formatting/matches.rs b/rustfmt-core/rustfmt-lib/src/formatting/matches.rs index bb95cfe8d77..679b99e3e77 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/matches.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/matches.rs @@ -5,11 +5,15 @@ use std::iter::repeat; use rustc_ast::{ast, ptr}; use rustc_span::{BytePos, Span}; +use crate::config::{ + lists::*, + Config, ControlBraceStyle, IndentStyle, MatchArmLeadingPipe, +}; use crate::formatting::{ comment::{combine_strs_with_missing_comments, rewrite_comment}, expr::{ - format_expr, is_empty_block, is_simple_block, is_unsafe_block, prefer_next_line, rewrite_cond, - ExprType, RhsTactics, + format_expr, is_empty_block, is_simple_block, is_unsafe_block, prefer_next_line, + rewrite_cond, ExprType, RhsTactics, }, lists::{itemize_list, write_list, ListFormatting}, rewrite::{Rewrite, RewriteContext}, @@ -17,14 +21,10 @@ use crate::formatting::{ source_map::SpanUtils, spanned::Spanned, utils::{ - contains_skip, extra_offset, first_line_width, inner_attributes, last_line_extendable, mk_sp, - semicolon_for_expr, trimmed_last_line_width, unicode_str_width, + contains_skip, extra_offset, first_line_width, inner_attributes, last_line_extendable, + mk_sp, semicolon_for_expr, trimmed_last_line_width, unicode_str_width, }, }; -use crate::config::{ - lists::*, - Config, ControlBraceStyle, IndentStyle, MatchArmLeadingPipe, -}; /// A simple wrapper type against `ast::Arm`. Used inside `write_list()`. struct ArmWrapper<'a> { diff --git a/rustfmt-core/rustfmt-lib/src/formatting/missed_spans.rs b/rustfmt-core/rustfmt-lib/src/formatting/missed_spans.rs index b80fa73dc6a..83e7bd12208 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/missed_spans.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/missed_spans.rs @@ -1,16 +1,14 @@ use rustc_span::{BytePos, Pos, Span}; -use crate::config::{ - file_lines::FileLines, - FileName, -}; +use crate::config::{file_lines::FileLines, FileName}; use crate::formatting::{ comment::{is_last_comment_block, rewrite_comment, CodeCharKind, CommentCodeSlices}, shape::{Indent, Shape}, source_map::LineRangeUtils, utils::{ - count_lf_crlf, count_newlines, last_line_contains_single_line_comment, last_line_width, mk_sp, + count_lf_crlf, count_newlines, last_line_contains_single_line_comment, last_line_width, + mk_sp, }, visitor::FmtVisitor, }; diff --git a/rustfmt-core/rustfmt-lib/src/formatting/modules.rs b/rustfmt-core/rustfmt-lib/src/formatting/modules.rs index 1dda132e4c4..cb49b62094c 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/modules.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/modules.rs @@ -6,6 +6,7 @@ use rustc_ast::ast; use rustc_ast::visit::Visitor; use rustc_span::symbol::{self, sym, Symbol}; +use crate::config::FileName; use crate::formatting::{ attr::MetaVisitor, items::is_mod_decl, @@ -13,7 +14,6 @@ use crate::formatting::{ syntux::session::ParseSess, utils::contains_skip, }; -use crate::config::FileName; mod visitor; diff --git a/rustfmt-core/rustfmt-lib/src/formatting/modules/visitor.rs b/rustfmt-core/rustfmt-lib/src/formatting/modules/visitor.rs index f4dd60f3c91..c8259d7087f 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/modules/visitor.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/modules/visitor.rs @@ -2,11 +2,7 @@ use rustc_ast::ast; use rustc_ast::visit::Visitor; use rustc_span::Symbol; -use crate::formatting::{ - attr::MetaVisitor, - syntux::parser::Parser, - syntux::session::ParseSess, -}; +use crate::formatting::{attr::MetaVisitor, syntux::parser::Parser, syntux::session::ParseSess}; pub(crate) struct ModItem { pub(crate) item: ast::Item, diff --git a/rustfmt-core/rustfmt-lib/src/formatting/overflow.rs b/rustfmt-core/rustfmt-lib/src/formatting/overflow.rs index c209fd15c60..d2172afd87c 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/overflow.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/overflow.rs @@ -7,15 +7,16 @@ use rustc_ast::token::DelimToken; use rustc_ast::{ast, ptr}; use rustc_span::Span; +use crate::config::lists::*; use crate::formatting::{ closures, expr::{ - can_be_overflowed_expr, is_every_expr_simple, is_method_call, is_nested_call, is_simple_expr, - rewrite_cond, + can_be_overflowed_expr, is_every_expr_simple, is_method_call, is_nested_call, + is_simple_expr, rewrite_cond, }, lists::{ - definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, - total_item_width, + definitive_tactic, itemize_list, total_item_width, write_list, ListFormatting, ListItem, + Separator, }, macros::MacroArg, patterns::{can_be_overflowed_pat, TuplePatField}, @@ -26,7 +27,6 @@ use crate::formatting::{ types::{can_be_overflowed_type, SegmentParam}, utils::{count_newlines, extra_offset, first_line_width, last_line_width, mk_sp}, }; -use crate::config::lists::*; const SHORT_ITEM_THRESHOLD: usize = 10; diff --git a/rustfmt-core/rustfmt-lib/src/formatting/pairs.rs b/rustfmt-core/rustfmt-lib/src/formatting/pairs.rs index 00f208be05c..de13597b2c7 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/pairs.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/pairs.rs @@ -5,9 +5,7 @@ use crate::config::IndentStyle; use crate::formatting::{ rewrite::{Rewrite, RewriteContext}, shape::Shape, - utils::{ - first_line_width, is_single_line, last_line_width, trimmed_last_line_width, wrap_str, - }, + utils::{first_line_width, is_single_line, last_line_width, trimmed_last_line_width, wrap_str}, }; /// Sigils that decorate a binop pair. diff --git a/rustfmt-core/rustfmt-lib/src/formatting/source_map.rs b/rustfmt-core/rustfmt-lib/src/formatting/source_map.rs index 68140f0108c..e2e1d893dc6 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/source_map.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/source_map.rs @@ -4,10 +4,7 @@ use rustc_span::{BytePos, Span}; use crate::config::file_lines::LineRange; -use crate::formatting::{ - comment::FindUncommented, - visitor::SnippetProvider, -}; +use crate::formatting::{comment::FindUncommented, visitor::SnippetProvider}; pub(crate) trait SpanUtils { fn span_after(&self, original: Span, needle: &str) -> BytePos; diff --git a/rustfmt-core/rustfmt-lib/src/formatting/syntux/session.rs b/rustfmt-core/rustfmt-lib/src/formatting/syntux/session.rs index 19415d4617e..65a994067d7 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/syntux/session.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/syntux/session.rs @@ -11,18 +11,12 @@ use rustc_span::{ symbol, BytePos, Span, }; -use crate::config::{ - Config, - FileName, - file_lines::LineRange, +use crate::config::{file_lines::LineRange, Config, FileName}; +use crate::formatting::{ + source_map::LineRangeUtils, utils::starts_with_newline, visitor::SnippetProvider, }; use crate::ignore_path::IgnorePathSet; use crate::result::OperationError; -use crate::formatting::{ - source_map::LineRangeUtils, - utils::starts_with_newline, - visitor::SnippetProvider, -}; /// ParseSess holds structs necessary for constructing a parser. pub(crate) struct ParseSess { @@ -275,8 +269,8 @@ mod tests { mod emitter { use super::*; use crate::config::IgnoreList; - use crate::is_nightly_channel; use crate::formatting::utils::mk_sp; + use crate::is_nightly_channel; use rustc_span::{FileName as SourceMapFileName, MultiSpan, DUMMY_SP}; use std::path::PathBuf; diff --git a/rustfmt-core/rustfmt-lib/src/formatting/types.rs b/rustfmt-core/rustfmt-lib/src/formatting/types.rs index 081e4d031f0..55eb1ba2b91 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/types.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/types.rs @@ -4,16 +4,10 @@ use std::ops::Deref; use rustc_ast::ast::{self, FnRetTy, Mutability}; use rustc_span::{symbol::kw, BytePos, Span}; -use crate::config::{ - lists::*, - IndentStyle, - TypeDensity, -}; +use crate::config::{lists::*, IndentStyle, TypeDensity}; use crate::formatting::{ expr::{format_expr, rewrite_assign_rhs, rewrite_tuple, rewrite_unary_prefix, ExprType}, - lists::{ - definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, - }, + lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}, macros::{rewrite_macro, MacroPosition}, overflow, pairs::{rewrite_pair, PairParts}, @@ -23,8 +17,7 @@ use crate::formatting::{ spanned::Spanned, utils::{ colon_spaces, extra_offset, first_line_width, format_extern, format_mutability, - last_line_extendable, last_line_width, mk_sp, rewrite_ident, - format_unsafety, + format_unsafety, last_line_extendable, last_line_width, mk_sp, rewrite_ident, }, }; diff --git a/rustfmt-core/rustfmt-lib/src/formatting/util.rs b/rustfmt-core/rustfmt-lib/src/formatting/util.rs index 4e4e03c3f5c..88194cf1f93 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/util.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/util.rs @@ -1,10 +1,7 @@ -use crate::{config::Config, emitter::Verbosity, Input, NewlineStyle, OperationSetting}; use crate::formatting::{ - comment::LineClasses, - FormattedSnippet, - shape::Indent, - utils::indent_next_line, + comment::LineClasses, shape::Indent, utils::indent_next_line, FormattedSnippet, }; +use crate::{config::Config, emitter::Verbosity, Input, NewlineStyle, OperationSetting}; /// Format the given snippet. The snippet is expected to be *complete* code. /// When we cannot parse the given snippet, this function returns `None`. diff --git a/rustfmt-core/rustfmt-lib/src/formatting/vertical.rs b/rustfmt-core/rustfmt-lib/src/formatting/vertical.rs index f4cd14e8c01..cb54125228e 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/vertical.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/vertical.rs @@ -6,13 +6,12 @@ use itertools::Itertools; use rustc_ast::ast; use rustc_span::{BytePos, Span}; +use crate::config::lists::*; use crate::formatting::{ comment::combine_strs_with_missing_comments, expr::rewrite_field, items::{rewrite_struct_field, rewrite_struct_field_prefix}, - lists::{ - definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, - }, + lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}, rewrite::{Rewrite, RewriteContext}, shape::{Indent, Shape}, source_map::SpanUtils, @@ -21,7 +20,6 @@ use crate::formatting::{ contains_skip, is_attributes_extendable, mk_sp, rewrite_ident, trimmed_last_line_width, }, }; -use crate::config::lists::*; pub(crate) trait AlignedItem { fn skip(&self) -> bool; diff --git a/rustfmt-core/rustfmt-lib/src/formatting/visitor.rs b/rustfmt-core/rustfmt-lib/src/formatting/visitor.rs index 6aad64dc238..e63ab4f6724 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/visitor.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/visitor.rs @@ -8,13 +8,13 @@ use crate::config::{BraceStyle, Config}; use crate::formatting::{ attr::*, comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}, - report::{FormatReport, NonFormattedRange}, items::{ format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, rewrite_associated_impl_type, rewrite_extern_crate, rewrite_opaque_impl_type, rewrite_opaque_type, rewrite_type_alias, FnBraceStyle, FnSig, StaticParts, StructParts, }, macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition}, + report::{FormatReport, NonFormattedRange}, rewrite::{Rewrite, RewriteContext}, shape::{Indent, Shape}, skip::{is_skip_attr, SkipContext}, From b05a9021066496a81b91bda597708fef599beed1 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 10 May 2020 17:42:11 +0900 Subject: [PATCH 34/59] Move some files --- rustfmt-core/rustfmt-lib/src/formatting/syntux/session.rs | 4 +++- .../src/{ => formatting/syntux/session}/ignore_path.rs | 2 +- rustfmt-core/rustfmt-lib/src/lib.rs | 3 +-- 3 files changed, 5 insertions(+), 4 deletions(-) rename rustfmt-core/rustfmt-lib/src/{ => formatting/syntux/session}/ignore_path.rs (97%) diff --git a/rustfmt-core/rustfmt-lib/src/formatting/syntux/session.rs b/rustfmt-core/rustfmt-lib/src/formatting/syntux/session.rs index 65a994067d7..83a0087273b 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/syntux/session.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/syntux/session.rs @@ -15,8 +15,10 @@ use crate::config::{file_lines::LineRange, Config, FileName}; use crate::formatting::{ source_map::LineRangeUtils, utils::starts_with_newline, visitor::SnippetProvider, }; -use crate::ignore_path::IgnorePathSet; use crate::result::OperationError; +use ignore_path::IgnorePathSet; + +mod ignore_path; /// ParseSess holds structs necessary for constructing a parser. pub(crate) struct ParseSess { diff --git a/rustfmt-core/rustfmt-lib/src/ignore_path.rs b/rustfmt-core/rustfmt-lib/src/formatting/syntux/session/ignore_path.rs similarity index 97% rename from rustfmt-core/rustfmt-lib/src/ignore_path.rs rename to rustfmt-core/rustfmt-lib/src/formatting/syntux/session/ignore_path.rs index b45bae5587c..d4e798315b7 100644 --- a/rustfmt-core/rustfmt-lib/src/ignore_path.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/syntux/session/ignore_path.rs @@ -34,8 +34,8 @@ impl IgnorePathSet { mod test { use std::path::{Path, PathBuf}; + use super::IgnorePathSet; use crate::config::{Config, FileName}; - use crate::ignore_path::IgnorePathSet; #[test] fn test_ignore_path_set() { diff --git a/rustfmt-core/rustfmt-lib/src/lib.rs b/rustfmt-core/rustfmt-lib/src/lib.rs index 43dc6a8e2f7..3c635f88bca 100644 --- a/rustfmt-core/rustfmt-lib/src/lib.rs +++ b/rustfmt-core/rustfmt-lib/src/lib.rs @@ -30,8 +30,7 @@ pub mod config; pub mod emitter; mod format_report_formatter; -pub(crate) mod formatting; -mod ignore_path; +mod formatting; mod release_channel; pub mod result; #[cfg(test)] From d261e9c46265e83f3a995abbdfce003799a16227 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 10 May 2020 18:10:56 +0900 Subject: [PATCH 35/59] Add format_inputs --- rustfmt-core/rustfmt-bin/src/bin/main.rs | 73 +++++-------------- .../rustfmt-lib/src/formatting/report.rs | 3 +- rustfmt-core/rustfmt-lib/src/lib.rs | 13 ++++ 3 files changed, 33 insertions(+), 56 deletions(-) diff --git a/rustfmt-core/rustfmt-bin/src/bin/main.rs b/rustfmt-core/rustfmt-bin/src/bin/main.rs index 97432ce4b10..a1964a6db2c 100644 --- a/rustfmt-core/rustfmt-bin/src/bin/main.rs +++ b/rustfmt-core/rustfmt-bin/src/bin/main.rs @@ -15,7 +15,7 @@ use thiserror::Error; use rustfmt_lib::{ emitter::{emit_format_report, EmitMode, EmitterConfig, Verbosity}, - load_config, CliOptions, Config, Edition, FileLines, FileName, FormatReport, + format_inputs, load_config, CliOptions, Config, Edition, FileLines, FileName, FormatReportFormatterBuilder, Input, OperationSetting, }; @@ -418,10 +418,8 @@ fn format_string(input: String, opt: Opt) -> Result { recursive: opt.recursive, verbosity: Verbosity::Quiet, }; - let mut format_report = FormatReport::new(); - // FIXME: Add error handling. - format_and_emit_report(Input::Text(input), &config, setting, &mut format_report); - let has_diff = emit_format_report(format_report, out, opt.emitter_config(EmitMode::Stdout))?; + let report = rustfmt_lib::format(Input::Text(input), &config, setting)?; + let has_diff = emit_format_report(report, out, opt.emitter_config(EmitMode::Stdout))?; Ok(if opt.check && has_diff { 1 } else { 0 }) } @@ -485,7 +483,7 @@ fn format(opt: Opt) -> Result { return Err(format_err!("Error: `{}` is a directory", dir.display())); } - let (config, config_path) = load_config(None, Some(&opt))?; + let (default_config, config_path) = load_config(None, Some(&opt))?; if opt.verbose { if let Some(path) = config_path.as_ref() { @@ -497,37 +495,21 @@ fn format(opt: Opt) -> Result { recursive: opt.recursive, verbosity: opt.verbosity(), }; - let mut format_report = FormatReport::new(); - - for pair in FileConfigPairIter::new(&opt, config_path.is_some()) { - let file = pair.file; - - if let FileConfig::Local(local_config, config_path) = pair.config { - if let Some(path) = config_path { - if opt.verbose { - println!( - "Using rustfmt config file {} for {}", - path.display(), - file.display() - ); - } - } - format_and_emit_report( - Input::File(file.to_path_buf()), - &local_config, - setting, - &mut format_report, - ); - } else { - format_and_emit_report( - Input::File(file.to_path_buf()), - &config, - setting, - &mut format_report, - ); - } - } + let inputs = FileConfigPairIter::new(&opt, config_path.is_some()).collect::>(); + let format_report = format_inputs( + inputs.iter().map(|p| { + ( + Input::File(p.file.to_path_buf()), + if let FileConfig::Local(ref config, _) = p.config { + config + } else { + &default_config + }, + ) + }), + setting, + )?; if format_report.has_errors() { eprintln!( @@ -538,28 +520,11 @@ fn format(opt: Opt) -> Result { ); } - let out = &mut stdout(); - let has_diff = emit_format_report(format_report, out, opt.emitter_config(EmitMode::Files))?; + let has_diff = emit_format_report(format_report, &mut stdout(), opt.emitter_config(EmitMode::Files))?; Ok(if opt.check && has_diff { 1 } else { 0 }) } -fn format_and_emit_report( - input: Input, - config: &Config, - operation_setting: OperationSetting, - format_report: &mut FormatReport, -) { - match rustfmt_lib::format(input, config, operation_setting) { - Ok(report) => { - format_report.merge(report); - } - Err(err) => { - eprintln!("{}", err); - } - } -} - #[cfg(test)] mod test { use super::*; diff --git a/rustfmt-core/rustfmt-lib/src/formatting/report.rs b/rustfmt-core/rustfmt-lib/src/formatting/report.rs index 411d5e7078f..3513a28ac0b 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/report.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/report.rs @@ -100,8 +100,7 @@ impl FormatReport { Rc::clone(&self.format_result) } - /// FIXME(topecongiro): reduce visibility. - pub fn merge(&mut self, other: Self) { + pub(crate) fn merge(&mut self, other: Self) { self.format_result .borrow_mut() .append(&mut other.format_result.borrow_mut()); diff --git a/rustfmt-core/rustfmt-lib/src/lib.rs b/rustfmt-core/rustfmt-lib/src/lib.rs index 3c635f88bca..7837eae64a1 100644 --- a/rustfmt-core/rustfmt-lib/src/lib.rs +++ b/rustfmt-core/rustfmt-lib/src/lib.rs @@ -33,6 +33,7 @@ mod format_report_formatter; mod formatting; mod release_channel; pub mod result; + #[cfg(test)] mod test; @@ -54,6 +55,18 @@ pub fn format( format_input_inner(input, config, operation_setting) } +pub fn format_inputs<'a>( + inputs: impl Iterator, + operation_setting: OperationSetting, +) -> Result { + let mut format_report = FormatReport::new(); + for (input, config) in inputs { + let report = format(input, config, operation_setting)?; + format_report.merge(report); + } + Ok(format_report) +} + /// The input to rustfmt. #[derive(Debug)] pub enum Input { From dd2e0ca018eb677cea939d5313a60b6c18b2a421 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 10 May 2020 18:15:15 +0900 Subject: [PATCH 36/59] Fix git-rustfmt --- .../rustfmt-bin/src/git-rustfmt/main.rs | 17 +++++++++++++---- .../rustfmt-lib/src/formatting/report.rs | 5 ----- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/rustfmt-core/rustfmt-bin/src/git-rustfmt/main.rs b/rustfmt-core/rustfmt-bin/src/git-rustfmt/main.rs index 55a70405a9b..8091ad05bf2 100644 --- a/rustfmt-core/rustfmt-bin/src/git-rustfmt/main.rs +++ b/rustfmt-core/rustfmt-bin/src/git-rustfmt/main.rs @@ -63,14 +63,23 @@ fn fmt_files(files: &[&str]) -> i32 { let mut out = stdout(); for file in files { - let report = format(Input::File(PathBuf::from(file)), &config, setting).unwrap(); - if report.has_warnings() { + let report = match format(Input::File(PathBuf::from(file)), &config, setting) { + Ok(report) => report, + Err(e) => { + eprintln!("{}", e); + return 1; + } + }; + if report.has_errors() { eprintln!("{}", FormatReportFormatterBuilder::new(&report).build()); } - emit_format_report(report, &mut out, EmitterConfig::default()).unwrap(); + if let Err(e) = emit_format_report(report, &mut out, EmitterConfig::default()) { + eprintln!("{}", e); + return 1; + } } - todo!("Fix error handling") + 0 } struct NullOptions; diff --git a/rustfmt-core/rustfmt-lib/src/formatting/report.rs b/rustfmt-core/rustfmt-lib/src/formatting/report.rs index 3513a28ac0b..7ceda2164a2 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/report.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/report.rs @@ -168,11 +168,6 @@ impl FormatReport { .map(|(_, format_result)| format_result.errors_excluding_macro().count()) .sum() } - - /// Whether any warnings or errors are present in the report. - pub fn has_warnings(&self) -> bool { - self.has_errors() - } } impl NonFormattedRange { From 975c19d72a37414c877a205edc12fd85cc19977f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 10 May 2020 22:14:27 +0900 Subject: [PATCH 37/59] Fix test --- rustfmt-core/rustfmt-bin/src/bin/main.rs | 6 +++++- rustfmt-core/rustfmt-lib/src/test/mod.rs | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/rustfmt-core/rustfmt-bin/src/bin/main.rs b/rustfmt-core/rustfmt-bin/src/bin/main.rs index a1964a6db2c..a36f63b58c9 100644 --- a/rustfmt-core/rustfmt-bin/src/bin/main.rs +++ b/rustfmt-core/rustfmt-bin/src/bin/main.rs @@ -520,7 +520,11 @@ fn format(opt: Opt) -> Result { ); } - let has_diff = emit_format_report(format_report, &mut stdout(), opt.emitter_config(EmitMode::Files))?; + let has_diff = emit_format_report( + format_report, + &mut stdout(), + opt.emitter_config(EmitMode::Files), + )?; Ok(if opt.check && has_diff { 1 } else { 0 }) } diff --git a/rustfmt-core/rustfmt-lib/src/test/mod.rs b/rustfmt-core/rustfmt-lib/src/test/mod.rs index 66823a7226d..606354de3d8 100644 --- a/rustfmt-core/rustfmt-lib/src/test/mod.rs +++ b/rustfmt-core/rustfmt-lib/src/test/mod.rs @@ -540,7 +540,7 @@ fn check_files(files: Vec, opt_config: &Option) -> (Vec { + Ok(ref report) if report.has_errors() => { print!("{}", FormatReportFormatterBuilder::new(&report).build()); fails += 1; } From 100068d0b7948aa8a8bda178cd7d42983ab3fc82 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 10 May 2020 23:06:44 +0900 Subject: [PATCH 38/59] Fix ignored test --- rustfmt-core/rustfmt-bin/tests/rustfmt/main.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rustfmt-core/rustfmt-bin/tests/rustfmt/main.rs b/rustfmt-core/rustfmt-bin/tests/rustfmt/main.rs index 29fc78c0a77..b0213f52782 100644 --- a/rustfmt-core/rustfmt-bin/tests/rustfmt/main.rs +++ b/rustfmt-core/rustfmt-bin/tests/rustfmt/main.rs @@ -91,10 +91,11 @@ fn inline_config() { "--config", "max_width=80,edition=2018", "--config", - "color=always,format_strings=true" + "tab_spaces=8,format_strings=true" ], contains("max_width = 80") && contains("edition = \"2018\"") && contains("format_strings = true") + && contains("tab_spaces = 8") ); } From d9f70644ec0ec99ba3bf42dad9d58d62c66f7f59 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 11 May 2020 21:13:24 +0900 Subject: [PATCH 39/59] Fix test --- rustfmt-core/rustfmt-bin/tests/rustfmt/main.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rustfmt-core/rustfmt-bin/tests/rustfmt/main.rs b/rustfmt-core/rustfmt-bin/tests/rustfmt/main.rs index b0213f52782..5d9ab53db25 100644 --- a/rustfmt-core/rustfmt-bin/tests/rustfmt/main.rs +++ b/rustfmt-core/rustfmt-bin/tests/rustfmt/main.rs @@ -91,11 +91,10 @@ fn inline_config() { "--config", "max_width=80,edition=2018", "--config", - "tab_spaces=8,format_strings=true" + "max_width=60,format_strings=true" ], - contains("max_width = 80") + contains("max_width = 60") && contains("edition = \"2018\"") && contains("format_strings = true") - && contains("tab_spaces = 8") ); } From 69f6b76dd73cf071aa8bf7234a317a6818296066 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 11 May 2020 21:18:49 +0900 Subject: [PATCH 40/59] Audit lib.rs --- rustfmt-core/rustfmt-lib/src/emitter/rustfmt_diff.rs | 2 +- rustfmt-core/rustfmt-lib/src/format_report_formatter.rs | 5 ++++- rustfmt-core/rustfmt-lib/src/formatting.rs | 3 ++- rustfmt-core/rustfmt-lib/src/formatting/items.rs | 2 +- rustfmt-core/rustfmt-lib/src/lib.rs | 7 +------ rustfmt-core/rustfmt-lib/src/test/mod.rs | 6 +++--- 6 files changed, 12 insertions(+), 13 deletions(-) diff --git a/rustfmt-core/rustfmt-lib/src/emitter/rustfmt_diff.rs b/rustfmt-core/rustfmt-lib/src/emitter/rustfmt_diff.rs index 56d129c75e4..6df2444d63b 100644 --- a/rustfmt-core/rustfmt-lib/src/emitter/rustfmt_diff.rs +++ b/rustfmt-core/rustfmt-lib/src/emitter/rustfmt_diff.rs @@ -3,7 +3,7 @@ use std::fmt; use std::io; use std::io::Write; -use crate::{Color, Verbosity}; +use crate::{emitter::Color, Verbosity}; #[derive(Debug, PartialEq)] pub enum DiffLine { diff --git a/rustfmt-core/rustfmt-lib/src/format_report_formatter.rs b/rustfmt-core/rustfmt-lib/src/format_report_formatter.rs index 5d3fabb70dc..b1b0d4a0ac5 100644 --- a/rustfmt-core/rustfmt-lib/src/format_report_formatter.rs +++ b/rustfmt-core/rustfmt-lib/src/format_report_formatter.rs @@ -1,5 +1,8 @@ use crate::config::FileName; -use crate::{ErrorKind, FormatError, FormatReport}; +use crate::{ + formatting::report::FormatReport, + result::{ErrorKind, FormatError}, +}; use annotate_snippets::display_list::DisplayList; use annotate_snippets::formatter::DisplayListFormatter; use annotate_snippets::snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation}; diff --git a/rustfmt-core/rustfmt-lib/src/formatting.rs b/rustfmt-core/rustfmt-lib/src/formatting.rs index a112503c080..50cb1471ac5 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting.rs @@ -18,7 +18,8 @@ use crate::formatting::{ }; use crate::result::OperationError; use crate::{ - ErrorKind, FormatError, FormatReport, FormatResult, Input, OperationSetting, Verbosity, + result::{ErrorKind, FormatError}, + FormatReport, FormatResult, Input, OperationSetting, Verbosity, }; #[macro_use] diff --git a/rustfmt-core/rustfmt-lib/src/formatting/items.rs b/rustfmt-core/rustfmt-lib/src/formatting/items.rs index 146245d1026..d72a42c1d47 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/items.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/items.rs @@ -687,7 +687,7 @@ impl<'a> FmtVisitor<'a> { // we still need to differentiate to maintain sorting order. // type -> opaque -> const -> macro -> method - use crate::ast::AssocItemKind::*; + use ast::AssocItemKind::*; fn need_empty_line(a: &ast::AssocItemKind, b: &ast::AssocItemKind) -> bool { match (a, b) { (TyAlias(_, _, _, ref lty), TyAlias(_, _, _, ref rty)) diff --git a/rustfmt-core/rustfmt-lib/src/lib.rs b/rustfmt-core/rustfmt-lib/src/lib.rs index 7837eae64a1..9a37e4158c6 100644 --- a/rustfmt-core/rustfmt-lib/src/lib.rs +++ b/rustfmt-core/rustfmt-lib/src/lib.rs @@ -9,8 +9,6 @@ extern crate log; use std::path::PathBuf; -use rustc_ast::ast; - pub use crate::config::{ load_config, CliOptions, Config, Edition, FileLines, FileName, NewlineStyle, Range, }; @@ -19,10 +17,7 @@ pub use crate::format_report_formatter::{FormatReportFormatter, FormatReportForm pub use crate::formatting::report::{FormatReport, FormatResult}; use crate::formatting::format_input_inner; -use crate::{ - emitter::{Color, Verbosity}, - result::{ErrorKind, FormatError, OperationError}, -}; +use crate::{emitter::Verbosity, result::OperationError}; #[cfg(feature = "config")] pub mod config; diff --git a/rustfmt-core/rustfmt-lib/src/test/mod.rs b/rustfmt-core/rustfmt-lib/src/test/mod.rs index 606354de3d8..b6f9aff7535 100644 --- a/rustfmt-core/rustfmt-lib/src/test/mod.rs +++ b/rustfmt-core/rustfmt-lib/src/test/mod.rs @@ -10,9 +10,9 @@ use crate::emitter::rustfmt_diff::{make_diff, print_diff, Mismatch, ModifiedChun use crate::config::{Config, FileName, NewlineStyle}; use crate::{ - emitter::{emit_format_report, EmitMode, EmitterConfig}, - format, is_nightly_channel, Color, FormatReport, FormatReportFormatterBuilder, Input, - OperationError, OperationSetting, + emitter::{emit_format_report, Color, EmitMode, EmitterConfig}, + format, is_nightly_channel, FormatReport, FormatReportFormatterBuilder, Input, OperationError, + OperationSetting, }; mod configuration_snippet; From b68f06b2ead628f24911974fa2b711f353ea09f5 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 11 May 2020 21:22:54 +0900 Subject: [PATCH 41/59] Cargo fmt --- rustfmt-core/rustfmt-lib/src/formatting/matches.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/rustfmt-core/rustfmt-lib/src/formatting/matches.rs b/rustfmt-core/rustfmt-lib/src/formatting/matches.rs index 679b99e3e77..7781814c123 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/matches.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/matches.rs @@ -5,10 +5,7 @@ use std::iter::repeat; use rustc_ast::{ast, ptr}; use rustc_span::{BytePos, Span}; -use crate::config::{ - lists::*, - Config, ControlBraceStyle, IndentStyle, MatchArmLeadingPipe, -}; +use crate::config::{lists::*, Config, ControlBraceStyle, IndentStyle, MatchArmLeadingPipe}; use crate::formatting::{ comment::{combine_strs_with_missing_comments, rewrite_comment}, expr::{ From 991ab171144c2847862860e49192d0eeb6796f47 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 20 May 2020 15:38:27 +0900 Subject: [PATCH 42/59] Fix merge conflicts --- rustfmt-core/rustfmt-lib/src/formatting.rs | 3 +- rustfmt-core/rustfmt-lib/src/lib.rs | 122 --------------------- 2 files changed, 2 insertions(+), 123 deletions(-) diff --git a/rustfmt-core/rustfmt-lib/src/formatting.rs b/rustfmt-core/rustfmt-lib/src/formatting.rs index 50cb1471ac5..19a14dbcb7b 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting.rs @@ -4,6 +4,7 @@ use std::io; use std::time::{Duration, Instant}; use rustc_ast::ast; +use rustc_span::symbol; pub(crate) use syntux::session::ParseSess; @@ -499,7 +500,7 @@ impl Input { let file_stem = file.file_stem()?; if file.parent()?.to_path_buf().join(file_stem).is_dir() { Some(DirectoryOwnership::Owned { - relative: file_stem.to_str().map(ast::Ident::from_str), + relative: file_stem.to_str().map(symbol::Ident::from_str), }) } else { None diff --git a/rustfmt-core/rustfmt-lib/src/lib.rs b/rustfmt-core/rustfmt-lib/src/lib.rs index 9a37e4158c6..a0005ea151d 100644 --- a/rustfmt-core/rustfmt-lib/src/lib.rs +++ b/rustfmt-core/rustfmt-lib/src/lib.rs @@ -70,125 +70,3 @@ pub enum Input { /// A UTF-8 string, in many cases from stdin. Text(String), } - -impl Input { - fn file_name(&self) -> FileName { - match *self { - Input::File(ref file) => FileName::Real(file.clone()), - Input::Text(..) => FileName::Stdin, - } - } - - fn to_directory_ownership(&self) -> Option { - match self { - Input::File(ref file) => { - // If there exists a directory with the same name as an input, - // then the input should be parsed as a sub module. - let file_stem = file.file_stem()?; - if file.parent()?.to_path_buf().join(file_stem).is_dir() { - Some(DirectoryOwnership::Owned { - relative: file_stem.to_str().map(symbol::Ident::from_str), - }) - } else { - None - } - } - _ => None, - } - } -} - -#[cfg(test)] -mod unit_tests { - use super::*; - - #[test] - fn test_no_panic_on_format_snippet_and_format_code_block() { - // `format_snippet()` and `format_code_block()` should not panic - // even when we cannot parse the given snippet. - let snippet = "let"; - assert!(format_snippet(snippet, &Config::default()).is_none()); - assert!(format_code_block(snippet, &Config::default()).is_none()); - } - - fn test_format_inner(formatter: F, input: &str, expected: &str) -> bool - where - F: Fn(&str, &Config) -> Option, - { - let output = formatter(input, &Config::default()); - output.is_some() && output.unwrap().snippet == expected - } - - #[test] - fn test_format_snippet() { - let snippet = "fn main() { println!(\"hello, world\"); }"; - #[cfg(not(windows))] - let expected = "fn main() {\n \ - println!(\"hello, world\");\n\ - }\n"; - #[cfg(windows)] - let expected = "fn main() {\r\n \ - println!(\"hello, world\");\r\n\ - }\r\n"; - assert!(test_format_inner(format_snippet, snippet, expected)); - } - - #[test] - fn test_format_code_block_fail() { - #[rustfmt::skip] - let code_block = "this_line_is_100_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(x, y, z);"; - assert!(format_code_block(code_block, &Config::default()).is_none()); - } - - #[test] - fn test_format_code_block() { - // simple code block - let code_block = "let x=3;"; - let expected = "let x = 3;"; - assert!(test_format_inner(format_code_block, code_block, expected)); - - // more complex code block, taken from chains.rs. - let code_block = -"let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { -( -chain_indent(context, shape.add_offset(parent_rewrite.len())), -context.config.indent_style() == IndentStyle::Visual || is_small_parent, -) -} else if is_block_expr(context, &parent, &parent_rewrite) { -match context.config.indent_style() { -// Try to put the first child on the same line with parent's last line -IndentStyle::Block => (parent_shape.block_indent(context.config.tab_spaces()), true), -// The parent is a block, so align the rest of the chain with the closing -// brace. -IndentStyle::Visual => (parent_shape, false), -} -} else { -( -chain_indent(context, shape.add_offset(parent_rewrite.len())), -false, -) -}; -"; - let expected = -"let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { - ( - chain_indent(context, shape.add_offset(parent_rewrite.len())), - context.config.indent_style() == IndentStyle::Visual || is_small_parent, - ) -} else if is_block_expr(context, &parent, &parent_rewrite) { - match context.config.indent_style() { - // Try to put the first child on the same line with parent's last line - IndentStyle::Block => (parent_shape.block_indent(context.config.tab_spaces()), true), - // The parent is a block, so align the rest of the chain with the closing - // brace. - IndentStyle::Visual => (parent_shape, false), - } -} else { - ( - chain_indent(context, shape.add_offset(parent_rewrite.len())), - false, - ) -};"; - assert!(test_format_inner(format_code_block, code_block, expected)); - } -} \ No newline at end of file From fffc7ffa3b6f6e54504fc4a516351564d0db6ff7 Mon Sep 17 00:00:00 2001 From: hafiz <20735482+ayazhafiz@users.noreply.github.com> Date: Wed, 20 May 2020 10:39:34 -0500 Subject: [PATCH 43/59] Preserve comments in empty statements (#4180) * Preserve comments in empty statements Closes #4018 * fixup! Preserve comments in empty statements --- .../rustfmt-lib/src/formatting/stmt.rs | 4 ++++ .../rustfmt-lib/src/formatting/visitor.rs | 22 ++++++++++++++----- .../rustfmt-lib/tests/source/issue-4018.rs | 13 +++++++++++ .../rustfmt-lib/tests/target/issue-4018.rs | 11 ++++++++++ 4 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 rustfmt-core/rustfmt-lib/tests/source/issue-4018.rs create mode 100644 rustfmt-core/rustfmt-lib/tests/target/issue-4018.rs diff --git a/rustfmt-core/rustfmt-lib/src/formatting/stmt.rs b/rustfmt-core/rustfmt-lib/src/formatting/stmt.rs index 7e788581bc9..91d0e012c45 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/stmt.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/stmt.rs @@ -53,6 +53,10 @@ impl<'a> Stmt<'a> { result } + pub(crate) fn is_empty(&self) -> bool { + matches!(self.inner.kind, ast::StmtKind::Empty) + } + fn is_last_expr(&self) -> bool { if !self.is_last { return false; diff --git a/rustfmt-core/rustfmt-lib/src/formatting/visitor.rs b/rustfmt-core/rustfmt-lib/src/formatting/visitor.rs index e63ab4f6724..439ae081ec5 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/visitor.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/visitor.rs @@ -25,7 +25,7 @@ use crate::formatting::{ utils::{ self, contains_skip, count_newlines, depr_skip_annotation, inner_attributes, last_line_contains_single_line_comment, last_line_width, mk_sp, ptr_vec_to_ref_vec, - rewrite_ident, stmt_expr, + rewrite_ident, starts_with_newline, stmt_expr, }, }; use crate::result::{ErrorKind, FormatError}; @@ -120,10 +120,22 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.parse_sess.span_to_debug_info(stmt.span()) ); - // https://github.com/rust-lang/rust/issues/63679. - let is_all_semicolons = - |snippet: &str| snippet.chars().all(|c| c.is_whitespace() || c == ';'); - if is_all_semicolons(&self.snippet(stmt.span())) { + if stmt.is_empty() { + // If the statement is empty, just skip over it. Before that, make sure any comment + // snippet preceding the semicolon is picked up. + let snippet = self.snippet(mk_sp(self.last_pos, stmt.span().lo())); + let original_starts_with_newline = snippet + .find(|c| c != ' ') + .map_or(false, |i| starts_with_newline(&snippet[i..])); + let snippet = snippet.trim(); + if !snippet.is_empty() { + if original_starts_with_newline { + self.push_str("\n"); + } + self.push_str(&self.block_indent.to_string(self.config)); + self.push_str(snippet); + } + self.last_pos = stmt.span().hi(); return; } diff --git a/rustfmt-core/rustfmt-lib/tests/source/issue-4018.rs b/rustfmt-core/rustfmt-lib/tests/source/issue-4018.rs new file mode 100644 index 00000000000..9a91dd9a306 --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/source/issue-4018.rs @@ -0,0 +1,13 @@ +fn main() { + ; + /* extra comment */ ; +} + +fn main() { + println!(""); + // comment 1 + // comment 2 + // comment 3 + // comment 4 + ; +} diff --git a/rustfmt-core/rustfmt-lib/tests/target/issue-4018.rs b/rustfmt-core/rustfmt-lib/tests/target/issue-4018.rs new file mode 100644 index 00000000000..cef3be06148 --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/target/issue-4018.rs @@ -0,0 +1,11 @@ +fn main() { + /* extra comment */ +} + +fn main() { + println!(""); + // comment 1 + // comment 2 + // comment 3 + // comment 4 +} From 037c0645a9aba48f56bfb8f998ba95a3c8554cab Mon Sep 17 00:00:00 2001 From: hafiz <20735482+ayazhafiz@users.noreply.github.com> Date: Wed, 20 May 2020 20:38:06 -0500 Subject: [PATCH 44/59] Add test cases for fixed issues (#4189) --- .../rustfmt-lib/tests/source/issue-3550.rs | 37 ++++++++++++++++++ .../rustfmt-lib/tests/target/issue-3068.rs | 14 +++++++ .../rustfmt-lib/tests/target/issue-3550.rs | 39 +++++++++++++++++++ .../rustfmt-lib/tests/target/issue-3638.rs | 19 +++++++++ .../rustfmt-lib/tests/target/issue-3858.rs | 12 ++++++ .../rustfmt-lib/tests/target/issue-3936.rs | 9 +++++ 6 files changed, 130 insertions(+) create mode 100644 rustfmt-core/rustfmt-lib/tests/source/issue-3550.rs create mode 100644 rustfmt-core/rustfmt-lib/tests/target/issue-3068.rs create mode 100644 rustfmt-core/rustfmt-lib/tests/target/issue-3550.rs create mode 100644 rustfmt-core/rustfmt-lib/tests/target/issue-3638.rs create mode 100644 rustfmt-core/rustfmt-lib/tests/target/issue-3858.rs create mode 100644 rustfmt-core/rustfmt-lib/tests/target/issue-3936.rs diff --git a/rustfmt-core/rustfmt-lib/tests/source/issue-3550.rs b/rustfmt-core/rustfmt-lib/tests/source/issue-3550.rs new file mode 100644 index 00000000000..b6a34c06684 --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/source/issue-3550.rs @@ -0,0 +1,37 @@ +fn main() { + assert(long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long(), + ); + + assert!(long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long(),); +} + diff --git a/rustfmt-core/rustfmt-lib/tests/target/issue-3068.rs b/rustfmt-core/rustfmt-lib/tests/target/issue-3068.rs new file mode 100644 index 00000000000..198d6385e6e --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/target/issue-3068.rs @@ -0,0 +1,14 @@ +// rustfmt-hard_tabs: true +// rustfmt-single_line_if_else_max_width: 10 + +macro_rules! foo { + ($bar: expr, $t: ty) => { + $bar(|x| { + if x { + None + } else { + None + } + }) + }; +} diff --git a/rustfmt-core/rustfmt-lib/tests/target/issue-3550.rs b/rustfmt-core/rustfmt-lib/tests/target/issue-3550.rs new file mode 100644 index 00000000000..49fd8423cad --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/target/issue-3550.rs @@ -0,0 +1,39 @@ +fn main() { + assert( + long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long(), + ); + + assert!( + long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long() + .long(), + ); +} diff --git a/rustfmt-core/rustfmt-lib/tests/target/issue-3638.rs b/rustfmt-core/rustfmt-lib/tests/target/issue-3638.rs new file mode 100644 index 00000000000..8f63f10213d --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/target/issue-3638.rs @@ -0,0 +1,19 @@ +macro_rules! abait { + ($x:expr) => { + Ok(()) + }; +} + +mod a { + fn foo() -> Result<(), ()> { + unsafe { + ( + abait!( + proxy.load_account(ahc_client_end, TEST_ACCOUNT_ID.clone().as_mut().into()) + )?, + (), + ) + }; + Ok(()) + } +} diff --git a/rustfmt-core/rustfmt-lib/tests/target/issue-3858.rs b/rustfmt-core/rustfmt-lib/tests/target/issue-3858.rs new file mode 100644 index 00000000000..d06a615b160 --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/target/issue-3858.rs @@ -0,0 +1,12 @@ +// rustfmt-hard_tabs: true + +macro_rules! member_mut { + ($self:expr, $member:expr) => {{ + use self::Member::*; + let r = &mut *$self; + match $member { + A => &mut r.a, + B => &mut r.b, + } + }}; +} diff --git a/rustfmt-core/rustfmt-lib/tests/target/issue-3936.rs b/rustfmt-core/rustfmt-lib/tests/target/issue-3936.rs new file mode 100644 index 00000000000..88e73e12154 --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/target/issue-3936.rs @@ -0,0 +1,9 @@ +// rustfmt-hard_tabs: true + +macro_rules! m { + ($a:expr) => { + if $a { + return; + } + }; +} From 25d5f9fb36c968997f5315b922e9ff0d58057419 Mon Sep 17 00:00:00 2001 From: hafiz <20735482+ayazhafiz@users.noreply.github.com> Date: Wed, 20 May 2020 22:25:25 -0500 Subject: [PATCH 45/59] Do not break empty blocks in match arm patterns (#4187) --- .../rustfmt-lib/src/formatting/matches.rs | 15 +++++++++--- .../rustfmt-lib/tests/source/issue-4125.rs | 19 +++++++++++++++ .../rustfmt-lib/tests/target/issue-4125.rs | 24 +++++++++++++++++++ .../rustfmt-lib/tests/target/match.rs | 4 ++-- 4 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 rustfmt-core/rustfmt-lib/tests/source/issue-4125.rs create mode 100644 rustfmt-core/rustfmt-lib/tests/target/issue-4125.rs diff --git a/rustfmt-core/rustfmt-lib/src/formatting/matches.rs b/rustfmt-core/rustfmt-lib/src/formatting/matches.rs index 7781814c123..a8a368a70a8 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/matches.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/matches.rs @@ -249,8 +249,17 @@ fn rewrite_match_arm( }; // Patterns - // 5 = ` => {` - let pat_shape = shape.sub_width(5)?.offset_left(pipe_offset)?; + let is_empty_block = if let ast::ExprKind::Block(ref block, _) = arm.body.kind { + is_empty_block(context, block, Some(&arm.body.attrs)) + } else { + false + }; + let sub_width = if is_empty_block { + " => {}".len() + } else { + " => {".len() + }; + let pat_shape = shape.sub_width(sub_width)?.offset_left(pipe_offset)?; let pats_str = arm.pat.rewrite(context, pat_shape)?; @@ -480,7 +489,7 @@ fn rewrite_match_body( match rewrite { Some(ref body_str) - if is_block + if (is_block && (!is_empty_block || !body_str.contains('\n'))) || (!body_str.contains('\n') && unicode_str_width(body_str) <= body_shape.width) => { diff --git a/rustfmt-core/rustfmt-lib/tests/source/issue-4125.rs b/rustfmt-core/rustfmt-lib/tests/source/issue-4125.rs new file mode 100644 index 00000000000..6eab7299442 --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/source/issue-4125.rs @@ -0,0 +1,19 @@ +// rustfmt-max_width: 60 + +fn main() { + match (pat, num) { + (PatternOne, 1) | (RoomForBlockOnSameLine, 10) => {} + + (PatternOne, 1) | (PatternStretchedToBounds, 2) => {} + + UnsplitableVeryLongArmPatternWithRoomForBlock0 => {} + + UnsplitableVeryLongArmPatternWithBraceAtEndOfLn => {} + + UnsplitableVeryLongArmPatternWithArrowAtColnWidth => {} + + UnsplitableVeryLongArmPatternWithArrowPastColnWidth => {} + + UnsplitableVeryLongArmPatternGoingBeyondMaxColumnWidth => {} + } +} diff --git a/rustfmt-core/rustfmt-lib/tests/target/issue-4125.rs b/rustfmt-core/rustfmt-lib/tests/target/issue-4125.rs new file mode 100644 index 00000000000..7a8114e5590 --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/target/issue-4125.rs @@ -0,0 +1,24 @@ +// rustfmt-max_width: 60 + +fn main() { + match (pat, num) { + (PatternOne, 1) | (RoomForBlockOnSameLine, 10) => {} + + (PatternOne, 1) + | (PatternStretchedToBounds, 2) => {} + + UnsplitableVeryLongArmPatternWithRoomForBlock0 => {} + + UnsplitableVeryLongArmPatternWithBraceAtEndOfLn => + {} + + UnsplitableVeryLongArmPatternWithArrowAtColnWidth => + {} + + UnsplitableVeryLongArmPatternWithArrowPastColnWidth => + {} + + UnsplitableVeryLongArmPatternGoingBeyondMaxColumnWidth => + {} + } +} diff --git a/rustfmt-core/rustfmt-lib/tests/target/match.rs b/rustfmt-core/rustfmt-lib/tests/target/match.rs index 7d207ca4b2c..b02eca78d64 100644 --- a/rustfmt-core/rustfmt-lib/tests/target/match.rs +++ b/rustfmt-core/rustfmt-lib/tests/target/match.rs @@ -124,8 +124,8 @@ fn issue339() { // collapsing here is safe ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff => {} // collapsing here exceeds line length - ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffg => { - } + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffg => + {} h => { // comment above block } i => {} // comment below block From 0e3d5f0f6e8bbe472e46e426d8d25fe037df303b Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 22 May 2020 10:47:57 +0900 Subject: [PATCH 46/59] Add cargo-make support (#4191) --- .cargo/Makefile.toml | 14 +++++++ .cargo/config | 12 ------ .github/workflows/linux.yml | 10 +++-- .github/workflows/mac.yml | 10 +++-- .github/workflows/windows.yml | 11 ++--- .travis.yml | 4 +- Makefile.toml | 41 +++++++++++++++++++ ci/integration.sh | 18 +------- rustfmt-core/Makefile.toml | 4 ++ rustfmt-core/rustfmt-bin/Makefile.toml | 1 + rustfmt-core/rustfmt-lib/Makefile.toml | 1 + .../config_proc_macro/Makefile.toml | 1 + 12 files changed, 84 insertions(+), 43 deletions(-) create mode 100644 .cargo/Makefile.toml delete mode 100644 .cargo/config create mode 100644 Makefile.toml create mode 100644 rustfmt-core/Makefile.toml create mode 100644 rustfmt-core/rustfmt-bin/Makefile.toml create mode 100644 rustfmt-core/rustfmt-lib/Makefile.toml create mode 100644 rustfmt-core/rustfmt-lib/config_proc_macro/Makefile.toml diff --git a/.cargo/Makefile.toml b/.cargo/Makefile.toml new file mode 100644 index 00000000000..3f771a9dfd3 --- /dev/null +++ b/.cargo/Makefile.toml @@ -0,0 +1,14 @@ +# This Makefile.toml defines common tasks and settings used in the rustfmt project. + +[env] +CFG_RELEASE = { value = "nightly", condition = { env_not_set = ["CFG_RELEASE"] } } +CFG_RELEASE_CHANNEL = { value = "nightly", condition = { env_not_set = ["CFG_RELEASE_CHANNEL"] } } + +[tasks.b] +alias = "build" + +[tasks.c] +alias = "check" + +[tasks.t] +alias = "test" diff --git a/.cargo/config b/.cargo/config deleted file mode 100644 index b6df9194d4b..00000000000 --- a/.cargo/config +++ /dev/null @@ -1,12 +0,0 @@ -[alias] -t = "test-all" -ta = "test-all" -test-all = "test --manifest-path rustfmt-core/Cargo.toml" - -test-bin = "test --manifest-path rustfmt-core/rustfmt-bin/Cargo.toml" -tb = "test-bin" - -test-lib = "test --manifest-path rustfmt-core/rustfmt-lib/Cargo.toml" -tl = "test-lib" - -i = "install --path . --force --locked" diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 6074c9c76b5..559eaec1595 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -39,13 +39,15 @@ jobs: override: true profile: minimal default: true + + - name: cargo-make + run: cargo install --force cargo-make + - name: build run: | rustc -Vv cargo -V - cargo build --manifest-path rustfmt-core/Cargo.toml --workspace + cargo make build - name: test - run: cargo test-all - - name: test ignored - run: cargo test-all -- --ignored + run: cargo make test diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index 183d5dc7bc7..39a6c1cc4d2 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -32,13 +32,15 @@ jobs: override: true profile: minimal default: true + + - name: cargo-make + run: cargo install --force cargo-make + - name: build run: | rustc -Vv cargo -V - cargo build --manifest-path rustfmt-core/Cargo.toml --workspace + cargo make build - name: test - run: cargo test-all - - name: test ignored - run: cargo test-all -- --ignored + run: cargo make test diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index dcb80852611..e3b95ee115d 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -82,16 +82,17 @@ jobs: override: true profile: minimal default: true + + - name: cargo-make + run: cargo install --force cargo-make + - name: build run: | rustc -Vv cargo -V - cargo build --manifest-path rustfmt-core/Cargo.toml --workspace + cargo make build shell: cmd - name: test - run: cargo test-all - shell: cmd - - name: test ignored - run: cargo test-all -- --ignored + run: cargo make test shell: cmd diff --git a/.travis.yml b/.travis.yml index 7f92a175f00..f59f51f0470 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,8 +45,8 @@ matrix: script: - | - export CFG_RELEASE_CHANNEL=nightly - export CFG_RELEASE=nightly + export CFG_RELEASE_CHANNEL=nightly + export CFG_RELEASE=nightly if [ -z ${INTEGRATION} ]; then cargo build && cargo test && cargo test -- --ignored && cargo test --manifest-path rustfmt-core/Cargo.toml && cargo test --manifest-path rustfmt-core/Cargo.toml -- --ignored else diff --git a/Makefile.toml b/Makefile.toml new file mode 100644 index 00000000000..e26685aba54 --- /dev/null +++ b/Makefile.toml @@ -0,0 +1,41 @@ +extend = ".cargo/Makefile.toml" + +[tasks.build] +clear = true +command = "cargo" +args = [ + "build", + "--manifest-path", + "rustfmt-core/Cargo.toml", + "--workspace", +] + +[tasks.install] +command = "cargo" +args = [ + "install", + "--path", + ".", + "--force", + "--locked", +] + +[tasks.test] +clear = true +run_task = { name = ["test-bin", "test-lib"] } + +[tasks.test-bin] +env = { "RUSTFMT_MAKE_MANIFEST_PATH" = "rustfmt-core/rustfmt-bin/Cargo.toml" } +run_task = "test-subproject" + +[tasks.test-lib] +env = { "RUSTFMT_MAKE_MANIFEST_PATH" = "rustfmt-core/rustfmt-lib/Cargo.toml" } +run_task = "test-subproject" + +[tasks.test-subproject] +condition = { env_set = ["RUSTFMT_MAKE_MANIFEST_PATH"] } +script_runner = "@shell" +script = [ + "cargo test --manifest-path ${RUSTFMT_MAKE_MANIFEST_PATH}", + "cargo test --manifest-path ${RUSTFMT_MAKE_MANIFEST_PATH} -- --ignored", +] diff --git a/ci/integration.sh b/ci/integration.sh index 823f176a95b..09d0fb959f5 100755 --- a/ci/integration.sh +++ b/ci/integration.sh @@ -4,22 +4,8 @@ set -ex : ${INTEGRATION?"The INTEGRATION environment variable must be set."} -# FIXME: this means we can get a stale cargo-fmt from a previous run. -# -# `which rustfmt` fails if rustfmt is not found. Since we don't install -# `rustfmt` via `rustup`, this is the case unless we manually install it. Once -# that happens, `cargo install --force` will be called, which installs -# `rustfmt`, `cargo-fmt`, etc to `~/.cargo/bin`. This directory is cached by -# travis (see `.travis.yml`'s "cache" key), such that build-bots that arrive -# here after the first installation will find `rustfmt` and won't need to build -# it again. -# -#which cargo-fmt || cargo install --force - -export CFG_RELEASE_CHANNEL=nightly -export CFG_RELEASE=nightly - -cargo install --path . --force --locked +which cargo-make || cargo install --force cargo-make +cargo make install echo "Integration tests for: ${INTEGRATION}" cargo fmt -- --version diff --git a/rustfmt-core/Makefile.toml b/rustfmt-core/Makefile.toml new file mode 100644 index 00000000000..632f925a4ec --- /dev/null +++ b/rustfmt-core/Makefile.toml @@ -0,0 +1,4 @@ +extend = { path = "../.cargo/Makefile.toml" } + +[env] +CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = "true" diff --git a/rustfmt-core/rustfmt-bin/Makefile.toml b/rustfmt-core/rustfmt-bin/Makefile.toml new file mode 100644 index 00000000000..65706bdf2d4 --- /dev/null +++ b/rustfmt-core/rustfmt-bin/Makefile.toml @@ -0,0 +1 @@ +extend = { path = "../Makefile.toml" } diff --git a/rustfmt-core/rustfmt-lib/Makefile.toml b/rustfmt-core/rustfmt-lib/Makefile.toml new file mode 100644 index 00000000000..65706bdf2d4 --- /dev/null +++ b/rustfmt-core/rustfmt-lib/Makefile.toml @@ -0,0 +1 @@ +extend = { path = "../Makefile.toml" } diff --git a/rustfmt-core/rustfmt-lib/config_proc_macro/Makefile.toml b/rustfmt-core/rustfmt-lib/config_proc_macro/Makefile.toml new file mode 100644 index 00000000000..65706bdf2d4 --- /dev/null +++ b/rustfmt-core/rustfmt-lib/config_proc_macro/Makefile.toml @@ -0,0 +1 @@ +extend = { path = "../Makefile.toml" } From b56a370cfc094226d34cc0b80ce38ee96a3737e6 Mon Sep 17 00:00:00 2001 From: hafiz <20735482+ayazhafiz@users.noreply.github.com> Date: Fri, 22 May 2020 04:53:22 -0500 Subject: [PATCH 47/59] Parse comma-separated branches in macro definitions (#4173) --- .../rustfmt-lib/src/formatting/macros.rs | 30 +++++++++++-------- .../rustfmt-lib/tests/target/issue-4111.rs | 21 +++++++++++++ .../rustfmt-lib/tests/target/macro_rules.rs | 8 ++--- 3 files changed, 42 insertions(+), 17 deletions(-) create mode 100644 rustfmt-core/rustfmt-lib/tests/target/issue-4111.rs diff --git a/rustfmt-core/rustfmt-lib/src/formatting/macros.rs b/rustfmt-core/rustfmt-lib/src/formatting/macros.rs index c8fc0f0a0ce..b1e8b669562 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/macros.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/macros.rs @@ -497,7 +497,7 @@ pub(crate) fn rewrite_macro_def( } let ts = def.body.inner_tokens(); let mut parser = MacroParser::new(ts.into_trees()); - let parsed_def = match parser.parse() { + let parsed_def = match parser.parse(def.macro_rules) { Some(def) => def, None => return snippet, }; @@ -544,8 +544,12 @@ pub(crate) fn rewrite_macro_def( .collect::>(); let fmt = ListFormatting::new(arm_shape, context.config) - .separator(if def.macro_rules { ";" } else { "" }) - .trailing_separator(SeparatorTactic::Always) + .separator(if def.macro_rules { ";" } else { "," }) + .trailing_separator(if def.macro_rules || multi_branch_style { + SeparatorTactic::Always + } else { + SeparatorTactic::Never + }) .preserve_newline(true); if multi_branch_style { @@ -1250,17 +1254,17 @@ impl MacroParser { } // (`(` ... `)` `=>` `{` ... `}`)* - fn parse(&mut self) -> Option { + fn parse(&mut self, is_macro_rules: bool) -> Option { let mut branches = vec![]; while self.toks.look_ahead(1).is_some() { - branches.push(self.parse_branch()?); + branches.push(self.parse_branch(is_macro_rules)?); } Some(Macro { branches }) } // `(` ... `)` `=>` `{` ... `}` - fn parse_branch(&mut self) -> Option { + fn parse_branch(&mut self, is_macro_rules: bool) -> Option { let tok = self.toks.next()?; let (lo, args_paren_kind) = match tok { TokenTree::Token(..) => return None, @@ -1285,13 +1289,13 @@ impl MacroParser { ) } }; - if let Some(TokenTree::Token(Token { - kind: TokenKind::Semi, - span, - })) = self.toks.look_ahead(0) - { - self.toks.next(); - hi = span.hi(); + if let Some(TokenTree::Token(Token { kind, span })) = self.toks.look_ahead(0) { + if (is_macro_rules && kind == TokenKind::Semi) + || (!is_macro_rules && kind == TokenKind::Comma) + { + self.toks.next(); + hi = span.hi(); + } } Some(MacroBranch { span: mk_sp(lo, hi), diff --git a/rustfmt-core/rustfmt-lib/tests/target/issue-4111.rs b/rustfmt-core/rustfmt-lib/tests/target/issue-4111.rs new file mode 100644 index 00000000000..69fe4ca70f7 --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/target/issue-4111.rs @@ -0,0 +1,21 @@ +// rustfmt-format_macro_bodies: true +// rustfmt-format_macro_matchers: true + +pub macro scalar($m:ident, $t:ident) { + pub macro $m { + () => { + Val::$t($t::default()) + }, + ($v: expr) => { + Val::$t($t::new($v)) + }, + } + pub macro a { + () => { + Val::$t($t::default()) + }, + ($v: expr) => { + Val::$t($t::new($v)) + }, + } +} diff --git a/rustfmt-core/rustfmt-lib/tests/target/macro_rules.rs b/rustfmt-core/rustfmt-lib/tests/target/macro_rules.rs index 68052b25f48..a83f334cb63 100644 --- a/rustfmt-core/rustfmt-lib/tests/target/macro_rules.rs +++ b/rustfmt-core/rustfmt-lib/tests/target/macro_rules.rs @@ -102,21 +102,21 @@ macro m2 { ($expr:expr, $($func:ident)*) => {{ let x = $expr; $func(x) - }} + }}, /* b */ () => { /* c */ - } + }, - (@tag) => {} + (@tag) => {}, // d ($item:ident) => { mod macro_item { struct $item; } - } + }, } // #2438, #2476 From 24fa6398c34e48999709692ab489bf506e6b5e52 Mon Sep 17 00:00:00 2001 From: mahkoh Date: Fri, 22 May 2020 11:55:34 +0200 Subject: [PATCH 48/59] Fix module resolution in inner modules with paths (#4194) --- .../rustfmt-lib/src/formatting/modules.rs | 17 +---------------- .../tests/target/inner-module-path/b.rs | 1 + .../tests/target/inner-module-path/c/d.rs | 1 + .../tests/target/inner-module-path/lib.rs | 10 ++++++++++ 4 files changed, 13 insertions(+), 16 deletions(-) create mode 100644 rustfmt-core/rustfmt-lib/tests/target/inner-module-path/b.rs create mode 100644 rustfmt-core/rustfmt-lib/tests/target/inner-module-path/c/d.rs create mode 100644 rustfmt-core/rustfmt-lib/tests/target/inner-module-path/lib.rs diff --git a/rustfmt-core/rustfmt-lib/src/formatting/modules.rs b/rustfmt-core/rustfmt-lib/src/formatting/modules.rs index cb49b62094c..eee19502906 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/modules.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/modules.rs @@ -37,8 +37,6 @@ enum SubModKind<'a, 'ast> { External(PathBuf, DirectoryOwnership, Cow<'ast, ast::Mod>), /// `mod foo;` with multiple sources. MultiExternal(Vec<(PathBuf, DirectoryOwnership, Cow<'ast, ast::Mod>)>), - /// `#[path = "..."] mod foo {}` - InternalWithPath(PathBuf), /// `mod foo {}` Internal(&'a ast::Item), } @@ -154,12 +152,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { self.find_external_module(item.ident, &item.attrs, sub_mod) } else { // An internal module (`mod foo { /* ... */ }`); - if let Some(path) = find_path_value(&item.attrs) { - let path = Path::new(&*path.as_str()).to_path_buf(); - Ok(Some(SubModKind::InternalWithPath(path))) - } else { - Ok(Some(SubModKind::Internal(item))) - } + Ok(Some(SubModKind::Internal(item))) } } @@ -199,14 +192,6 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { }; self.visit_sub_mod_after_directory_update(sub_mod, Some(directory)) } - SubModKind::InternalWithPath(mod_path) => { - // All `#[path]` files are treated as though they are a `mod.rs` file. - let directory = Directory { - path: mod_path, - ownership: DirectoryOwnership::Owned { relative: None }, - }; - self.visit_sub_mod_after_directory_update(sub_mod, Some(directory)) - } SubModKind::Internal(ref item) => { self.push_inline_mod_directory(item.ident, &item.attrs); self.visit_sub_mod_after_directory_update(sub_mod, None) diff --git a/rustfmt-core/rustfmt-lib/tests/target/inner-module-path/b.rs b/rustfmt-core/rustfmt-lib/tests/target/inner-module-path/b.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/target/inner-module-path/b.rs @@ -0,0 +1 @@ + diff --git a/rustfmt-core/rustfmt-lib/tests/target/inner-module-path/c/d.rs b/rustfmt-core/rustfmt-lib/tests/target/inner-module-path/c/d.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/target/inner-module-path/c/d.rs @@ -0,0 +1 @@ + diff --git a/rustfmt-core/rustfmt-lib/tests/target/inner-module-path/lib.rs b/rustfmt-core/rustfmt-lib/tests/target/inner-module-path/lib.rs new file mode 100644 index 00000000000..fb75d70cd93 --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/target/inner-module-path/lib.rs @@ -0,0 +1,10 @@ +// rustfmt-recursive: true + +#[path = "."] +mod a { + mod b; +} + +mod c { + mod d; +} From 5b627100e0a55afb8b71c2dd6b5d25e9349f2e92 Mon Sep 17 00:00:00 2001 From: mahkoh Date: Sat, 23 May 2020 14:53:49 +0200 Subject: [PATCH 49/59] Update Contributing.md (#4195) --- Contributing.md | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/Contributing.md b/Contributing.md index 80ce4e76e8a..d25e5256bdd 100644 --- a/Contributing.md +++ b/Contributing.md @@ -9,6 +9,22 @@ on issues, or file new issues specifically to get help. All contributors are expected to follow our [Code of Conduct](CODE_OF_CONDUCT.md). +# Building and Testing + +Rustfmt requires a nightly compiler. Replace all invocations of `cargo` by +`cargo +nightly` if necessary. + +At all times the environment variables `CFG_RELEASE_CHANNEL` and `CFG_RELEASE` must +be set to either `nightly` or `beta`. Both should be set to the same value. The +project supports [cargo-make](https://github.com/sagiegurari/cargo-make) which +automatically sets these variables for you: + +``` +cargo +nightly make test +``` + +The available tasks are listed in `Makefile.toml`. + ## Test and file issues It would be really useful to have people use rustfmt on their projects and file @@ -20,18 +36,19 @@ issues where it does something you don't expect. Having a strong test suite for a tool like this is essential. It is very easy to create regressions. Any tests you can add are very much appreciated. -The tests can be run with `cargo test`. This does a number of things: +The tests can be run with `cargo make test`. This does a number of things: * runs the unit tests for a number of internal functions; -* makes sure that rustfmt run on every file in `./tests/source/` is equal to its - associated file in `./tests/target/`; -* runs idempotence tests on the files in `./tests/target/`. These files should - not be changed by rustfmt; +* makes sure that rustfmt run on every file in `rustfmt-core/rustfmt-lib/tests/source/` + is equal to its associated file in `rustfmt-core/rustfmt-lib/tests/target/`; +* runs idempotence tests on the files in `rustfmt-core/rustfmt-lib/tests/target/`. + These files should not be changed by rustfmt; * checks that rustfmt's code is not changed by running on itself. This ensures that the project bootstraps. -Creating a test is as easy as creating a new file in `./tests/source/` and an -equally named one in `./tests/target/`. If it is only required that rustfmt -leaves a piece of code unformatted, it may suffice to only create a target file. +Creating a test is as easy as creating a new file in +`rustfmt-core/rustfmt-lib/tests/source/` and an equally named one in +`rustfmt-core/rustfmt-lib/tests/target/`. If it is only required that rustfmt leaves a +piece of code unformatted, it may suffice to only create a target file. Whenever there's a discrepancy between the expected output when running tests, a colourised diff will be printed so that the offending line(s) can quickly be From 20a52b7bd9159815acdabb7df3900f6f54d75940 Mon Sep 17 00:00:00 2001 From: BO41 Date: Sat, 23 May 2020 14:43:55 +0000 Subject: [PATCH 50/59] Align string type for edition (#4197) --- Configurations.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Configurations.md b/Configurations.md index 26dd316fb61..869d152967b 100644 --- a/Configurations.md +++ b/Configurations.md @@ -519,8 +519,8 @@ fn main() { Specifies which edition is used by the parser. -- **Default value**: `2015` -- **Possible values**: `2015`, `2018` +- **Default value**: `"2015"` +- **Possible values**: `"2015"`, `"2018"` - **Stable**: Yes Rustfmt is able to pick up the edition used by reading the `Cargo.toml` file if executed @@ -2621,4 +2621,4 @@ 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. -``` \ No newline at end of file +``` From b042b379b1bda5e2d08cfeb19ac3a11adb4c2f2b Mon Sep 17 00:00:00 2001 From: hafiz <20735482+ayazhafiz@users.noreply.github.com> Date: Sat, 23 May 2020 22:28:16 -0500 Subject: [PATCH 51/59] Merge configs from parent directories (#4179) --- ci/integration.sh | 14 +- rustfmt-core/rustfmt-bin/src/bin/main.rs | 21 +- rustfmt-core/rustfmt-lib/src/config.rs | 192 +++++++++++++----- .../rustfmt-lib/src/config/config_type.rs | 27 ++- .../rustfmt-lib/src/config/options.rs | 67 ++++++ 5 files changed, 253 insertions(+), 68 deletions(-) diff --git a/ci/integration.sh b/ci/integration.sh index 09d0fb959f5..86980eb11bc 100755 --- a/ci/integration.sh +++ b/ci/integration.sh @@ -71,25 +71,27 @@ function show_head { echo "Head commit of ${INTEGRATION}: $head" } +tempdir=$(mktemp -d) + case ${INTEGRATION} in cargo) - git clone --depth=1 https://github.com/rust-lang/${INTEGRATION}.git - cd ${INTEGRATION} + git clone --depth=1 https://github.com/rust-lang/${INTEGRATION}.git ${tempdir} + cd ${tempdir} show_head export CFG_DISABLE_CROSS_TESTS=1 check_fmt_with_all_tests cd - ;; crater) - git clone --depth=1 https://github.com/rust-lang-nursery/${INTEGRATION}.git - cd ${INTEGRATION} + git clone --depth=1 https://github.com/rust-lang-nursery/${INTEGRATION}.git ${tempdir} + cd ${tempdir} show_head check_fmt_with_lib_tests cd - ;; *) - git clone --depth=1 https://github.com/rust-lang-nursery/${INTEGRATION}.git - cd ${INTEGRATION} + git clone --depth=1 https://github.com/rust-lang-nursery/${INTEGRATION}.git ${tempdir} + cd ${tempdir} show_head check_fmt_with_all_tests cd - diff --git a/rustfmt-core/rustfmt-bin/src/bin/main.rs b/rustfmt-core/rustfmt-bin/src/bin/main.rs index a36f63b58c9..9839dfa7ad3 100644 --- a/rustfmt-core/rustfmt-bin/src/bin/main.rs +++ b/rustfmt-core/rustfmt-bin/src/bin/main.rs @@ -425,7 +425,7 @@ fn format_string(input: String, opt: Opt) -> Result { enum FileConfig { Default, - Local(Config, Option), + Local(Config, Option>), } struct FileConfigPair<'a> { @@ -457,9 +457,9 @@ impl<'a> Iterator for FileConfigPairIter<'a> { let config = if self.has_config_from_commandline { FileConfig::Default } else { - let (local_config, config_path) = + let (local_config, config_paths) = load_config(Some(file.parent()?), Some(self.opt)).ok()?; - FileConfig::Local(local_config, config_path) + FileConfig::Local(local_config, config_paths) }; Some(FileConfigPair { file, config }) @@ -483,11 +483,18 @@ fn format(opt: Opt) -> Result { return Err(format_err!("Error: `{}` is a directory", dir.display())); } - let (default_config, config_path) = load_config(None, Some(&opt))?; + let (default_config, config_paths) = load_config(None, Some(&opt))?; if opt.verbose { - if let Some(path) = config_path.as_ref() { - println!("Using rustfmt config file {}", path.display()); + if let Some(paths) = config_paths.as_ref() { + println!( + "Using rustfmt config file(s) {}", + paths + .into_iter() + .map(|p| p.display().to_string()) + .collect::>() + .join(","), + ); } } @@ -496,7 +503,7 @@ fn format(opt: Opt) -> Result { verbosity: opt.verbosity(), }; - let inputs = FileConfigPairIter::new(&opt, config_path.is_some()).collect::>(); + let inputs = FileConfigPairIter::new(&opt, config_paths.is_some()).collect::>(); let format_report = format_inputs( inputs.iter().map(|p| { ( diff --git a/rustfmt-core/rustfmt-lib/src/config.rs b/rustfmt-core/rustfmt-lib/src/config.rs index 76bd0d89055..1f0a48d05f2 100644 --- a/rustfmt-core/rustfmt-lib/src/config.rs +++ b/rustfmt-core/rustfmt-lib/src/config.rs @@ -170,6 +170,43 @@ impl PartialConfig { ::toml::to_string(&cloned).map_err(ToTomlError) } + + pub fn from_toml_path(file_path: &Path) -> Result { + let mut file = File::open(&file_path)?; + let mut toml = String::new(); + file.read_to_string(&mut toml)?; + PartialConfig::from_toml(&toml).map_err(|err| Error::new(ErrorKind::InvalidData, err)) + } + + fn from_toml(toml: &str) -> Result { + let parsed: ::toml::Value = toml + .parse() + .map_err(|e| format!("Could not parse TOML: {}", e))?; + let mut err = String::new(); + let table = parsed + .as_table() + .ok_or_else(|| String::from("Parsed config was not table"))?; + for key in table.keys() { + if !Config::is_valid_name(key) { + let msg = &format!("Warning: Unknown configuration option `{}`\n", key); + err.push_str(msg) + } + } + match parsed.try_into() { + Ok(parsed_config) => { + if !err.is_empty() { + eprint!("{}", err); + } + Ok(parsed_config) + } + Err(e) => { + err.push_str("Error: Decoding config file failed:\n"); + err.push_str(format!("{}\n", e).as_str()); + err.push_str("Please check your config file."); + Err(err) + } + } + } } impl Config { @@ -197,11 +234,8 @@ impl Config { /// Returns a `Config` if the config could be read and parsed from /// the file, otherwise errors. pub fn from_toml_path(file_path: &Path) -> Result { - let mut file = File::open(&file_path)?; - let mut toml = String::new(); - file.read_to_string(&mut toml)?; - Config::from_toml(&toml, file_path.parent().unwrap()) - .map_err(|err| Error::new(ErrorKind::InvalidData, err)) + let partial_config = PartialConfig::from_toml_path(file_path)?; + Ok(Config::default().fill_from_parsed_config(partial_config, file_path.parent().unwrap())) } /// Resolves the config for input in `dir`. @@ -213,11 +247,11 @@ impl Config { /// /// Returns the `Config` to use, and the path of the project file if there was /// one. - pub fn from_resolved_toml_path(dir: &Path) -> Result<(Config, Option), Error> { + pub fn from_resolved_toml_path(dir: &Path) -> Result<(Config, Option>), Error> { /// Try to find a project file in the given directory and its parents. /// Returns the path of a the nearest project file if one exists, /// or `None` if no project file was found. - fn resolve_project_file(dir: &Path) -> Result, Error> { + fn resolve_project_files(dir: &Path) -> Result>, Error> { let mut current = if dir.is_relative() { env::current_dir()?.join(dir) } else { @@ -225,13 +259,11 @@ impl Config { }; current = dunce::canonicalize(current)?; + let mut paths = Vec::new(); loop { - match get_toml_path(¤t) { - Ok(Some(path)) => return Ok(Some(path)), - Err(e) => return Err(e), - _ => (), - } + let current_toml_path = get_toml_path(¤t)?; + paths.push(current_toml_path); // If the current directory has no parent, we're done searching. if !current.pop() { @@ -239,10 +271,19 @@ impl Config { } } + // List of closest -> most distant rustfmt config from the current directory. + let config_paths: Option> = paths.into_iter().filter(|p| p.is_some()).collect(); + let has_paths = config_paths + .as_ref() + .map_or(false, |paths| !paths.is_empty()); + if has_paths { + return Ok(config_paths); + } + // If nothing was found, check in the home directory. if let Some(home_dir) = dirs::home_dir() { if let Some(path) = get_toml_path(&home_dir)? { - return Ok(Some(path)); + return Ok(Some(vec![path])); } } @@ -250,48 +291,33 @@ impl Config { if let Some(mut config_dir) = dirs::config_dir() { config_dir.push("rustfmt"); if let Some(path) = get_toml_path(&config_dir)? { - return Ok(Some(path)); + return Ok(Some(vec![path])); } } Ok(None) } - match resolve_project_file(dir)? { + match resolve_project_files(dir)? { None => Ok((Config::default(), None)), - Some(path) => Config::from_toml_path(&path).map(|config| (config, Some(path))), + Some(paths) => { + let mut config = Config::default(); + let mut used_paths = Vec::with_capacity(paths.len()); + for path in paths.into_iter().rev() { + let partial_config = PartialConfig::from_toml_path(&path)?; + config = config.fill_from_parsed_config(partial_config, &path); + used_paths.push(path); + } + + Ok((config, Some(used_paths))) + } } } pub fn from_toml(toml: &str, dir: &Path) -> Result { - let parsed: ::toml::Value = toml - .parse() - .map_err(|e| format!("Could not parse TOML: {}", e))?; - let mut err = String::new(); - let table = parsed - .as_table() - .ok_or_else(|| String::from("Parsed config was not table"))?; - for key in table.keys() { - if !Config::is_valid_name(key) { - let msg = &format!("Warning: Unknown configuration option `{}`\n", key); - err.push_str(msg) - } - } - match parsed.try_into() { - Ok(parsed_config) => { - if !err.is_empty() { - eprint!("{}", err); - } - let config = Config::default().fill_from_parsed_config(parsed_config, dir); - Ok(config) - } - Err(e) => { - err.push_str("Error: Decoding config file failed:\n"); - err.push_str(format!("{}\n", e).as_str()); - err.push_str("Please check your config file."); - Err(err) - } - } + let partial_config = PartialConfig::from_toml(toml)?; + let config = Config::default().fill_from_parsed_config(partial_config, dir); + Ok(config) } } @@ -300,14 +326,14 @@ impl Config { pub fn load_config( file_path: Option<&Path>, options: Option<&O>, -) -> Result<(Config, Option), Error> { +) -> Result<(Config, Option>), Error> { let over_ride = match options { Some(opts) => config_path(opts)?, None => None, }; let result = if let Some(over_ride) = over_ride { - Config::from_toml_path(over_ride.as_ref()).map(|p| (p, Some(over_ride.to_owned()))) + Config::from_toml_path(over_ride.as_ref()).map(|p| (p, Some(vec![over_ride.to_owned()]))) } else if let Some(file_path) = file_path { Config::from_resolved_toml_path(file_path) } else { @@ -417,6 +443,42 @@ mod test { } } + struct TempFile { + path: PathBuf, + } + + fn make_temp_file(file_name: &'static str, content: &'static str) -> TempFile { + use std::env::var; + + // Used in the Rust build system. + let target_dir = var("RUSTFMT_TEST_DIR").map_or_else(|_| env::temp_dir(), PathBuf::from); + let path = target_dir.join(file_name); + + fs::create_dir_all(path.parent().unwrap()).expect("couldn't create temp file"); + let mut file = File::create(&path).expect("couldn't create temp file"); + file.write_all(content.as_bytes()) + .expect("couldn't write temp file"); + TempFile { path } + } + + impl Drop for TempFile { + fn drop(&mut self) { + use std::fs::remove_file; + remove_file(&self.path).expect("couldn't delete temp file"); + } + } + + struct NullOptions; + + impl CliOptions for NullOptions { + fn apply_to(&self, _: &mut Config) { + unreachable!(); + } + fn config_path(&self) -> Option<&Path> { + unreachable!(); + } + } + #[test] fn test_config_set() { let mut config = Config::default(); @@ -568,6 +630,44 @@ ignore = [] assert_eq!(&toml, &default_config); } + #[test] + fn test_merged_config() { + match option_env!("CFG_RELEASE_CHANNEL") { + // this test requires nightly + None | Some("nightly") => { + let _outer_config = make_temp_file( + "a/rustfmt.toml", + r#" +tab_spaces = 2 +fn_call_width = 50 +ignore = ["b/main.rs", "util.rs"] +"#, + ); + + let inner_config = make_temp_file( + "a/b/rustfmt.toml", + r#" +version = "two" +tab_spaces = 3 +ignore = [] +"#, + ); + + let inner_dir = inner_config.path.parent().unwrap(); + let (config, paths) = load_config::(Some(inner_dir), None).unwrap(); + + assert_eq!(config.tab_spaces(), 3); + assert_eq!(config.fn_call_width(), 50); + assert_eq!(config.ignore().to_string(), r#"["main.rs"]"#); + + let paths = paths.unwrap(); + assert!(paths[0].ends_with("a/rustfmt.toml")); + assert!(paths[1].ends_with("a/b/rustfmt.toml")); + } + _ => (), + }; + } + mod unstable_features { use super::super::*; diff --git a/rustfmt-core/rustfmt-lib/src/config/config_type.rs b/rustfmt-core/rustfmt-lib/src/config/config_type.rs index 5abb8ccc93f..6a4c3191d5d 100644 --- a/rustfmt-core/rustfmt-lib/src/config/config_type.rs +++ b/rustfmt-core/rustfmt-lib/src/config/config_type.rs @@ -50,6 +50,22 @@ impl ConfigType for IgnoreList { } } +macro_rules! update_config { + ($config:ident, ignore = $val:ident, $dir:ident) => { + $config.ignore.1 = true; + + let mut new_ignored = $val; + new_ignored.add_prefix($dir); + let old_ignored = $config.ignore.2; + $config.ignore.2 = old_ignored.merge_into(new_ignored); + }; + + ($config:ident, $i:ident = $val:ident, $dir:ident) => { + $config.$i.1 = true; + $config.$i.2 = $val; + }; +} + macro_rules! create_config { ($($i:ident: $Ty:ty, $def:expr, $is_stable:literal, $dstring:literal;)+) => ( use std::io::Write; @@ -149,12 +165,10 @@ macro_rules! create_config { $( if let Some(val) = parsed.$i { if self.$i.3 { - self.$i.1 = true; - self.$i.2 = val; + update_config!(self, $i = val, dir); } else { if is_nightly_channel!() { - self.$i.1 = true; - self.$i.2 = val; + update_config!(self, $i = val, dir); } else { eprintln!("Warning: can't set `{} = {:?}`, unstable features are only \ available in nightly channel.", stringify!($i), val); @@ -164,7 +178,6 @@ macro_rules! create_config { )+ self.set_heuristics(); self.set_license_template(); - self.set_ignore(dir); self } @@ -397,10 +410,6 @@ macro_rules! create_config { } } - fn set_ignore(&mut self, dir: &Path) { - self.ignore.2.add_prefix(dir); - } - #[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 { diff --git a/rustfmt-core/rustfmt-lib/src/config/options.rs b/rustfmt-core/rustfmt-lib/src/config/options.rs index 23b4ba83e7a..8a0f548a708 100644 --- a/rustfmt-core/rustfmt-lib/src/config/options.rs +++ b/rustfmt-core/rustfmt-lib/src/config/options.rs @@ -276,6 +276,33 @@ impl IgnoreList { pub fn rustfmt_toml_path(&self) -> &Path { &self.rustfmt_toml_path } + + /// Merges `self` into `other`, returning a new `IgnoreList`. The resulting `IgnoreList` uses + /// the `rustfmt_toml_path` of `other`, and only contains paths that are in `other`'s + /// `rustfmt_toml_path`. + pub fn merge_into(self, other: Self) -> Self { + let old_rustfmt_toml_path = self.rustfmt_toml_path; + let new_rustfmt_toml_path = other.rustfmt_toml_path; + let relocalized_old_paths: HashSet = self + .path_set + .into_iter() + .map(|p| old_rustfmt_toml_path.parent().unwrap().join(p)) + .map(|p| { + // Only keep old paths that are also in the new config path + p.strip_prefix(new_rustfmt_toml_path.parent().unwrap()) + .map(PathBuf::from) + }) + .flatten() + .collect(); + + let mut path_set = other.path_set; + path_set.extend(relocalized_old_paths); + + Self { + path_set, + rustfmt_toml_path: new_rustfmt_toml_path, + } + } } impl std::str::FromStr for IgnoreList { @@ -331,3 +358,43 @@ pub enum MatchArmLeadingPipe { /// Maintain any existing leading pipes KeepExisting, } + +#[cfg(test)] +mod test { + use std::path::PathBuf; + + use crate::config::IgnoreList; + + #[test] + fn test_ignore_list_merge_into() { + let ignore_list_outer = IgnoreList { + path_set: vec!["b/c/d.rs", "b/c/d/e.rs", "b/other.rs"] + .into_iter() + .map(PathBuf::from) + .collect(), + rustfmt_toml_path: PathBuf::from("a/rustfmt.toml"), + }; + + let ignore_list_inner = IgnoreList { + path_set: vec!["f.rs", "g/h.rs"] + .into_iter() + .map(PathBuf::from) + .collect(), + rustfmt_toml_path: PathBuf::from("a/b/c/rustfmt.toml"), + }; + + let ignore_list_merged = ignore_list_outer.merge_into(ignore_list_inner); + + assert_eq!( + ignore_list_merged.rustfmt_toml_path, + PathBuf::from("a/b/c/rustfmt.toml") + ); + assert_eq!( + ignore_list_merged.path_set, + vec!["d.rs", "d/e.rs", "f.rs", "g/h.rs"] + .into_iter() + .map(PathBuf::from) + .collect() + ); + } +} From cbf44c8760df3c9b7dd1fdc74195bf75d89d0b98 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 24 May 2020 12:29:02 +0900 Subject: [PATCH 52/59] Stabilize ignore config option (#4139) --- Configurations.md | 2 +- rustfmt-core/rustfmt-lib/src/config.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Configurations.md b/Configurations.md index 869d152967b..c1234fba03e 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1051,7 +1051,7 @@ The pattern format is the same as [.gitignore](https://git-scm.com/docs/gitignor - **Default value**: format every file - **Possible values**: See an example below -- **Stable**: No (tracking issue: [#3395](https://github.com/rust-lang/rustfmt/issues/3395)) +- **Stable**: Yes ### Example diff --git a/rustfmt-core/rustfmt-lib/src/config.rs b/rustfmt-core/rustfmt-lib/src/config.rs index 1f0a48d05f2..a77c0ac8eec 100644 --- a/rustfmt-core/rustfmt-lib/src/config.rs +++ b/rustfmt-core/rustfmt-lib/src/config.rs @@ -149,7 +149,7 @@ create_config! { error_on_unformatted: bool, false, false, "Error if unable to get comments or string literals within max_width, \ or they are left with trailing whitespaces"; - ignore: IgnoreList, IgnoreList::default(), false, + ignore: IgnoreList, IgnoreList::default(), true, "Skip formatting the specified files and directories"; // Not user-facing From 4861ef4e522e5e50520d3b61848376738ef25a34 Mon Sep 17 00:00:00 2001 From: Juan Aguilar Date: Sun, 24 May 2020 15:52:00 -0700 Subject: [PATCH 53/59] Upload annotate-snippets to 0.8 (#4161) --- Cargo.lock | 21 +++- rustfmt-core/rustfmt-lib/Cargo.toml | 2 +- .../src/format_report_formatter.rs | 112 ++++++++---------- 3 files changed, 67 insertions(+), 68 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4740588c3d2..5177fae1fc4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,8 +14,14 @@ name = "annotate-snippets" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7021ce4924a3f25f802b2cccd1af585e39ea1a363a1aa2e72afe54b67a3a7a7" + +[[package]] +name = "annotate-snippets" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d78ea013094e5ea606b1c05fe35f1dd7ea1eb1ea259908d040b25bd5ec677ee5" dependencies = [ - "ansi_term", + "yansi-term", ] [[package]] @@ -830,7 +836,7 @@ version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c374e89b3c9714869ef86076942155383804ba6778c26be2169d324563c31f9" dependencies = [ - "annotate-snippets", + "annotate-snippets 0.6.1", "atty", "log", "rustc-ap-rustc_data_structures", @@ -1073,7 +1079,7 @@ dependencies = [ name = "rustfmt_lib" version = "2.0.0-rc.1" dependencies = [ - "annotate-snippets", + "annotate-snippets 0.8.0", "anyhow", "bytecount", "diff", @@ -1462,3 +1468,12 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "yansi-term" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a30d0d48515e745863faad2da9c1e1bac640f9f0f83f1eecb79fc0bf4018e5d2" +dependencies = [ + "winapi", +] diff --git a/rustfmt-core/rustfmt-lib/Cargo.toml b/rustfmt-core/rustfmt-lib/Cargo.toml index ecf4bfe6f8e..646c4c1c0d1 100644 --- a/rustfmt-core/rustfmt-lib/Cargo.toml +++ b/rustfmt-core/rustfmt-lib/Cargo.toml @@ -29,7 +29,7 @@ emitter = [ ] [dependencies] -annotate-snippets = { version = "0.6", features = ["ansi_term"] } +annotate-snippets = { version = "0.8", features = ["color"] } anyhow = "1.0" bytecount = "0.6" dunce = "1.0" diff --git a/rustfmt-core/rustfmt-lib/src/format_report_formatter.rs b/rustfmt-core/rustfmt-lib/src/format_report_formatter.rs index b1b0d4a0ac5..ee885d3f0fe 100644 --- a/rustfmt-core/rustfmt-lib/src/format_report_formatter.rs +++ b/rustfmt-core/rustfmt-lib/src/format_report_formatter.rs @@ -1,10 +1,8 @@ -use crate::config::FileName; use crate::{ formatting::report::FormatReport, result::{ErrorKind, FormatError}, }; -use annotate_snippets::display_list::DisplayList; -use annotate_snippets::formatter::DisplayListFormatter; +use annotate_snippets::display_list::{DisplayList, FormatOptions}; use annotate_snippets::snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation}; use std::fmt::{self, Display}; @@ -50,85 +48,71 @@ pub struct FormatReportFormatter<'a> { impl<'a> Display for FormatReportFormatter<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let formatter = DisplayListFormatter::new(self.enable_colors, false); - + let opt = FormatOptions { + color: self.enable_colors, + ..Default::default() + }; for (file, errors) in self.report.format_result_as_rc().borrow().iter() { for error in errors.errors_excluding_macro() { - let snippet = formatting_error_to_snippet(file, error); - writeln!(f, "{}\n", formatter.format(&DisplayList::from(snippet)))?; + let annotation_type = error_kind_to_snippet_annotation_type(&error.kind()); + let label = error.kind().to_string(); + let title = Annotation { + id: None, + label: Some(&label), + annotation_type, + }; + let origin = error + .line_num() + .as_ref() + .map(|line_num| format!("{}:{}", file, line_num)); + let slice = Slice { + source: error.line_str().unwrap_or(""), + line_start: error.line_num().unwrap_or(0), + origin: origin.as_ref().map(|s| s.as_str()), + fold: false, + annotations: slice_annotation(error).into_iter().collect(), + }; + + let snippet = Snippet { + title: Some(title), + slices: vec![slice], + footer: vec![], + opt, + }; + writeln!(f, "{}\n", DisplayList::from(snippet))?; } } if self.report.has_errors() { - let snippet = formatting_failure_snippet(self.report.warning_count()); - writeln!(f, "{}", formatter.format(&DisplayList::from(snippet)))?; + let label = format!( + "rustfmt has failed to format. See previous {} errors.", + self.report.warning_count() + ); + let snippet = Snippet { + title: Some(Annotation { + id: None, + label: Some(&label), + annotation_type: AnnotationType::Warning, + }), + slices: Vec::new(), + footer: vec![], + opt, + }; + writeln!(f, "{}", DisplayList::from(snippet))?; } Ok(()) } } -fn formatting_failure_snippet(warning_count: usize) -> Snippet { - Snippet { - title: Some(Annotation { - id: None, - label: Some(format!( - "rustfmt has failed to format. See previous {} errors.", - warning_count - )), - annotation_type: AnnotationType::Warning, - }), - slices: Vec::new(), - footer: vec![], - } -} - -fn formatting_error_to_snippet(file: &FileName, error: &FormatError) -> Snippet { - let slices = vec![snippet_code_slice(file, error)]; - let title = Some(snippet_title(error)); - - Snippet { - title, - slices, - footer: vec![], - } -} - -fn snippet_title(error: &FormatError) -> Annotation { - let annotation_type = error_kind_to_snippet_annotation_type(&error.kind()); - - Annotation { - id: None, - label: Some(error.kind().to_string()), - annotation_type, - } -} - -fn snippet_code_slice(file: &FileName, error: &FormatError) -> Slice { - let annotations = slice_annotation(error).into_iter().collect(); - let origin = error - .line_num() - .as_ref() - .map(|line_num| format!("{}:{}", file, line_num)); - let source = error.line_str().unwrap_or("").to_owned(); - - Slice { - source, - line_start: error.line_num().unwrap_or(0), - origin, - fold: false, - annotations, - } -} - -fn slice_annotation(error: &FormatError) -> Option { +fn slice_annotation(error: &FormatError) -> Option> { match error.format_len() { Some((range_start, range_length)) if range_length > 0 => { let range_end = range_start + range_length; Some(SourceAnnotation { annotation_type: AnnotationType::Error, range: (range_start, range_end), - label: String::new(), + label: "", }) } _ => None, From 35121eaa57e6c8475c93d8e77f13006f131bfab1 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 25 May 2020 08:34:08 +0900 Subject: [PATCH 54/59] Improve error message when module resolution failed (#4198) --- rustfmt-core/rustfmt-bin/src/bin/main.rs | 8 +- rustfmt-core/rustfmt-lib/src/formatting.rs | 4 +- .../rustfmt-lib/src/formatting/modules.rs | 87 ++++++++++++------- .../src/formatting/syntux/parser.rs | 8 +- rustfmt-core/rustfmt-lib/src/result.rs | 7 +- 5 files changed, 69 insertions(+), 45 deletions(-) diff --git a/rustfmt-core/rustfmt-bin/src/bin/main.rs b/rustfmt-core/rustfmt-bin/src/bin/main.rs index 9839dfa7ad3..80df2c325dc 100644 --- a/rustfmt-core/rustfmt-bin/src/bin/main.rs +++ b/rustfmt-core/rustfmt-bin/src/bin/main.rs @@ -323,16 +323,10 @@ pub enum OperationError { #[error("The `--print-config=minimal` option doesn't work with standard input.")] MinimalPathWithStdin, /// An io error during reading or writing. - #[error("io error: {0}")] + #[error("{0}")] IoError(IoError), } -impl From for OperationError { - fn from(e: IoError) -> OperationError { - OperationError::IoError(e) - } -} - impl CliOptions for Opt { fn apply_to(&self, config: &mut Config) { config.set().file_lines(self.file_lines.clone()); diff --git a/rustfmt-core/rustfmt-lib/src/formatting.rs b/rustfmt-core/rustfmt-lib/src/formatting.rs index 19a14dbcb7b..22842c8aef9 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting.rs @@ -1,6 +1,5 @@ // High level formatting functions. -use std::io; use std::time::{Duration, Instant}; use rustc_ast::ast; @@ -117,8 +116,7 @@ fn format_project( directory_ownership.unwrap_or(DirectoryOwnership::UnownedViaMod), !input_is_stdin && operation_setting.recursive, ) - .visit_crate(&krate) - .map_err(|e| OperationError::IoError(io::Error::new(io::ErrorKind::Other, e)))?; + .visit_crate(&krate)?; for (path, module) in files { let should_ignore = !input_is_stdin && parse_session.ignore_file(&path); diff --git a/rustfmt-core/rustfmt-lib/src/formatting/modules.rs b/rustfmt-core/rustfmt-lib/src/formatting/modules.rs index eee19502906..f5c50529185 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/modules.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/modules.rs @@ -5,12 +5,13 @@ use std::path::{Path, PathBuf}; use rustc_ast::ast; use rustc_ast::visit::Visitor; use rustc_span::symbol::{self, sym, Symbol}; +use thiserror::Error; use crate::config::FileName; use crate::formatting::{ attr::MetaVisitor, items::is_mod_decl, - syntux::parser::{Directory, DirectoryOwnership, ModulePathSuccess, Parser}, + syntux::parser::{Directory, DirectoryOwnership, ModulePathSuccess, Parser, ParserError}, syntux::session::ParseSess, utils::contains_skip, }; @@ -31,6 +32,24 @@ pub(crate) struct ModResolver<'ast, 'sess> { recursive: bool, } +/// Represents errors while trying to resolve modules. +#[error("failed to resolve mod `{module}`: {kind}")] +#[derive(Debug, Error)] +pub struct ModuleResolutionError { + module: String, + kind: ModuleResolutionErrorKind, +} + +#[derive(Debug, Error)] +pub(crate) enum ModuleResolutionErrorKind { + /// Find a file that cannot be parsed. + #[error("cannot parse {file}")] + ParseError { file: PathBuf }, + /// File cannot be found. + #[error("{file} does not exist")] + NotFound { file: PathBuf }, +} + #[derive(Clone)] enum SubModKind<'a, 'ast> { /// `mod foo;` @@ -63,7 +82,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { pub(crate) fn visit_crate( mut self, krate: &'ast ast::Crate, - ) -> Result, String> { + ) -> Result, ModuleResolutionError> { let root_filename = self.parse_sess.span_to_filename(krate.span); self.directory.path = match root_filename { FileName::Real(ref p) => p.parent().unwrap_or_else(|| Path::new("")).to_path_buf(), @@ -81,7 +100,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } /// Visit `cfg_if` macro and look for module declarations. - fn visit_cfg_if(&mut self, item: Cow<'ast, ast::Item>) -> Result<(), String> { + fn visit_cfg_if(&mut self, item: Cow<'ast, ast::Item>) -> Result<(), ModuleResolutionError> { let mut visitor = visitor::CfgIfVisitor::new(self.parse_sess); visitor.visit_item(&item); for module_item in visitor.mods() { @@ -93,7 +112,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } /// Visit modules defined inside macro calls. - fn visit_mod_outside_ast(&mut self, module: ast::Mod) -> Result<(), String> { + fn visit_mod_outside_ast(&mut self, module: ast::Mod) -> Result<(), ModuleResolutionError> { for item in module.items { if is_cfg_if(&item) { self.visit_cfg_if(Cow::Owned(item.into_inner()))?; @@ -108,7 +127,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } /// Visit modules from AST. - fn visit_mod_from_ast(&mut self, module: &'ast ast::Mod) -> Result<(), String> { + fn visit_mod_from_ast(&mut self, module: &'ast ast::Mod) -> Result<(), ModuleResolutionError> { for item in &module.items { if is_cfg_if(item) { self.visit_cfg_if(Cow::Borrowed(item))?; @@ -125,7 +144,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { &mut self, item: &'c ast::Item, sub_mod: Cow<'ast, ast::Mod>, - ) -> Result<(), String> { + ) -> Result<(), ModuleResolutionError> { let old_directory = self.directory.clone(); let sub_mod_kind = self.peek_sub_mod(item, &sub_mod)?; if let Some(sub_mod_kind) = sub_mod_kind { @@ -141,7 +160,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { &self, item: &'c ast::Item, sub_mod: &Cow<'ast, ast::Mod>, - ) -> Result>, String> { + ) -> Result>, ModuleResolutionError> { if contains_skip(&item.attrs) { return Ok(None); } @@ -160,7 +179,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { &mut self, sub_mod_kind: SubModKind<'c, 'ast>, _sub_mod: Cow<'ast, ast::Mod>, - ) -> Result<(), String> { + ) -> Result<(), ModuleResolutionError> { match sub_mod_kind { SubModKind::External(mod_path, _, sub_mod) => { self.file_map @@ -183,7 +202,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { &mut self, sub_mod: Cow<'ast, ast::Mod>, sub_mod_kind: SubModKind<'c, 'ast>, - ) -> Result<(), String> { + ) -> Result<(), ModuleResolutionError> { match sub_mod_kind { SubModKind::External(mod_path, directory_ownership, sub_mod) => { let directory = Directory { @@ -213,7 +232,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { &mut self, sub_mod: Cow<'ast, ast::Mod>, directory: Option, - ) -> Result<(), String> { + ) -> Result<(), ModuleResolutionError> { if let Some(directory) = directory { self.directory = directory; } @@ -229,7 +248,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { mod_name: symbol::Ident, attrs: &[ast::Attribute], sub_mod: &Cow<'ast, ast::Mod>, - ) -> Result>, String> { + ) -> Result>, ModuleResolutionError> { let relative = match self.directory.ownership { DirectoryOwnership::Owned { relative } => relative, DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod => None, @@ -239,15 +258,19 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { return Ok(None); } return match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.inner) { - Some(m) => Ok(Some(SubModKind::External( + Ok(m) => Ok(Some(SubModKind::External( path, DirectoryOwnership::Owned { relative: None }, Cow::Owned(m), ))), - None => Err(format!( - "Failed to find module {} in {:?} {:?}", - mod_name, self.directory.path, relative, - )), + Err(ParserError::ParseError) => Err(ModuleResolutionError { + module: mod_name.to_string(), + kind: ModuleResolutionErrorKind::ParseError { file: path }, + }), + Err(..) => Err(ModuleResolutionError { + module: mod_name.to_string(), + kind: ModuleResolutionErrorKind::NotFound { file: path }, + }), }; } @@ -277,21 +300,25 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } } match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.inner) { - Some(m) if outside_mods_empty => { + Ok(m) if outside_mods_empty => { Ok(Some(SubModKind::External(path, ownership, Cow::Owned(m)))) } - Some(m) => { + Ok(m) => { mods_outside_ast.push((path.clone(), ownership, Cow::Owned(m))); if should_insert { mods_outside_ast.push((path, ownership, sub_mod.clone())); } Ok(Some(SubModKind::MultiExternal(mods_outside_ast))) } - None if outside_mods_empty => Err(format!( - "Failed to find module {} in {:?} {:?}", - mod_name, self.directory.path, relative, - )), - None => { + Err(ParserError::ParseError) => Err(ModuleResolutionError { + module: mod_name.to_string(), + kind: ModuleResolutionErrorKind::ParseError { file: path }, + }), + Err(..) if outside_mods_empty => Err(ModuleResolutionError { + module: mod_name.to_string(), + kind: ModuleResolutionErrorKind::NotFound { file: path }, + }), + Err(..) => { if should_insert { mods_outside_ast.push((path, ownership, sub_mod.clone())); } @@ -305,10 +332,12 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } Err(mut e) => { e.cancel(); - Err(format!( - "Failed to find module {} in {:?} {:?}", - mod_name, self.directory.path, relative, - )) + Err(ModuleResolutionError { + module: mod_name.to_string(), + kind: ModuleResolutionErrorKind::NotFound { + file: self.directory.path.clone(), + }, + }) } } } @@ -367,8 +396,8 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { let m = match Parser::parse_file_as_module(self.parse_sess, &actual_path, sub_mod.inner) { - Some(m) => m, - None => continue, + Ok(m) => m, + Err(..) => continue, }; result.push(( diff --git a/rustfmt-core/rustfmt-lib/src/formatting/syntux/parser.rs b/rustfmt-core/rustfmt-lib/src/formatting/syntux/parser.rs index 8b82e97f8fa..69bac50b5bd 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/syntux/parser.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/syntux/parser.rs @@ -167,7 +167,7 @@ impl<'a> Parser<'a> { sess: &'a ParseSess, path: &Path, span: Span, - ) -> Option { + ) -> Result { let result = catch_unwind(AssertUnwindSafe(|| { let mut parser = new_parser_from_file(sess.inner(), &path, Some(span)); @@ -192,8 +192,10 @@ impl<'a> Parser<'a> { } })); match result { - Ok(Some(m)) => Some(m), - _ => None, + Ok(Some(m)) => Ok(m), + Ok(None) => Err(ParserError::ParseError), + Err(..) if path.exists() => Err(ParserError::ParseError), + Err(_) => Err(ParserError::ParsePanicError), } } diff --git a/rustfmt-core/rustfmt-lib/src/result.rs b/rustfmt-core/rustfmt-lib/src/result.rs index f212811fc88..9d51c379684 100644 --- a/rustfmt-core/rustfmt-lib/src/result.rs +++ b/rustfmt-core/rustfmt-lib/src/result.rs @@ -3,6 +3,7 @@ use rustc_span::Span; use thiserror::Error; +use crate::formatting::modules::ModuleResolutionError; use crate::{formatting::ParseSess, FileName}; /// Represents the specific error kind of [`FormatError`]. @@ -110,9 +111,9 @@ pub enum OperationError { /// satisfy that requirement. #[error("version mismatch")] VersionMismatch, - /// An io error during reading or writing. - #[error("io error: {0}")] - IoError(std::io::Error), + /// Error during module resolution. + #[error("{0}")] + ModuleResolutionError(#[from] ModuleResolutionError), /// Invalid glob pattern in `ignore` configuration option. #[error("invalid glob pattern found in ignore list: {0}")] InvalidGlobPattern(ignore::Error), From 5936675aaeeeb3af8f2c7dd0e275970e03fa629f Mon Sep 17 00:00:00 2001 From: Sagie Gur-Ari Date: Mon, 25 May 2020 19:50:36 +0900 Subject: [PATCH 55/59] Fix CFG_RELEASE value (#4202) --- .cargo/Makefile.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.cargo/Makefile.toml b/.cargo/Makefile.toml index 3f771a9dfd3..85de1f4d494 100644 --- a/.cargo/Makefile.toml +++ b/.cargo/Makefile.toml @@ -1,8 +1,8 @@ # This Makefile.toml defines common tasks and settings used in the rustfmt project. [env] -CFG_RELEASE = { value = "nightly", condition = { env_not_set = ["CFG_RELEASE"] } } -CFG_RELEASE_CHANNEL = { value = "nightly", condition = { env_not_set = ["CFG_RELEASE_CHANNEL"] } } +CFG_RELEASE = { value = "${CARGO_MAKE_RUST_VERSION}", condition = { env_not_set = ["CFG_RELEASE"] } } +CFG_RELEASE_CHANNEL = { value = "${CARGO_MAKE_RUST_CHANNEL}", condition = { env_not_set = ["CFG_RELEASE_CHANNEL"] } } [tasks.b] alias = "build" From 0a45e91a3bfd508d0de35208ab4023eaaa13e120 Mon Sep 17 00:00:00 2001 From: wangtheo Date: Mon, 25 May 2020 06:53:24 -0400 Subject: [PATCH 56/59] #4099: trailing_comma + struct_field_align_threshold -> removing a struct's commas (#4201) --- .../rustfmt-lib/src/formatting/vertical.rs | 10 +++++-- .../rustfmt-lib/tests/source/issue-4099.rs | 30 +++++++++++++++++++ .../rustfmt-lib/tests/target/issue-4099.rs | 30 +++++++++++++++++++ 3 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 rustfmt-core/rustfmt-lib/tests/source/issue-4099.rs create mode 100644 rustfmt-core/rustfmt-lib/tests/target/issue-4099.rs diff --git a/rustfmt-core/rustfmt-lib/src/formatting/vertical.rs b/rustfmt-core/rustfmt-lib/src/formatting/vertical.rs index cb54125228e..ad74f34f36c 100644 --- a/rustfmt-core/rustfmt-lib/src/formatting/vertical.rs +++ b/rustfmt-core/rustfmt-lib/src/formatting/vertical.rs @@ -161,7 +161,7 @@ pub(crate) fn rewrite_with_alignment( let init_span = mk_sp(span.lo(), init_last_pos); let one_line_width = if rest.is_empty() { one_line_width } else { 0 }; let result = - rewrite_aligned_items_inner(context, init, init_span, shape.indent, one_line_width)?; + rewrite_aligned_items_inner(context, init, rest, init_span, shape.indent, one_line_width)?; if rest.is_empty() { Some(result + spaces) } else { @@ -198,6 +198,7 @@ fn struct_field_prefix_max_min_width( fn rewrite_aligned_items_inner( context: &RewriteContext<'_>, fields: &[T], + remaining_fields: &[T], span: Span, offset: Indent, one_line_width: usize, @@ -248,7 +249,12 @@ fn rewrite_aligned_items_inner( let fmt = ListFormatting::new(item_shape, context.config) .tactic(tactic) - .trailing_separator(context.config.trailing_comma()) + .trailing_separator(if remaining_fields.is_empty() { + // trailing commas should only be removed on the last field + context.config.trailing_comma() + } else { + SeparatorTactic::Always + }) .preserve_newline(true); write_list(&items, &fmt) } diff --git a/rustfmt-core/rustfmt-lib/tests/source/issue-4099.rs b/rustfmt-core/rustfmt-lib/tests/source/issue-4099.rs new file mode 100644 index 00000000000..c218b18dceb --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/source/issue-4099.rs @@ -0,0 +1,30 @@ +// rustfmt-struct_field_align_threshold: 127 +// rustfmt-trailing_comma: Never + +struct S { + aaa: f32, + + bbb: f32, + + ccc: f32, +} + +struct S2 { + aaa: f32, + bbb: f32, + ccc: f32, +} + +struct S3 { + aaa: f32, + bbb: f32, + + ccc: f32, +} + +struct S4 { + aaa: f32, + + bbb: f32, + ccc: f32, +} diff --git a/rustfmt-core/rustfmt-lib/tests/target/issue-4099.rs b/rustfmt-core/rustfmt-lib/tests/target/issue-4099.rs new file mode 100644 index 00000000000..66d5d97ced4 --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/target/issue-4099.rs @@ -0,0 +1,30 @@ +// rustfmt-struct_field_align_threshold: 127 +// rustfmt-trailing_comma: Never + +struct S { + aaa: f32, + + bbb: f32, + + ccc: f32 +} + +struct S2 { + aaa: f32, + bbb: f32, + ccc: f32 +} + +struct S3 { + aaa: f32, + bbb: f32, + + ccc: f32 +} + +struct S4 { + aaa: f32, + + bbb: f32, + ccc: f32 +} From b272c77a7ba2de07c811652c12aae40786c36a33 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 25 May 2020 21:16:28 +0900 Subject: [PATCH 57/59] Fix makefile (#4203) --- .cargo/Makefile.toml | 13 +++++++++++++ Makefile.toml | 10 ---------- .../rustfmt-lib/config_proc_macro/Cargo.toml | 3 +-- .../rustfmt-lib/config_proc_macro/src/lib.rs | 3 +-- .../rustfmt-lib/config_proc_macro/src/utils.rs | 3 +-- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.cargo/Makefile.toml b/.cargo/Makefile.toml index 85de1f4d494..9d79bddad79 100644 --- a/.cargo/Makefile.toml +++ b/.cargo/Makefile.toml @@ -4,9 +4,22 @@ CFG_RELEASE = { value = "${CARGO_MAKE_RUST_VERSION}", condition = { env_not_set = ["CFG_RELEASE"] } } CFG_RELEASE_CHANNEL = { value = "${CARGO_MAKE_RUST_CHANNEL}", condition = { env_not_set = ["CFG_RELEASE_CHANNEL"] } } +[tasks.build-bin] +workspace = false +command = "cargo" +args = [ + "build", + "--bin", + "rustfmt", + "--all-features", +] + [tasks.b] alias = "build" +[tasks.bb] +alias = "build-bin" + [tasks.c] alias = "check" diff --git a/Makefile.toml b/Makefile.toml index e26685aba54..57c5f3f4969 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -1,15 +1,5 @@ extend = ".cargo/Makefile.toml" -[tasks.build] -clear = true -command = "cargo" -args = [ - "build", - "--manifest-path", - "rustfmt-core/Cargo.toml", - "--workspace", -] - [tasks.install] command = "cargo" args = [ diff --git a/rustfmt-core/rustfmt-lib/config_proc_macro/Cargo.toml b/rustfmt-core/rustfmt-lib/config_proc_macro/Cargo.toml index eb045a452ad..c8d5497f911 100644 --- a/rustfmt-core/rustfmt-lib/config_proc_macro/Cargo.toml +++ b/rustfmt-core/rustfmt-lib/config_proc_macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustfmt-config_proc_macro" -version = "0.5.0" +version = "0.5.1" authors = ["topecongiro "] edition = "2018" description = "A collection of procedural macros for rustfmt" @@ -21,4 +21,3 @@ serde = { version = "1.0", features = ["derive"] } [features] default = [] -debug-with-rustfmt = [] diff --git a/rustfmt-core/rustfmt-lib/config_proc_macro/src/lib.rs b/rustfmt-core/rustfmt-lib/config_proc_macro/src/lib.rs index 66cfd3c727d..caece7e8595 100644 --- a/rustfmt-core/rustfmt-lib/config_proc_macro/src/lib.rs +++ b/rustfmt-core/rustfmt-lib/config_proc_macro/src/lib.rs @@ -18,8 +18,7 @@ pub fn config_type(_args: TokenStream, input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as syn::Item); let output = config_type::define_config_type(&input); - #[cfg(feature = "debug-with-rustfmt")] - { + if std::env::var("RUSTFMT_DEV_DEBUG_PROC_MACRO").is_ok() { utils::debug_with_rustfmt(&output); } diff --git a/rustfmt-core/rustfmt-lib/config_proc_macro/src/utils.rs b/rustfmt-core/rustfmt-lib/config_proc_macro/src/utils.rs index fec6a8e4907..739a2e29efd 100644 --- a/rustfmt-core/rustfmt-lib/config_proc_macro/src/utils.rs +++ b/rustfmt-core/rustfmt-lib/config_proc_macro/src/utils.rs @@ -19,9 +19,8 @@ pub fn is_unit(v: &syn::Variant) -> bool { } } -#[cfg(feature = "debug-with-rustfmt")] /// Pretty-print the output of proc macro using rustfmt. -pub fn debug_with_rustfmt(input: &TokenStream) { +pub(crate) fn debug_with_rustfmt(input: &TokenStream) { use std::io::Write; use std::process::{Command, Stdio}; From 256c02476624c116e0bf8b2ede0d3f47018e9b87 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 25 May 2020 21:17:47 +0900 Subject: [PATCH 58/59] Cargo update --- Cargo.lock | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5177fae1fc4..7cb1a881726 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -156,9 +156,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.53" +version = "1.0.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "404b1fe4f65288577753b17e3b36a04596ee784493ec249bf81c7f2d2acd751c" +checksum = "7bbb73db36c1246e9034e307d0fba23f9a2e251faa47ade70c1bd252220c8311" [[package]] name = "cfg-if" @@ -388,9 +388,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61565ff7aaace3525556587bd2dc31d4a07071957be715e63ce7b1eccf51a8f4" +checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71" dependencies = [ "libc", ] @@ -642,9 +642,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.12" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8872cf6f48eee44265156c111456a700ab3483686b3f96df4cf5481c89157319" +checksum = "1502d12e458c49a4c9cbff560d0fe0060c252bc29799ed94ca2ed4bb665a0101" dependencies = [ "unicode-xid", ] @@ -666,9 +666,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42934bc9c8ab0d3b273a16d8551c8f0fcff46be73276ca083ec2414c15c4ba5e" +checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea" dependencies = [ "proc-macro2", ] @@ -1048,7 +1048,7 @@ dependencies = [ [[package]] name = "rustfmt-config_proc_macro" -version = "0.5.0" +version = "0.5.1" dependencies = [ "proc-macro2", "quote", @@ -1262,9 +1262,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.21" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4696caa4048ac7ce2bcd2e484b3cef88c1004e41b8e945a277e2c25dc0b72060" +checksum = "f87bc5b2815ebb664de0392fdf1b95b6d10e160f86d9f64ff65e5679841ca06a" dependencies = [ "proc-macro2", "quote", @@ -1334,18 +1334,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.17" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "467e5ff447618a916519a4e0d62772ab14f434897f3d63f05d8700ef1e9b22c1" +checksum = "b13f926965ad00595dd129fa12823b04bbf866e9085ab0a5f2b05b850fbfc344" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.17" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e63c1091225b9834089b429bc4a2e01223470e3183e891582909e9d1c4cb55d9" +checksum = "893582086c2f98cde18f906265a65b5030a074b1046c674ae898be6519a7f479" dependencies = [ "proc-macro2", "quote", @@ -1417,9 +1417,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" +checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" [[package]] name = "walkdir" From 77a7f95689322a8da9186400153167419ef3b3fa Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 25 May 2020 21:20:26 +0900 Subject: [PATCH 59/59] Release v2.0.0-rc.2 --- Cargo.lock | 4 ++-- Cargo.toml | 4 ++-- rustfmt-core/rustfmt-bin/Cargo.toml | 4 ++-- rustfmt-core/rustfmt-lib/Cargo.toml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7cb1a881726..7ee439ed27c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1057,7 +1057,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "2.0.0-rc.1" +version = "2.0.0-rc.2" dependencies = [ "anyhow", "cargo_metadata", @@ -1077,7 +1077,7 @@ dependencies = [ [[package]] name = "rustfmt_lib" -version = "2.0.0-rc.1" +version = "2.0.0-rc.2" dependencies = [ "annotate-snippets 0.8.0", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index a741d6adf9d..bb7ad511ddb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "2.0.0-rc.1" +version = "2.0.0-rc.2" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang/rustfmt" @@ -51,7 +51,7 @@ regex = { version = "1.0", optional = true } serde = { version = "1.0", optional = true } serde_json = { version = "1.0", optional = true } -rustfmt_lib = { path = "rustfmt-core/rustfmt-lib", version = "2.0.0-rc.1" } +rustfmt_lib = { path = "rustfmt-core/rustfmt-lib", version = "2.0.0-rc.2" } [dev-dependencies] lazy_static = "1.0" diff --git a/rustfmt-core/rustfmt-bin/Cargo.toml b/rustfmt-core/rustfmt-bin/Cargo.toml index 3d8e033957c..b03a882058a 100644 --- a/rustfmt-core/rustfmt-bin/Cargo.toml +++ b/rustfmt-core/rustfmt-bin/Cargo.toml @@ -2,7 +2,7 @@ # The metadata of this crate is intentionally removed to avoid publishing this crate by accident. name = "rustfmt-bin" -version = "2.0.0-rc.1" +version = "2.0.0-rc.2" edition = "2018" [[bin]] @@ -42,7 +42,7 @@ structopt = "0.3" term = "0.6" thiserror = "1.0" -rustfmt_lib = { path = "../rustfmt-lib", version = "2.0.0-rc.1" } +rustfmt_lib = { path = "../rustfmt-lib", version = "2.0.0-rc.2" } [dev-dependencies] lazy_static = "1.0" diff --git a/rustfmt-core/rustfmt-lib/Cargo.toml b/rustfmt-core/rustfmt-lib/Cargo.toml index 646c4c1c0d1..1bc4c7fd194 100644 --- a/rustfmt-core/rustfmt-lib/Cargo.toml +++ b/rustfmt-core/rustfmt-lib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustfmt_lib" -version = "2.0.0-rc.1" +version = "2.0.0-rc.2" authors = ["topecongiro "] edition = "2018" description = "Rustfmt as a library"