Skip to content

Commit 34e9fca

Browse files
msmorgancalebcartwright
authored andcommitted
Add imports_granularity="Item".
This option splits all imports into their own `use` statement.
1 parent 5e14f76 commit 34e9fca

File tree

6 files changed

+81
-9
lines changed

6 files changed

+81
-9
lines changed

Configurations.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1620,7 +1620,7 @@ pub enum Foo {}
16201620
How imports should be grouped into `use` statements. Imports will be merged or split to the configured level of granularity.
16211621

16221622
- **Default value**: `Preserve`
1623-
- **Possible values**: `Preserve`, `Crate`, `Module`
1623+
- **Possible values**: `Preserve`, `Crate`, `Module`, `Item`
16241624
- **Stable**: No
16251625

16261626
#### `Preserve` (default):
@@ -1659,6 +1659,21 @@ use foo::{a, b, c};
16591659
use qux::{h, i};
16601660
```
16611661

1662+
#### `Item`:
1663+
1664+
Flatten imports so that each has its own `use` statement.
1665+
1666+
```rust
1667+
use foo::a;
1668+
use foo::b;
1669+
use foo::b::f;
1670+
use foo::b::g;
1671+
use foo::c;
1672+
use foo::d::e;
1673+
use qux::h;
1674+
use qux::i;
1675+
```
1676+
16621677
## `merge_imports`
16631678

16641679
This option is deprecated. Use `imports_granularity = "Crate"` instead.

src/config/options.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ pub enum ImportGranularity {
121121
Crate,
122122
/// Use one `use` statement per module.
123123
Module,
124+
/// Use one `use` statement per imported item.
125+
Item,
124126
}
125127

126128
#[config_type]

src/imports.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,24 @@ pub(crate) fn merge_use_trees(use_trees: Vec<UseTree>, merge_by: SharedPrefix) -
181181
result
182182
}
183183

184+
pub(crate) fn flatten_use_trees(use_trees: Vec<UseTree>) -> Vec<UseTree> {
185+
use_trees
186+
.into_iter()
187+
.flat_map(UseTree::flatten)
188+
.map(|mut tree| {
189+
// If a path ends in `::self`, rewrite it to `::{self}`.
190+
if let Some(UseSegment::Slf(..)) = tree.path.last() {
191+
let self_segment = tree.path.pop().unwrap();
192+
tree.path.push(UseSegment::List(vec![UseTree::from_path(
193+
vec![self_segment],
194+
DUMMY_SP,
195+
)]));
196+
}
197+
tree
198+
})
199+
.collect()
200+
}
201+
184202
impl fmt::Debug for UseTree {
185203
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
186204
fmt::Display::fmt(self, f)
@@ -1084,6 +1102,25 @@ mod test {
10841102
);
10851103
}
10861104

1105+
#[test]
1106+
fn test_flatten_use_trees() {
1107+
assert_eq!(
1108+
flatten_use_trees(parse_use_trees!["foo::{a::{b, c}, d::e}"]),
1109+
parse_use_trees!["foo::a::b", "foo::a::c", "foo::d::e"]
1110+
);
1111+
1112+
assert_eq!(
1113+
flatten_use_trees(parse_use_trees!["foo::{self, a, b::{c, d}, e::*}"]),
1114+
parse_use_trees![
1115+
"foo::{self}",
1116+
"foo::a",
1117+
"foo::b::c",
1118+
"foo::b::d",
1119+
"foo::e::*"
1120+
]
1121+
);
1122+
}
1123+
10871124
#[test]
10881125
fn test_use_tree_flatten() {
10891126
assert_eq!(

src/reorder.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_ast::ast;
1212
use rustc_span::{symbol::sym, Span};
1313

1414
use crate::config::{Config, GroupImportsTactic, ImportGranularity};
15-
use crate::imports::{merge_use_trees, SharedPrefix, UseSegment, UseTree};
15+
use crate::imports::{flatten_use_trees, merge_use_trees, SharedPrefix, UseSegment, UseTree};
1616
use crate::items::{is_mod_decl, rewrite_extern_crate, rewrite_mod};
1717
use crate::lists::{itemize_list, write_list, ListFormatting, ListItem};
1818
use crate::rewrite::RewriteContext;
@@ -107,15 +107,14 @@ fn rewrite_reorderable_or_regroupable_items(
107107
for (item, list_item) in normalized_items.iter_mut().zip(list_items) {
108108
item.list_item = Some(list_item.clone());
109109
}
110-
match context.config.imports_granularity() {
111-
ImportGranularity::Crate => {
112-
normalized_items = merge_use_trees(normalized_items, SharedPrefix::Crate)
113-
}
110+
normalized_items = match context.config.imports_granularity() {
111+
ImportGranularity::Crate => merge_use_trees(normalized_items, SharedPrefix::Crate),
114112
ImportGranularity::Module => {
115-
normalized_items = merge_use_trees(normalized_items, SharedPrefix::Module)
113+
merge_use_trees(normalized_items, SharedPrefix::Module)
116114
}
117-
ImportGranularity::Preserve => {}
118-
}
115+
ImportGranularity::Item => flatten_use_trees(normalized_items),
116+
ImportGranularity::Preserve => normalized_items,
117+
};
119118

120119
let mut regrouped_items = match context.config.group_imports() {
121120
GroupImportsTactic::Preserve => vec![normalized_items],
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// rustfmt-imports_granularity: Item
2+
3+
use a::{b, c, d};
4+
use a::{f::g, h::{i, j}};
5+
use a::{l::{self, m, n::o, p::*}};
6+
use a::q::{self};
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// rustfmt-imports_granularity: Item
2+
3+
use a::b;
4+
use a::c;
5+
use a::d;
6+
use a::f::g;
7+
use a::h::i;
8+
use a::h::j;
9+
use a::l::m;
10+
use a::l::n::o;
11+
use a::l::p::*;
12+
use a::l::{self};
13+
use a::q::{self};

0 commit comments

Comments
 (0)