From fe3170dc344f73126cd4ff2f197d49a8b7f2fe1f Mon Sep 17 00:00:00 2001 From: Aleksei Sidorov Date: Thu, 3 Sep 2020 01:32:18 +0300 Subject: Initial implementation of the #5085 issue --- .../handlers/replace_impl_trait_with_generic.rs | 62 ++++++++++++++++++++++ crates/assists/src/lib.rs | 2 + 2 files changed, 64 insertions(+) create mode 100644 crates/assists/src/handlers/replace_impl_trait_with_generic.rs (limited to 'crates/assists') 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 @@ +use syntax::ast::{self, edit::AstNodeEdit, make, AstNode, GenericParamsOwner}; + +use crate::{AssistContext, AssistId, AssistKind, Assists}; + +// Assist: replace_impl_trait_with_generic +// +// Replaces `impl Trait` function argument with the named generic. +pub(crate) fn replace_impl_trait_with_generic( + acc: &mut Assists, + ctx: &AssistContext, +) -> Option<()> { + let type_impl_trait = ctx.find_node_at_offset::()?; + let type_param = type_impl_trait.syntax().parent().and_then(ast::Param::cast)?; + let type_fn = type_param.syntax().ancestors().nth(2).and_then(ast::Fn::cast)?; + + let generic_param_list = + type_fn.generic_param_list().unwrap_or_else(|| make::generic_param_list(None)); + + let impl_trait_ty = type_impl_trait + .syntax() + .descendants() + .last() + .and_then(ast::NameRef::cast)? + .text() + .to_string(); + + let target = type_fn.syntax().text_range(); + acc.add( + AssistId("replace_impl_trait_with_generic", AssistKind::RefactorRewrite), + "Replace impl trait with generic", + target, + |edit| { + let generic_letter = impl_trait_ty[..1].to_string(); + edit.replace_ast::(type_impl_trait.into(), make::ty(&generic_letter)); + + let new_params = generic_param_list + .append_param(make::generic_param(generic_letter, Some(impl_trait_ty))); + let new_type_fn = type_fn.replace_descendant(generic_param_list, new_params); + edit.replace_ast(type_fn.clone(), new_type_fn); + }, + ) +} + +#[cfg(test)] +mod tests { + use super::*; + + use crate::tests::check_assist; + + #[test] + fn replace_with_generic_params() { + check_assist( + replace_impl_trait_with_generic, + r#" + fn foo(bar: <|>impl Bar) {} + "#, + r#" + fn foo(bar: B) {} + "#, + ); + } +} diff --git a/crates/assists/src/lib.rs b/crates/assists/src/lib.rs index 2e0d191a6..cbac53e71 100644 --- a/crates/assists/src/lib.rs +++ b/crates/assists/src/lib.rs @@ -155,6 +155,7 @@ mod handlers { mod remove_unused_param; mod reorder_fields; mod replace_if_let_with_match; + mod replace_impl_trait_with_generic; mod replace_let_with_if_let; mod replace_qualified_name_with_use; mod replace_unwrap_with_match; @@ -202,6 +203,7 @@ mod handlers { remove_unused_param::remove_unused_param, reorder_fields::reorder_fields, replace_if_let_with_match::replace_if_let_with_match, + replace_impl_trait_with_generic::replace_impl_trait_with_generic, replace_let_with_if_let::replace_let_with_if_let, replace_qualified_name_with_use::replace_qualified_name_with_use, replace_unwrap_with_match::replace_unwrap_with_match, -- cgit v1.2.3