// Assist: replace_impl_trait_with_generic
//
// Replaces `impl Trait` function argument with the named generic.
+//
+// ```
+// fn foo<G>(bar: <|>impl Bar) {}
+// ```
+// ->
+// ```
+// fn foo<B: Bar>(bar: B) {}
+// ```
pub(crate) fn replace_impl_trait_with_generic(
acc: &mut Assists,
ctx: &AssistContext,
) -> Option<()> {
let type_impl_trait = ctx.find_node_at_offset::<ast::ImplTraitType>()?;
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 type_fn = type_param.syntax().ancestors().find_map(ast::Fn::cast)?;
let impl_trait_ty = type_impl_trait
.syntax()
"Replace impl trait with generic",
target,
|edit| {
- let generic_letter = impl_trait_ty[..1].to_string();
+ let generic_letter = impl_trait_ty.chars().next().unwrap().to_string();
let generic_param_list = type_fn
.generic_param_list()
let new_type_fn = type_fn
.replace_descendant::<ast::Type>(type_impl_trait.into(), make::ty(&generic_letter))
- .with_generic_params(generic_param_list);
+ .with_generic_param_list(generic_param_list);
edit.replace_ast(type_fn.clone(), new_type_fn);
},
#[test]
fn replace_impl_trait_with_empty_multiline_generic_params() {
- // FIXME: It would be more correct to place the generic parameter
- // on the next line after the left angle.
check_assist(
replace_impl_trait_with_generic,
r#"
fn foo<
G: Foo,
F,
- H,
- B: Bar,
+ H, B: Bar,
>(bar: B) {}
"#,
);
}
#[must_use]
- pub fn with_generic_params(&self, generic_args: ast::GenericParamList) -> ast::Fn {
+ pub fn with_generic_param_list(&self, generic_args: ast::GenericParamList) -> ast::Fn {
if let Some(old) = self.generic_param_list() {
return self.replace_descendant(old, generic_args);
}
#[must_use]
pub fn append_param(&self, item: ast::GenericParam) -> ast::GenericParamList {
- let is_multiline = self.syntax().text().contains_char('\n');
- let ws;
- let space = if is_multiline {
- ws = tokens::WsBuilder::new(&format!(
- "\n{} ",
- leading_indent(self.syntax()).unwrap_or_default()
- ));
- ws.ws()
- } else {
- tokens::single_space()
- };
+ let space = tokens::single_space();
let mut to_insert: ArrayVec<[SyntaxElement; 4]> = ArrayVec::new();
if self.generic_params().next().is_some() {
};
};
- if !is_multiline {
- // don't insert comma before angle
- to_insert.pop();
- }
-
let position = match self.generic_params().last() {
Some(it) => after_field!(it),
None => after_l_angle!(),