Skip to content

Commit 90022d6

Browse files
committed
Preserve attributes for imports_granularity=Item
Fixes rust-lang#5030
1 parent 89ca3f3 commit 90022d6

File tree

4 files changed

+56
-24
lines changed

4 files changed

+56
-24
lines changed

src/imports.rs

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc_span::{
1010

1111
use crate::comment::combine_strs_with_missing_comments;
1212
use crate::config::lists::*;
13+
use crate::config::ImportGranularity;
1314
use crate::config::{Edition, IndentStyle};
1415
use crate::lists::{
1516
definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator,
@@ -182,15 +183,26 @@ impl UseSegment {
182183
}
183184
}
184185

185-
pub(crate) fn merge_use_trees(use_trees: Vec<UseTree>, merge_by: SharedPrefix) -> Vec<UseTree> {
186+
pub(crate) fn regroup_use_trees(
187+
use_trees: Vec<UseTree>,
188+
import_granularity: ImportGranularity,
189+
) -> Vec<UseTree> {
190+
let merge_by = match import_granularity {
191+
ImportGranularity::Item => return flatten_use_trees(use_trees, ImportGranularity::Item),
192+
ImportGranularity::Preserve => return use_trees,
193+
ImportGranularity::Crate => SharedPrefix::Crate,
194+
ImportGranularity::Module => SharedPrefix::Module,
195+
ImportGranularity::One => SharedPrefix::One,
196+
};
197+
186198
let mut result = Vec::with_capacity(use_trees.len());
187199
for use_tree in use_trees {
188200
if use_tree.has_comment() || use_tree.attrs.is_some() {
189201
result.push(use_tree);
190202
continue;
191203
}
192204

193-
for flattened in use_tree.flatten() {
205+
for flattened in use_tree.flatten(import_granularity) {
194206
if let Some(tree) = result
195207
.iter_mut()
196208
.find(|tree| tree.share_prefix(&flattened, merge_by))
@@ -204,10 +216,13 @@ pub(crate) fn merge_use_trees(use_trees: Vec<UseTree>, merge_by: SharedPrefix) -
204216
result
205217
}
206218

207-
pub(crate) fn flatten_use_trees(use_trees: Vec<UseTree>) -> Vec<UseTree> {
219+
fn flatten_use_trees(
220+
use_trees: Vec<UseTree>,
221+
import_granularity: ImportGranularity,
222+
) -> Vec<UseTree> {
208223
use_trees
209224
.into_iter()
210-
.flat_map(UseTree::flatten)
225+
.flat_map(|tree| tree.flatten(import_granularity))
211226
.map(|mut tree| {
212227
// If a path ends in `::self`, rewrite it to `::{self}`.
213228
if let Some(UseSegment::Slf(..)) = tree.path.last() {
@@ -587,7 +602,7 @@ impl UseTree {
587602
}
588603
}
589604

590-
fn flatten(self) -> Vec<UseTree> {
605+
fn flatten(self, import_granularity: ImportGranularity) -> Vec<UseTree> {
591606
if self.path.is_empty() {
592607
return vec![self];
593608
}
@@ -601,15 +616,19 @@ impl UseTree {
601616
let prefix = &self.path[..self.path.len() - 1];
602617
let mut result = vec![];
603618
for nested_use_tree in list {
604-
for flattend in &mut nested_use_tree.clone().flatten() {
619+
for flattend in &mut nested_use_tree.clone().flatten(import_granularity) {
605620
let mut new_path = prefix.to_vec();
606621
new_path.append(&mut flattend.path);
607622
result.push(UseTree {
608623
path: new_path,
609624
span: self.span,
610625
list_item: None,
611626
visibility: self.visibility.clone(),
612-
attrs: None,
627+
// only retain attributes for `ImportGranularity::Item`
628+
attrs: match import_granularity {
629+
ImportGranularity::Item => self.attrs.clone(),
630+
_ => None,
631+
},
613632
});
614633
}
615634
}
@@ -945,7 +964,7 @@ impl Rewrite for UseTree {
945964
}
946965

947966
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
948-
pub(crate) enum SharedPrefix {
967+
enum SharedPrefix {
949968
Crate,
950969
Module,
951970
One,
@@ -1100,7 +1119,7 @@ mod test {
11001119
macro_rules! test_merge {
11011120
($by:ident, [$($input:expr),* $(,)*], [$($output:expr),* $(,)*]) => {
11021121
assert_eq!(
1103-
merge_use_trees(parse_use_trees!($($input,)*), SharedPrefix::$by),
1122+
regroup_use_trees(parse_use_trees!($($input,)*), ImportGranularity::$by),
11041123
parse_use_trees!($($output,)*),
11051124
);
11061125
}
@@ -1209,12 +1228,18 @@ mod test {
12091228
#[test]
12101229
fn test_flatten_use_trees() {
12111230
assert_eq!(
1212-
flatten_use_trees(parse_use_trees!["foo::{a::{b, c}, d::e}"]),
1231+
flatten_use_trees(
1232+
parse_use_trees!["foo::{a::{b, c}, d::e}"],
1233+
ImportGranularity::Item
1234+
),
12131235
parse_use_trees!["foo::a::b", "foo::a::c", "foo::d::e"]
12141236
);
12151237

12161238
assert_eq!(
1217-
flatten_use_trees(parse_use_trees!["foo::{self, a, b::{c, d}, e::*}"]),
1239+
flatten_use_trees(
1240+
parse_use_trees!["foo::{self, a, b::{c, d}, e::*}"],
1241+
ImportGranularity::Item
1242+
),
12181243
parse_use_trees![
12191244
"foo::{self}",
12201245
"foo::a",
@@ -1228,12 +1253,13 @@ mod test {
12281253
#[test]
12291254
fn test_use_tree_flatten() {
12301255
assert_eq!(
1231-
parse_use_tree("a::b::{c, d, e, f}").flatten(),
1256+
parse_use_tree("a::b::{c, d, e, f}").flatten(ImportGranularity::Item),
12321257
parse_use_trees!("a::b::c", "a::b::d", "a::b::e", "a::b::f",)
12331258
);
12341259

12351260
assert_eq!(
1236-
parse_use_tree("a::b::{c::{d, e, f}, g, h::{i, j, k}}").flatten(),
1261+
parse_use_tree("a::b::{c::{d, e, f}, g, h::{i, j, k}}")
1262+
.flatten(ImportGranularity::Item),
12371263
parse_use_trees![
12381264
"a::b::c::d",
12391265
"a::b::c::e",

src/reorder.rs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ use std::cmp::{Ord, Ordering};
1111
use rustc_ast::ast;
1212
use rustc_span::{symbol::sym, Span};
1313

14-
use crate::config::{Config, GroupImportsTactic, ImportGranularity};
15-
use crate::imports::{flatten_use_trees, merge_use_trees, SharedPrefix, UseSegment, UseTree};
14+
use crate::config::{Config, GroupImportsTactic};
15+
use crate::imports::{regroup_use_trees, 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,8 @@ 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-
normalized_items = match context.config.imports_granularity() {
111-
ImportGranularity::Crate => merge_use_trees(normalized_items, SharedPrefix::Crate),
112-
ImportGranularity::Module => {
113-
merge_use_trees(normalized_items, SharedPrefix::Module)
114-
}
115-
ImportGranularity::Item => flatten_use_trees(normalized_items),
116-
ImportGranularity::One => merge_use_trees(normalized_items, SharedPrefix::One),
117-
ImportGranularity::Preserve => normalized_items,
118-
};
110+
normalized_items =
111+
regroup_use_trees(normalized_items, context.config.imports_granularity());
119112

120113
let mut regrouped_items = match context.config.group_imports() {
121114
GroupImportsTactic::Preserve | GroupImportsTactic::One => {

tests/source/issue-5030.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// rustfmt-imports_granularity: Item
2+
3+
#[cfg(feature = "foo")]
4+
use std::collections::{
5+
HashMap,
6+
HashSet,
7+
};

tests/target/issue-5030.rs

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+
#[cfg(feature = "foo")]
4+
use std::collections::HashMap;
5+
#[cfg(feature = "foo")]
6+
use std::collections::HashSet;

0 commit comments

Comments
 (0)