Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-completion/src/completions/item_list/trait_impl.rs')
| -rw-r--r-- | crates/ide-completion/src/completions/item_list/trait_impl.rs | 122 |
1 files changed, 63 insertions, 59 deletions
diff --git a/crates/ide-completion/src/completions/item_list/trait_impl.rs b/crates/ide-completion/src/completions/item_list/trait_impl.rs index 4072f05a41..c165a32082 100644 --- a/crates/ide-completion/src/completions/item_list/trait_impl.rs +++ b/crates/ide-completion/src/completions/item_list/trait_impl.rs @@ -38,10 +38,14 @@ use ide_db::{ syntax_helpers::prettify_macro_expansion, traits::get_missing_assoc_items, }; use syntax::ast::HasGenericParams; +use syntax::syntax_editor::{Position, SyntaxEditor}; use syntax::{ AstNode, SmolStr, SyntaxElement, SyntaxKind, T, TextRange, ToSmolStr, - ast::{self, HasGenericArgs, HasTypeBounds, edit_in_place::AttrsOwnerEdit, make}, - format_smolstr, ted, + ast::{ + self, HasGenericArgs, HasTypeBounds, + edit::{AstNodeEdit, AttrsOwnerEdit}, + }, + format_smolstr, }; use crate::{ @@ -59,7 +63,7 @@ enum ImplCompletionKind { pub(crate) fn complete_trait_impl_const( acc: &mut Completions, - ctx: &CompletionContext<'_>, + ctx: &CompletionContext<'_, '_>, name: &Option<ast::Name>, ) -> Option<()> { complete_trait_impl_name(acc, ctx, name, ImplCompletionKind::Const) @@ -67,7 +71,7 @@ pub(crate) fn complete_trait_impl_const( pub(crate) fn complete_trait_impl_type_alias( acc: &mut Completions, - ctx: &CompletionContext<'_>, + ctx: &CompletionContext<'_, '_>, name: &Option<ast::Name>, ) -> Option<()> { complete_trait_impl_name(acc, ctx, name, ImplCompletionKind::TypeAlias) @@ -75,7 +79,7 @@ pub(crate) fn complete_trait_impl_type_alias( pub(crate) fn complete_trait_impl_fn( acc: &mut Completions, - ctx: &CompletionContext<'_>, + ctx: &CompletionContext<'_, '_>, name: &Option<ast::Name>, ) -> Option<()> { complete_trait_impl_name(acc, ctx, name, ImplCompletionKind::Fn) @@ -83,7 +87,7 @@ pub(crate) fn complete_trait_impl_fn( fn complete_trait_impl_name( acc: &mut Completions, - ctx: &CompletionContext<'_>, + ctx: &CompletionContext<'_, '_>, name: &Option<ast::Name>, kind: ImplCompletionKind, ) -> Option<()> { @@ -122,7 +126,7 @@ fn complete_trait_impl_name( pub(crate) fn complete_trait_impl_item_by_name( acc: &mut Completions, - ctx: &CompletionContext<'_>, + ctx: &CompletionContext<'_, '_>, path_ctx: &PathCompletionCtx<'_>, name_ref: &Option<ast::NameRef>, impl_: &Option<ast::Impl>, @@ -149,7 +153,7 @@ pub(crate) fn complete_trait_impl_item_by_name( fn complete_trait_impl( acc: &mut Completions, - ctx: &CompletionContext<'_>, + ctx: &CompletionContext<'_, '_>, kind: ImplCompletionKind, replacement_range: TextRange, impl_def: &ast::Impl, @@ -178,7 +182,7 @@ fn complete_trait_impl( fn add_function_impl( acc: &mut Completions, - ctx: &CompletionContext<'_>, + ctx: &CompletionContext<'_, '_>, replacement_range: TextRange, func: hir::Function, impl_def: hir::Impl, @@ -198,7 +202,7 @@ fn add_function_impl( fn add_function_impl_( acc: &mut Completions, - ctx: &CompletionContext<'_>, + ctx: &CompletionContext<'_, '_>, replacement_range: TextRange, func: hir::Function, impl_def: hir::Impl, @@ -233,13 +237,14 @@ fn add_function_impl_( get_transformed_fn(ctx, source.value, impl_def, async_sugaring) { let function_decl = function_declaration(ctx, &transformed_fn, source.file_id.macro_file()); + let ws = if function_decl.contains('\n') { "\n" } else { " " }; match ctx.config.snippet_cap { Some(cap) => { - let snippet = format!("{function_decl} {{\n $0\n}}"); + let snippet = format!("{function_decl}{ws}{{\n $0\n}}"); item.snippet_edit(cap, TextEdit::replace(replacement_range, snippet)); } None => { - let header = format!("{function_decl} {{"); + let header = format!("{function_decl}{ws}{{"); item.text_edit(TextEdit::replace(replacement_range, header)); } }; @@ -257,70 +262,65 @@ enum AsyncSugaring { /// Transform a relevant associated item to inline generics from the impl, remove attrs and docs, etc. fn get_transformed_assoc_item( - ctx: &CompletionContext<'_>, + ctx: &CompletionContext<'_, '_>, assoc_item: ast::AssocItem, impl_def: hir::Impl, ) -> Option<ast::AssocItem> { let trait_ = impl_def.trait_(ctx.db)?; let source_scope = &ctx.sema.scope(assoc_item.syntax())?; - 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, - ); + let impl_source = ctx.sema.source(impl_def)?; + let target_scope = &ctx.sema.scope(impl_source.syntax().value)?; + let transform = + PathTransform::trait_impl(target_scope, source_scope, trait_, impl_source.value); - let assoc_item = assoc_item.clone_for_update(); // FIXME: Paths in nested macros are not handled well. See // `macro_generated_assoc_item2` test. let assoc_item = ast::AssocItem::cast(transform.apply(assoc_item.syntax()))?; - assoc_item.remove_attrs_and_docs(); - Some(assoc_item) + let (editor, assoc_item) = SyntaxEditor::with_ast_node(&assoc_item); + assoc_item.remove_attrs_and_docs(&editor); + ast::AssocItem::cast(editor.finish().new_root().clone()) } /// Transform a relevant associated item to inline generics from the impl, remove attrs and docs, etc. fn get_transformed_fn( - ctx: &CompletionContext<'_>, + ctx: &CompletionContext<'_, '_>, fn_: ast::Fn, impl_def: hir::Impl, async_: AsyncSugaring, ) -> Option<ast::Fn> { let trait_ = impl_def.trait_(ctx.db)?; let source_scope = &ctx.sema.scope(fn_.syntax())?; - 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, - ); + let impl_source = ctx.sema.source(impl_def)?; + let target_scope = &ctx.sema.scope(impl_source.syntax().value)?; + let transform = + PathTransform::trait_impl(target_scope, source_scope, trait_, impl_source.value); - let fn_ = fn_.clone_for_update(); + let fn_ = fn_.reset_indent(); // FIXME: Paths in nested macros are not handled well. See // `macro_generated_assoc_item2` test. let fn_ = ast::Fn::cast(transform.apply(fn_.syntax()))?; - fn_.remove_attrs_and_docs(); + let (editor, fn_) = SyntaxEditor::with_ast_node(&fn_); + let factory = editor.make(); + fn_.remove_attrs_and_docs(&editor); match async_ { AsyncSugaring::Desugar => { match fn_.ret_type() { Some(ret_ty) => { let ty = ret_ty.ty()?; - ted::replace( + editor.replace( ty.syntax(), - make::ty(&format!("impl Future<Output = {ty}>")) - .syntax() - .clone_for_update(), + factory.ty(&format!("impl Future<Output = {ty}>")).syntax(), + ); + } + None => { + let ret_type = factory.ret_type(factory.ty("impl Future<Output = ()>")); + editor.insert_with_whitespace( + Position::after(fn_.param_list()?.syntax()), + ret_type.syntax(), ); } - None => ted::append_child( - fn_.param_list()?.syntax(), - make::ret_type(make::ty("impl Future<Output = ()>")) - .syntax() - .clone_for_update(), - ), } - fn_.async_token().unwrap().detach(); + editor.delete(fn_.async_token()?); } AsyncSugaring::Resugar => { let ty = fn_.ret_type()?.ty()?; @@ -347,23 +347,26 @@ fn get_transformed_fn( if let ast::Type::TupleType(ty) = &output && ty.fields().next().is_none() { - ted::remove(fn_.ret_type()?.syntax()); + editor.delete(fn_.ret_type()?.syntax()); } else { - ted::replace(ty.syntax(), output.syntax()); + editor.replace(ty.syntax(), output.syntax()); } } _ => (), } - ted::prepend_child(fn_.syntax(), make::token(T![async])); + editor.insert_with_whitespace( + Position::first_child_of(fn_.syntax()), + factory.token(T![async]), + ); } AsyncSugaring::Async | AsyncSugaring::Plain => (), } - Some(fn_) + ast::Fn::cast(editor.finish().new_root().clone()) } fn add_type_alias_impl( acc: &mut Completions, - ctx: &CompletionContext<'_>, + ctx: &CompletionContext<'_, '_>, replacement_range: TextRange, type_alias: hir::TypeAlias, impl_def: hir::Impl, @@ -444,7 +447,7 @@ fn add_type_alias_impl( fn add_const_impl( acc: &mut Completions, - ctx: &CompletionContext<'_>, + ctx: &CompletionContext<'_, '_>, replacement_range: TextRange, const_: hir::Const, impl_def: hir::Impl, @@ -486,13 +489,13 @@ fn add_const_impl( } fn make_const_compl_syntax( - ctx: &CompletionContext<'_>, + ctx: &CompletionContext<'_, '_>, const_: &ast::Const, macro_file: Option<MacroCallId>, ) -> SmolStr { let const_ = if let Some(macro_file) = macro_file { let span_map = ctx.db.expansion_span_map(macro_file); - prettify_macro_expansion(ctx.db, const_.syntax().clone(), &span_map, ctx.krate.into()) + prettify_macro_expansion(ctx.db, const_.syntax().clone(), span_map, ctx.krate.into()) } else { const_.syntax().clone() }; @@ -514,13 +517,13 @@ fn make_const_compl_syntax( } fn function_declaration( - ctx: &CompletionContext<'_>, + ctx: &CompletionContext<'_, '_>, node: &ast::Fn, macro_file: Option<MacroCallId>, ) -> String { let node = if let Some(macro_file) = macro_file { let span_map = ctx.db.expansion_span_map(macro_file); - prettify_macro_expansion(ctx.db, node.syntax().clone(), &span_map, ctx.krate.into()) + prettify_macro_expansion(ctx.db, node.syntax().clone(), span_map, ctx.krate.into()) } else { node.syntax().clone() }; @@ -1256,7 +1259,7 @@ trait SomeTrait<T> {} trait Foo<T> { fn function() - where Self: SomeTrait<T>; + where Self: SomeTrait<T>; } struct Bar; @@ -1269,13 +1272,14 @@ trait SomeTrait<T> {} trait Foo<T> { fn function() - where Self: SomeTrait<T>; + where Self: SomeTrait<T>; } struct Bar; impl Foo<u32> for Bar { fn function() - where Self: SomeTrait<u32> { +where Self: SomeTrait<u32> +{ $0 } } @@ -1356,7 +1360,7 @@ noop! { struct Test; impl Foo for Test { - fn foo(&mut self,bar:i64,baz: &mut u32) -> Result<(),u32> { + fn foo(&mut self,bar: i64,baz: &mut u32) -> Result<(),u32> { $0 } } @@ -1740,7 +1744,7 @@ impl Trait for () { me fn bar(..) me fn baz(..) me fn foo(..) - md proc_macros + md proc_macros:: kw crate:: kw self:: "#]], |