Skip to content

Commit a8a18f3

Browse files
committed
add normalize import assist
1 parent 81d713e commit a8a18f3

File tree

3 files changed

+181
-0
lines changed

3 files changed

+181
-0
lines changed
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
use ide_db::imports::merge_imports::try_normalize_import;
2+
use syntax::{ast, AstNode};
3+
4+
use crate::{
5+
assist_context::{AssistContext, Assists},
6+
AssistId, AssistKind,
7+
};
8+
9+
// Assist: normalize_import
10+
//
11+
// Normalizes an import.
12+
//
13+
// ```
14+
// use$0 std::{io, {fmt::Formatter}};
15+
// ```
16+
// ->
17+
// ```
18+
// use std::{fmt::Formatter, io};
19+
// ```
20+
pub(crate) fn normalize_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
21+
let use_item = if ctx.has_empty_selection() {
22+
ctx.find_node_at_offset()?
23+
} else {
24+
ctx.covering_element().ancestors().find_map(ast::Use::cast)?
25+
};
26+
27+
let target = use_item.syntax().text_range();
28+
let normalized_use_item =
29+
try_normalize_import(&use_item, ctx.config.insert_use.granularity.into())?;
30+
31+
acc.add(
32+
AssistId("normalize_import", AssistKind::RefactorRewrite),
33+
"Normalize import",
34+
target,
35+
|builder| {
36+
builder.replace_ast(use_item, normalized_use_item);
37+
},
38+
)
39+
}
40+
41+
#[cfg(test)]
42+
mod tests {
43+
use crate::tests::{
44+
check_assist, check_assist_import_one, check_assist_not_applicable,
45+
check_assist_not_applicable_for_import_one,
46+
};
47+
48+
use super::*;
49+
50+
macro_rules! check_assist_variations {
51+
($fixture: literal, $expected: literal) => {
52+
check_assist(
53+
normalize_import,
54+
concat!("use $0", $fixture, ";"),
55+
concat!("use ", $expected, ";"),
56+
);
57+
check_assist(
58+
normalize_import,
59+
concat!("$0use ", $fixture, ";"),
60+
concat!("use ", $expected, ";"),
61+
);
62+
63+
check_assist_import_one(
64+
normalize_import,
65+
concat!("use $0", $fixture, ";"),
66+
concat!("use {", $expected, "};"),
67+
);
68+
check_assist_import_one(
69+
normalize_import,
70+
concat!("$0use ", $fixture, ";"),
71+
concat!("use {", $expected, "};"),
72+
);
73+
74+
check_assist_import_one(
75+
normalize_import,
76+
concat!("use $0{", $fixture, "};"),
77+
concat!("use {", $expected, "};"),
78+
);
79+
check_assist_import_one(
80+
normalize_import,
81+
concat!("$0use {", $fixture, "};"),
82+
concat!("use {", $expected, "};"),
83+
);
84+
85+
check_assist(
86+
normalize_import,
87+
concat!("use $0", $fixture, "$0;"),
88+
concat!("use ", $expected, ";"),
89+
);
90+
check_assist(
91+
normalize_import,
92+
concat!("$0use ", $fixture, ";$0"),
93+
concat!("use ", $expected, ";"),
94+
);
95+
};
96+
}
97+
98+
macro_rules! check_assist_not_applicable_variations {
99+
($fixture: literal) => {
100+
check_assist_not_applicable(normalize_import, concat!("use $0", $fixture, ";"));
101+
check_assist_not_applicable(normalize_import, concat!("$0use ", $fixture, ";"));
102+
103+
check_assist_not_applicable_for_import_one(
104+
normalize_import,
105+
concat!("use $0{", $fixture, "};"),
106+
);
107+
check_assist_not_applicable_for_import_one(
108+
normalize_import,
109+
concat!("$0use {", $fixture, "};"),
110+
);
111+
};
112+
}
113+
114+
#[test]
115+
fn test_order() {
116+
check_assist_variations!(
117+
"foo::{*, Qux, bar::{Quux, Bar}, baz, FOO_BAZ, self, Baz}",
118+
"foo::{self, bar::{Bar, Quux}, baz, Baz, Qux, FOO_BAZ, *}"
119+
);
120+
}
121+
122+
#[test]
123+
fn test_redundant_braces() {
124+
check_assist_variations!("foo::{bar::{baz, Qux}}", "foo::bar::{baz, Qux}");
125+
check_assist_variations!("foo::{bar::{self}}", "foo::bar");
126+
check_assist_variations!("foo::{bar::{*}}", "foo::bar::*");
127+
check_assist_variations!("foo::{bar::{Qux as Quux}}", "foo::bar::Qux as Quux");
128+
check_assist_variations!(
129+
"foo::bar::{{FOO_BAZ, Qux, self}, {*, baz}}",
130+
"foo::bar::{self, baz, Qux, FOO_BAZ, *}"
131+
);
132+
check_assist_variations!(
133+
"foo::bar::{{{FOO_BAZ}, {{Qux}, {self}}}, {{*}, {baz}}}",
134+
"foo::bar::{self, baz, Qux, FOO_BAZ, *}"
135+
);
136+
}
137+
138+
#[test]
139+
fn test_merge() {
140+
check_assist_variations!(
141+
"foo::{*, bar, {FOO_BAZ, qux}, bar::{*, baz}, {Quux}}",
142+
"foo::{bar::{self, baz, *}, qux, Quux, FOO_BAZ, *}"
143+
);
144+
check_assist_variations!(
145+
"foo::{*, bar, {FOO_BAZ, qux}, bar::{*, baz}, {Quux, bar::{baz::Foo}}}",
146+
"foo::{bar::{self, baz::{self, Foo}, *}, qux, Quux, FOO_BAZ, *}"
147+
);
148+
}
149+
150+
#[test]
151+
fn not_applicable_to_normalized_import() {
152+
check_assist_not_applicable_variations!("foo::bar");
153+
check_assist_not_applicable_variations!("foo::bar::*");
154+
check_assist_not_applicable_variations!("foo::bar::Qux as Quux");
155+
check_assist_not_applicable_variations!("foo::bar::{self, baz, Qux, FOO_BAZ, *}");
156+
check_assist_not_applicable_variations!(
157+
"foo::{self, bar::{Bar, Quux}, baz, Baz, Qux, FOO_BAZ, *}"
158+
);
159+
check_assist_not_applicable_variations!(
160+
"foo::{bar::{self, baz, *}, qux, Quux, FOO_BAZ, *}"
161+
);
162+
check_assist_not_applicable_variations!(
163+
"foo::{bar::{self, baz::{self, Foo}, *}, qux, Quux, FOO_BAZ, *}"
164+
);
165+
}
166+
}

