Skip to content

Commit 95888c8

Browse files
make the generated lifetime more orderly
1 parent 6aa7edf commit 95888c8

File tree

1 file changed

+46
-27
lines changed

1 file changed

+46
-27
lines changed

crates/ide-assists/src/handlers/add_missing_lifetime.rs

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use ide_db::{FxIndexSet, syntax_helpers::suggest_name::NameGenerator};
2+
use itertools::chain;
23
use syntax::{
34
NodeOrToken, SmolStr, T,
45
ast::{
@@ -53,7 +54,10 @@ pub(crate) fn add_missing_lifetime(acc: &mut Assists, ctx: &AssistContext<'_>) -
5354
.filter(|lt_text| !adt_declared_lifetimes.contains(lt_text))
5455
.collect();
5556

56-
if refs_without_lifetime.is_empty() && adt_undeclared_lifetimes.is_empty() {
57+
let has_refs_without_lifetime = !refs_without_lifetime.is_empty();
58+
let has_undeclared_lifetimes = !adt_undeclared_lifetimes.is_empty();
59+
60+
if !has_refs_without_lifetime && !has_undeclared_lifetimes {
5761
return None;
5862
}
5963

@@ -67,6 +71,8 @@ pub(crate) fn add_missing_lifetime(acc: &mut Assists, ctx: &AssistContext<'_>) -
6771
adt_undeclared_lifetimes,
6872
refs_without_lifetime,
6973
all_existing_lifetimes,
74+
has_refs_without_lifetime,
75+
has_undeclared_lifetimes,
7076
)
7177
}
7278

@@ -77,10 +83,9 @@ fn add_and_declare_lifetimes(
7783
adt_undeclared_lifetimes: FxIndexSet<SmolStr>,
7884
refs_without_lifetime: Vec<ast::RefType>,
7985
all_existing_lifetimes: Vec<SmolStr>,
86+
has_refs_without_lifetime: bool,
87+
has_undeclared_lifetimes: bool,
8088
) -> Option<()> {
81-
let has_refs_without_lifetime = !refs_without_lifetime.is_empty();
82-
let has_undeclared_lifetimes = !adt_undeclared_lifetimes.is_empty();
83-
8489
let message = match (has_refs_without_lifetime, has_undeclared_lifetimes) {
8590
(false, true) => "Declare used lifetimes in generic parameters",
8691
(true, false) | (true, true) => "Add missing lifetimes",
@@ -99,41 +104,46 @@ fn add_and_declare_lifetimes(
99104
|builder| {
100105
let make = SyntaxFactory::with_mappings();
101106
let mut editor = builder.make_editor(node.syntax());
102-
let comma_and_space = [make::token(T![,]).into(), tokens::single_space().into()];
107+
let comma_and_space = || [make::token(T![,]).into(), tokens::single_space().into()];
103108

104109
let mut lifetime_elements = vec![];
105110
let mut new_lifetime_to_annotate = None;
106111

107112
if has_undeclared_lifetimes {
108113
for (i, lifetime_text) in adt_undeclared_lifetimes.iter().enumerate() {
109-
(i > 0).then(|| lifetime_elements.extend(comma_and_space.clone()));
110-
let new_lifetime = make.lifetime(lifetime_text);
111-
lifetime_elements.push(new_lifetime.syntax().clone().into());
114+
(i > 0).then(|| lifetime_elements.extend(comma_and_space()));
115+
lifetime_elements.push(make.lifetime(lifetime_text).syntax().clone().into());
112116
}
113117
}
114118

115119
if has_refs_without_lifetime {
116-
has_undeclared_lifetimes.then(|| lifetime_elements.extend(comma_and_space.clone()));
120+
has_undeclared_lifetimes.then(|| lifetime_elements.extend(comma_and_space()));
117121
let lifetime = make.lifetime(&new_lifetime_name);
118-
new_lifetime_to_annotate = Some(lifetime.clone());
119122
lifetime_elements.push(lifetime.syntax().clone().into());
123+
new_lifetime_to_annotate = Some(lifetime);
120124
}
121125

122-
if let Some(gen_param) = node.generic_param_list()
123-
&& let Some(left_angle) = gen_param.l_angle_token()
124-
{
125-
if !lifetime_elements.is_empty() {
126+
if let Some(gen_param) = node.generic_param_list() {
127+
if let Some(last_lifetime) = gen_param.lifetime_params().last() {
128+
editor.insert_all(
129+
Position::after(last_lifetime.syntax()),
130+
chain!(comma_and_space(), lifetime_elements).collect(),
131+
);
132+
} else if let Some(l_angle) = gen_param.l_angle_token() {
126133
lifetime_elements.push(make::token(T![,]).into());
127134
lifetime_elements.push(tokens::single_space().into());
135+
editor.insert_all(Position::after(&l_angle), lifetime_elements);
128136
}
129-
editor.insert_all(Position::after(&left_angle), lifetime_elements);
130-
} else if let Some(name) = node.name()
131-
&& !lifetime_elements.is_empty()
132-
{
133-
let mut final_elements = vec![make::token(T![<]).into()];
134-
final_elements.append(&mut lifetime_elements);
135-
final_elements.push(make::token(T![>]).into());
136-
editor.insert_all(Position::after(name.syntax()), final_elements);
137+
} else if let Some(name) = node.name() {
138+
editor.insert_all(
139+
Position::after(name.syntax()),
140+
chain!(
141+
[make::token(T![<]).into()],
142+
lifetime_elements,
143+
[make::token(T![>]).into()]
144+
)
145+
.collect(),
146+
);
137147
}
138148

139149
let snippet = ctx.config.snippet_cap.map(|cap| builder.make_placeholder_snippet(cap));
@@ -276,7 +286,7 @@ struct Foo<'a> {
276286
y: &$0u32
277287
}"#,
278288
r#"
279-
struct Foo<${0:'b}, 'a> {
289+
struct Foo<'a, ${0:'b}> {
280290
x: &'a i32,
281291
y: &${0:'b} u32
282292
}"#,
@@ -300,13 +310,22 @@ struct Foo<'a, ${0:'b}> {
300310
struct $0Foo<T> {
301311
x: &'a i32,
302312
y: &T
313+
z: &'b u32
303314
}"#,
304315
r#"
305-
struct Foo<'a, ${0:'b}, T> {
316+
struct Foo<'a, 'b, ${0:'c}, T> {
306317
x: &'a i32,
307-
y: &${0:'b} T
318+
y: &${0:'c} T
319+
z: &'b u32
308320
}"#,
309321
);
322+
check_assist(
323+
add_missing_lifetime,
324+
r#"
325+
struct $0Foo(&fn(&str) -> &str);"#,
326+
r#"
327+
struct Foo<${0:'a}>(&${0:'a} fn(&str) -> &str);"#,
328+
);
310329
}
311330

312331
#[test]
@@ -392,7 +411,7 @@ enum Foo<'a> {
392411
}
393412
}"#,
394413
r#"
395-
enum Foo<${0:'b}, 'a> {
414+
enum Foo<'a, ${0:'b}> {
396415
Bar {
397416
x: &'a i32,
398417
y: &${0:'b} u32
@@ -472,7 +491,7 @@ union Foo<'a> {
472491
y: &$0u32
473492
}"#,
474493
r#"
475-
union Foo<${0:'b}, 'a> {
494+
union Foo<'a, ${0:'b}> {
476495
x: &'a i32,
477496
y: &${0:'b} u32
478497
}"#,

0 commit comments

Comments
 (0)