diff options
Diffstat (limited to 'crates/assists/src/handlers')
-rw-r--r-- | crates/assists/src/handlers/replace_impl_trait_with_generic.rs | 62 |
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 @@ | |||
1 | use syntax::ast::{self, edit::AstNodeEdit, make, AstNode, GenericParamsOwner}; | ||
2 | |||
3 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | ||
4 | |||
5 | // Assist: replace_impl_trait_with_generic | ||
6 | // | ||
7 | // Replaces `impl Trait` function argument with the named generic. | ||
8 | pub(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)] | ||
45 | mod 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 | } | ||