aboutsummaryrefslogtreecommitdiff
path: root/crates/assists/src/handlers
diff options
context:
space:
mode:
Diffstat (limited to 'crates/assists/src/handlers')
-rw-r--r--crates/assists/src/handlers/replace_impl_trait_with_generic.rs62
1 files changed, 62 insertions, 0 deletions
diff --git a/crates/assists/src/handlers/replace_impl_trait_with_generic.rs b/crates/assists/src/handlers/replace_impl_trait_with_generic.rs
new file mode 100644
index 000000000..8af2d16dd
--- /dev/null
+++ b/crates/assists/src/handlers/replace_impl_trait_with_generic.rs
@@ -0,0 +1,62 @@
1use syntax::ast::{self, edit::AstNodeEdit, make, AstNode, GenericParamsOwner};
2
3use crate::{AssistContext, AssistId, AssistKind, Assists};
4
5// Assist: replace_impl_trait_with_generic
6//
7// Replaces `impl Trait` function argument with the named generic.
8pub(crate) fn replace_impl_trait_with_generic(
9 acc: &mut Assists,
10 ctx: &AssistContext,
11) -> Option<()> {
12 let type_impl_trait = ctx.find_node_at_offset::<ast::ImplTraitType>()?;
13 let type_param = type_impl_trait.syntax().parent().and_then(ast::Param::cast)?;
14 let type_fn = type_param.syntax().ancestors().nth(2).and_then(ast::Fn::cast)?;
15
16 let generic_param_list =
17 type_fn.generic_param_list().unwrap_or_else(|| make::generic_param_list(None));
18
19 let impl_trait_ty = type_impl_trait
20 .syntax()
21 .descendants()
22 .last()
23 .and_then(ast::NameRef::cast)?
24 .text()
25 .to_string();
26
27 let target = type_fn.syntax().text_range();
28 acc.add(
29 AssistId("replace_impl_trait_with_generic", AssistKind::RefactorRewrite),
30 "Replace impl trait with generic",
31 target,
32 |edit| {
33 let generic_letter = impl_trait_ty[..1].to_string();
34 edit.replace_ast::<ast::Type>(type_impl_trait.into(), make::ty(&generic_letter));
35
36 let new_params = generic_param_list
37 .append_param(make::generic_param(generic_letter, Some(impl_trait_ty)));
38 let new_type_fn = type_fn.replace_descendant(generic_param_list, new_params);
39 edit.replace_ast(type_fn.clone(), new_type_fn);
40 },
41 )
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47
48 use crate::tests::check_assist;
49
50 #[test]
51 fn replace_with_generic_params() {
52 check_assist(
53 replace_impl_trait_with_generic,
54 r#"
55 fn foo<G>(bar: <|>impl Bar) {}
56 "#,
57 r#"
58 fn foo<G, B: Bar>(bar: B) {}
59 "#,
60 );
61 }
62}