From b036bb4d6dc14e3319d7b8cdba95de1c6b393389 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Sun, 26 Mar 2023 11:30:02 -0400 Subject: [PATCH] Add `ExternalCrate` import grouping style This creates two groups: 1. `std`, `core`, `alloc` and external crates, 2. `self`, `super` and `crate` imports. --- Configurations.md | 22 ++++++++++++- src/config/options.rs | 4 +++ src/reorder.rs | 31 +++++++++++++++++-- .../configs/group_imports/ExternalCrate.rs | 15 +++++++++ .../configs/group_imports/ExternalCrate.rs | 12 +++++++ 5 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 tests/source/configs/group_imports/ExternalCrate.rs create mode 100644 tests/target/configs/group_imports/ExternalCrate.rs diff --git a/Configurations.md b/Configurations.md index ac638ff91e6..e11c03f8fab 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 257a17b2703..61f8b9caa12 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 9e4a668aa49..77f85ae6a78 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.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.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;