diff --git a/Configurations.md b/Configurations.md index ac5747800b2..b04e36f838f 100644 --- a/Configurations.md +++ b/Configurations.md @@ -2229,7 +2229,7 @@ Controls the strategy for how consecutive imports are grouped together. Controls the strategy for grouping sets of consecutive imports. Imports may contain newlines between imports and still be grouped together as a single set, but other statements between imports will result in different grouping sets. - **Default value**: `Preserve` -- **Possible values**: `Preserve`, `StdExternalCrate`, `One` +- **Possible values**: `Preserve`, `StdExternalCrate`, `ExternalCrate`, `One` - **Stable**: No (tracking issue: [#5083](https://github.com/rust-lang/rustfmt/issues/5083)) Each set of imports (one or more `use` statements, optionally separated by newlines) will be formatted independently. Other statements such as `mod ...` or `extern crate ...` will cause imports to not be grouped together. @@ -2277,6 +2277,26 @@ use super::update::convert_publish_payload; use crate::models::Event; ``` +#### `ExternalCrate`: + +Discard existing import groups, and create two groups for: +1. `std`, `core`, `alloc` and external crates, +2. `self`, `super` and `crate` imports. + +```rust +use alloc::alloc::Layout; +use broker::database::PooledConnection; +use chrono::Utc; +use core::f32; +use juniper::{FieldError, FieldResult}; +use std::sync::Arc; +use uuid::Uuid; + +use super::schema::{Context, Payload}; +use super::update::convert_publish_payload; +use crate::models::Event; +``` + #### `One`: Discard existing import groups, and create a single group for everything diff --git a/src/config/options.rs b/src/config/options.rs index e37f4027e4a..95074d6eef0 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -112,6 +112,10 @@ pub enum GroupImportsTactic { /// 2. other imports /// 3. `self` / `crate` / `super` imports StdExternalCrate, + /// Discard existing groups, and create new groups for + /// 1. `std` / `core` / `alloc` / other imports + /// 2. `self` / `crate` / `super` imports + ExternalCrate, /// Discard existing groups, and create a single group for everything One, } diff --git a/src/reorder.rs b/src/reorder.rs index 3bddf4c1b6a..8b1ebfbe76b 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -116,7 +116,10 @@ fn rewrite_reorderable_or_regroupable_items( GroupImportsTactic::Preserve | GroupImportsTactic::One => { vec![normalized_items] } - GroupImportsTactic::StdExternalCrate => group_imports(normalized_items), + GroupImportsTactic::StdExternalCrate => { + group_imports_std_external_crate(normalized_items) + } + GroupImportsTactic::ExternalCrate => group_imports_external_crate(normalized_items), }; if context.config.reorder_imports() { @@ -172,7 +175,7 @@ fn contains_macro_use_attr(item: &ast::Item) -> bool { /// Divides imports into three groups, corresponding to standard, external /// and local imports. Sorts each subgroup. -fn group_imports(uts: Vec) -> Vec> { +fn group_imports_std_external_crate(uts: Vec) -> Vec> { let mut std_imports = Vec::new(); let mut external_imports = Vec::new(); let mut local_imports = Vec::new(); @@ -198,6 +201,30 @@ fn group_imports(uts: Vec) -> Vec> { vec![std_imports, external_imports, local_imports] } +/// Divides imports into two groups, corresponding to external crates +/// and local imports. Sorts each subgroup. +fn group_imports_external_crate(uts: Vec) -> Vec> { + let mut external_imports = Vec::new(); + let mut local_imports = Vec::new(); + + for ut in uts.into_iter() { + if ut.path.is_empty() { + external_imports.push(ut); + continue; + } + match &ut.path[0].kind { + UseSegmentKind::Ident(..) => external_imports.push(ut), + UseSegmentKind::Slf(_) | UseSegmentKind::Super(_) | UseSegmentKind::Crate(_) => { + local_imports.push(ut) + } + // These are probably illegal here + UseSegmentKind::Glob | UseSegmentKind::List(_) => external_imports.push(ut), + } + } + + vec![external_imports, local_imports] +} + /// A simplified version of `ast::ItemKind`. #[derive(Debug, PartialEq, Eq, Copy, Clone)] enum ReorderableItemKind { diff --git a/tests/source/configs/group_imports/ExternalCrate-merge_imports.rs b/tests/source/configs/group_imports/ExternalCrate-merge_imports.rs new file mode 100644 index 00000000000..c5c013068f9 --- /dev/null +++ b/tests/source/configs/group_imports/ExternalCrate-merge_imports.rs @@ -0,0 +1,17 @@ +// rustfmt-group_imports: ExternalCrate +// rustfmt-imports_granularity: Crate +use chrono::Utc; +use super::update::convert_publish_payload; + +use juniper::{FieldError, FieldResult}; +use uuid::Uuid; +use alloc::alloc::Layout; + +use std::sync::Arc; +use alloc::vec::Vec; + +use broker::database::PooledConnection; + +use super::schema::{Context, Payload}; +use core::f32; +use crate::models::Event; diff --git a/tests/source/configs/group_imports/ExternalCrate-nested.rs b/tests/source/configs/group_imports/ExternalCrate-nested.rs new file mode 100644 index 00000000000..3b844f5b1e9 --- /dev/null +++ b/tests/source/configs/group_imports/ExternalCrate-nested.rs @@ -0,0 +1,7 @@ +// rustfmt-group_imports: ExternalCrate +mod test { + use crate::foo::bar; + use std::path; + use crate::foo::bar2; + use uuid::Uuid; +} diff --git a/tests/source/configs/group_imports/ExternalCrate-no_reorder.rs b/tests/source/configs/group_imports/ExternalCrate-no_reorder.rs new file mode 100644 index 00000000000..b762340c26a --- /dev/null +++ b/tests/source/configs/group_imports/ExternalCrate-no_reorder.rs @@ -0,0 +1,17 @@ +// rustfmt-group_imports: ExternalCrate +// rustfmt-reorder_imports: false + +use chrono::Utc; +use super::update::convert_publish_payload; + +use juniper::{FieldError, FieldResult}; +use uuid::Uuid; +use alloc::alloc::Layout; + +use std::sync::Arc; + +use broker::database::PooledConnection; + +use super::schema::{Context, Payload}; +use core::f32; +use crate::models::Event; diff --git a/tests/source/configs/group_imports/ExternalCrate-non_consecutive.rs b/tests/source/configs/group_imports/ExternalCrate-non_consecutive.rs new file mode 100644 index 00000000000..8ffecce9205 --- /dev/null +++ b/tests/source/configs/group_imports/ExternalCrate-non_consecutive.rs @@ -0,0 +1,27 @@ +// rustfmt-group_imports: ExternalCrate +use chrono::Utc; +use super::update::convert_publish_payload; + + + + + +use juniper::{FieldError, FieldResult}; + +use uuid::Uuid; +use alloc::alloc::Layout; + +extern crate uuid; + + + + + +use std::sync::Arc; + + +use broker::database::PooledConnection; + +use super::schema::{Context, Payload}; +use core::f32; +use crate::models::Event; diff --git a/tests/source/configs/group_imports/ExternalCrate.rs b/tests/source/configs/group_imports/ExternalCrate.rs new file mode 100644 index 00000000000..b209192f36d --- /dev/null +++ b/tests/source/configs/group_imports/ExternalCrate.rs @@ -0,0 +1,15 @@ +// rustfmt-group_imports: ExternalCrate +use chrono::Utc; +use super::update::convert_publish_payload; + +use juniper::{FieldError, FieldResult}; +use uuid::Uuid; +use alloc::alloc::Layout; + +use std::sync::Arc; + +use broker::database::PooledConnection; + +use super::schema::{Context, Payload}; +use core::f32; +use crate::models::Event; diff --git a/tests/target/configs/group_imports/ExternalCrate-merge_imports.rs b/tests/target/configs/group_imports/ExternalCrate-merge_imports.rs new file mode 100644 index 00000000000..cea05e76826 --- /dev/null +++ b/tests/target/configs/group_imports/ExternalCrate-merge_imports.rs @@ -0,0 +1,15 @@ +// rustfmt-group_imports: ExternalCrate +// rustfmt-imports_granularity: Crate +use alloc::{alloc::Layout, vec::Vec}; +use broker::database::PooledConnection; +use chrono::Utc; +use core::f32; +use juniper::{FieldError, FieldResult}; +use std::sync::Arc; +use uuid::Uuid; + +use super::{ + schema::{Context, Payload}, + update::convert_publish_payload, +}; +use crate::models::Event; diff --git a/tests/target/configs/group_imports/ExternalCrate-nested.rs b/tests/target/configs/group_imports/ExternalCrate-nested.rs new file mode 100644 index 00000000000..17ec33d83d1 --- /dev/null +++ b/tests/target/configs/group_imports/ExternalCrate-nested.rs @@ -0,0 +1,8 @@ +// rustfmt-group_imports: ExternalCrate +mod test { + use std::path; + use uuid::Uuid; + + use crate::foo::bar; + use crate::foo::bar2; +} diff --git a/tests/target/configs/group_imports/ExternalCrate-no_reorder.rs b/tests/target/configs/group_imports/ExternalCrate-no_reorder.rs new file mode 100644 index 00000000000..6673cc09097 --- /dev/null +++ b/tests/target/configs/group_imports/ExternalCrate-no_reorder.rs @@ -0,0 +1,14 @@ +// rustfmt-group_imports: ExternalCrate +// rustfmt-reorder_imports: false + +use chrono::Utc; +use juniper::{FieldError, FieldResult}; +use uuid::Uuid; +use alloc::alloc::Layout; +use std::sync::Arc; +use broker::database::PooledConnection; +use core::f32; + +use super::update::convert_publish_payload; +use super::schema::{Context, Payload}; +use crate::models::Event; diff --git a/tests/target/configs/group_imports/ExternalCrate-non_consecutive.rs b/tests/target/configs/group_imports/ExternalCrate-non_consecutive.rs new file mode 100644 index 00000000000..259d22a838a --- /dev/null +++ b/tests/target/configs/group_imports/ExternalCrate-non_consecutive.rs @@ -0,0 +1,16 @@ +// rustfmt-group_imports: ExternalCrate +use alloc::alloc::Layout; +use chrono::Utc; +use juniper::{FieldError, FieldResult}; +use uuid::Uuid; + +use super::update::convert_publish_payload; + +extern crate uuid; + +use broker::database::PooledConnection; +use core::f32; +use std::sync::Arc; + +use super::schema::{Context, Payload}; +use crate::models::Event; diff --git a/tests/target/configs/group_imports/ExternalCrate.rs b/tests/target/configs/group_imports/ExternalCrate.rs new file mode 100644 index 00000000000..8af9c1fd4a4 --- /dev/null +++ b/tests/target/configs/group_imports/ExternalCrate.rs @@ -0,0 +1,12 @@ +// rustfmt-group_imports: ExternalCrate +use alloc::alloc::Layout; +use broker::database::PooledConnection; +use chrono::Utc; +use core::f32; +use juniper::{FieldError, FieldResult}; +use std::sync::Arc; +use uuid::Uuid; + +use super::schema::{Context, Payload}; +use super::update::convert_publish_payload; +use crate::models::Event;