Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-completion/src/render.rs')
| -rw-r--r-- | crates/ide-completion/src/render.rs | 108 |
1 files changed, 102 insertions, 6 deletions
diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs index d77e793295..b946441991 100644 --- a/crates/ide-completion/src/render.rs +++ b/crates/ide-completion/src/render.rs @@ -220,13 +220,15 @@ pub(crate) fn render_tuple_field( pub(crate) fn render_type_inference( ty_string: String, ctx: &CompletionContext<'_>, + path_ctx: &PathCompletionCtx<'_>, ) -> CompletionItem { let mut builder = CompletionItem::new( CompletionItemKind::InferredType, ctx.source_range(), - ty_string, + &ty_string, ctx.edition, ); + adds_ret_type_arrow(ctx, path_ctx, &mut builder, ty_string); builder.set_relevance(CompletionRelevance { type_match: Some(CompletionRelevanceTypeMatch::Exact), exact_name_match: true, @@ -425,11 +427,10 @@ fn render_resolution_path( let config = completion.config; let requires_import = import_to_add.is_some(); - let name = local_name.display_no_db(ctx.completion.edition).to_smolstr(); + let name = local_name.display(db, completion.edition).to_smolstr(); let mut item = render_resolution_simple_(ctx, &local_name, import_to_add, resolution); - if local_name.needs_escape(completion.edition) { - item.insert_text(local_name.display_no_db(completion.edition).to_smolstr()); - } + let mut insert_text = name.clone(); + // Add `<>` for generic types let type_path_no_ty_args = matches!( path_ctx, @@ -446,12 +447,14 @@ fn render_resolution_path( if has_non_default_type_params { cov_mark::hit!(inserts_angle_brackets_for_generics); + insert_text = format_smolstr!("{insert_text}<$0>"); item.lookup_by(name.clone()) .label(SmolStr::from_iter([&name, "<…>"])) .trigger_call_info() - .insert_snippet(cap, format!("{}<$0>", local_name.display(db, completion.edition))); + .insert_snippet(cap, ""); // set is snippet } } + adds_ret_type_arrow(completion, path_ctx, &mut item, insert_text.into()); let mut set_item_relevance = |ty: Type<'_>| { if !ty.is_unknown() { @@ -577,6 +580,48 @@ fn scope_def_is_deprecated(ctx: &RenderContext<'_>, resolution: ScopeDef) -> boo } } +pub(crate) fn render_type_keyword_snippet( + ctx: &CompletionContext<'_>, + path_ctx: &PathCompletionCtx<'_>, + label: &str, + snippet: &str, +) -> Builder { + let source_range = ctx.source_range(); + let mut item = + CompletionItem::new(CompletionItemKind::Keyword, source_range, label, ctx.edition); + + let insert_text = if !snippet.contains('$') { + item.insert_text(snippet); + snippet + } else if let Some(cap) = ctx.config.snippet_cap { + item.insert_snippet(cap, snippet); + snippet + } else { + label + }; + + adds_ret_type_arrow(ctx, path_ctx, &mut item, insert_text.to_owned()); + item +} + +fn adds_ret_type_arrow( + ctx: &CompletionContext<'_>, + path_ctx: &PathCompletionCtx<'_>, + item: &mut Builder, + insert_text: String, +) { + if let Some((arrow, at)) = path_ctx.required_thin_arrow() { + let mut edit = TextEdit::builder(); + + edit.insert(at, arrow.to_owned()); + edit.replace(ctx.source_range(), insert_text); + + item.text_edit(edit.finish()).adds_text(SmolStr::new_static(arrow)); + } else { + item.insert_text(insert_text); + } +} + // FIXME: This checks types without possible coercions which some completions might want to do fn match_types( ctx: &CompletionContext<'_>, @@ -3045,6 +3090,57 @@ fn main() { } #[test] + fn enum_variant_name_exact_match_is_high_priority() { + check_relevance( + r#" +struct Other; +struct String; +enum Foo { + String($0) +} + "#, + expect![[r#" + st String String [name] + en Foo Foo [] + st Other Other [] + sp Self Foo [] + "#]], + ); + + check_relevance( + r#" +struct Other; +struct String; +enum Foo { + String(String, $0) +} + "#, + expect![[r#" + en Foo Foo [] + st Other Other [] + sp Self Foo [] + st String String [] + "#]], + ); + + check_relevance( + r#" +struct Other; +struct Vec<T>(T); +enum Foo { + Vec(Vec<$0>) +} + "#, + expect![[r#" + en Foo Foo [] + st Other Other [] + sp Self Foo [] + st Vec<…> Vec<{unknown}> [] + "#]], + ); + } + + #[test] fn postfix_inexact_match_is_low_priority() { cov_mark::check!(postfix_inexact_match_is_low_priority); check_relevance_for_kinds( |