- let range = TextRange::new(fn_def_node.text_range().start(), ctx.source_range().end());
-
- if let Some(src) = func.source(ctx.db) {
- let function_decl = function_declaration(&src.value);
- match ctx.config.snippet_cap {
- Some(cap) => {
- let snippet = format!("{} {{\n $0\n}}", function_decl);
- item.snippet_edit(cap, TextEdit::replace(range, snippet));
- }
- None => {
- let header = format!("{} {{", function_decl);
- item.text_edit(TextEdit::replace(range, header));
- }
- };
- item.kind(completion_kind);
- item.add_to(acc);
+
+ let range = replacement_range(ctx, fn_def_node);
+ let mut item = CompletionItem::new(completion_kind, range, label);
+ item.lookup_by(fn_name).set_documentation(func.docs(ctx.db));
+
+ if let Some(source) = ctx.sema.source(func) {
+ let assoc_item = ast::AssocItem::Fn(source.value);
+ if let Some(transformed_item) = get_transformed_assoc_item(ctx, assoc_item, impl_def) {
+ let transformed_fn = match transformed_item {
+ ast::AssocItem::Fn(func) => func,
+ _ => unreachable!(),
+ };
+
+ let function_decl = function_declaration(&transformed_fn);
+ match ctx.config.snippet_cap {
+ Some(cap) => {
+ let snippet = format!("{} {{\n $0\n}}", function_decl);
+ item.snippet_edit(cap, TextEdit::replace(range, snippet));
+ }
+ None => {
+ let header = format!("{} {{", function_decl);
+ item.text_edit(TextEdit::replace(range, header));
+ }
+ };
+ item.add_to(acc);
+ }
+ }
+}
+
+/// Transform a relevant associated item to inline generics from the impl, remove attrs and docs, etc.
+fn get_transformed_assoc_item(
+ ctx: &CompletionContext,
+ assoc_item: ast::AssocItem,
+ impl_def: hir::Impl,
+) -> Option<ast::AssocItem> {
+ let assoc_item = assoc_item.clone_for_update();
+ let trait_ = impl_def.trait_(ctx.db)?;
+ let source_scope = &ctx.sema.scope_for_def(trait_);
+ let target_scope = &ctx.sema.scope(ctx.sema.source(impl_def)?.syntax().value);
+ let transform = PathTransform::trait_impl(
+ target_scope,
+ source_scope,
+ trait_,
+ ctx.sema.source(impl_def)?.value,
+ );
+
+ transform.apply(assoc_item.syntax());
+ if let ast::AssocItem::Fn(func) = &assoc_item {
+ func.remove_attrs_and_docs();