crates/ide-assists/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ mod handlers {
183183
mod move_guard;
184184
mod move_module_to_file;
185185
mod move_to_mod_rs;
186+
mod normalize_import;
186187
mod number_representation;
187188
mod promote_local_to_const;
188189
mod pull_assignment_up;
@@ -300,6 +301,7 @@ mod handlers {
300301
move_module_to_file::move_module_to_file,
301302
move_to_mod_rs::move_to_mod_rs,
302303
move_from_mod_rs::move_from_mod_rs,
304+
normalize_import::normalize_import,
303305
number_representation::reformat_number_literal,
304306
pull_assignment_up::pull_assignment_up,
305307
promote_local_to_const::promote_local_to_const,

crates/ide-assists/src/tests/generated.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2217,6 +2217,19 @@ fn t() {}
22172217
)
22182218
}
22192219

2220+
#[test]
2221+
fn doctest_normalize_import() {
2222+
check_doc_test(
2223+
"normalize_import",
2224+
r#####"
2225+
use$0 std::{io, {fmt::Formatter}};
2226+
"#####,
2227+
r#####"
2228+
use std::{fmt::Formatter, io};
2229+
"#####,
2230+
)
2231+
}
2232+
22202233
#[test]
22212234
fn doctest_promote_local_to_const() {
22222235
check_doc_test(

0 commit comments

Comments
 (0)