1 //! This modules takes care of rendering various defenitions as completion items.
2 use join_to_string::join;
3 use test_utils::tested_by;
6 use crate::completion::{
7 Completions, CompletionKind, CompletionItemKind, CompletionContext, CompletionItem,
12 pub(crate) fn add_field(
14 ctx: &CompletionContext,
15 field: hir::StructField,
19 CompletionKind::Reference,
21 field.name(ctx.db).to_string(),
23 .kind(CompletionItemKind::Field)
24 .detail(field.ty(ctx.db).subst(substs).to_string())
25 .set_documentation(field.docs(ctx.db))
29 pub(crate) fn add_pos_field(&mut self, ctx: &CompletionContext, field: usize, ty: &hir::Ty) {
30 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), field.to_string())
31 .kind(CompletionItemKind::Field)
32 .detail(ty.to_string())
36 pub(crate) fn add_function(&mut self, ctx: &CompletionContext, func: hir::Function) {
37 let sig = func.signature(ctx.db);
39 let mut builder = CompletionItem::new(
40 CompletionKind::Reference,
42 sig.name().to_string(),
44 .kind(if sig.has_self_param() {
45 CompletionItemKind::Method
47 CompletionItemKind::Function
49 .set_documentation(func.docs(ctx.db))
50 .set_detail(function_item_label(ctx, func));
51 // If not an import, add parenthesis automatically.
52 if ctx.use_item_syntax.is_none() && !ctx.is_call {
53 tested_by!(inserts_parens_for_function_calls);
55 if sig.params().is_empty() || sig.has_self_param() && sig.params().len() == 1 {
56 format!("{}()$0", sig.name())
58 format!("{}($0)", sig.name())
60 builder = builder.insert_snippet(snippet);
65 pub(crate) fn add_enum_variant(&mut self, ctx: &CompletionContext, variant: hir::EnumVariant) {
66 let name = match variant.name(ctx.db) {
70 let detail_types = variant.fields(ctx.db).into_iter().map(|field| field.ty(ctx.db));
71 let detail = join(detail_types).separator(", ").surround_with("(", ")").to_string();
73 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string())
74 .kind(CompletionItemKind::EnumVariant)
75 .set_documentation(variant.docs(ctx.db))
81 fn function_item_label(ctx: &CompletionContext, function: hir::Function) -> Option<String> {
82 let node = function.source(ctx.db).1;
88 use test_utils::covers;
90 use crate::completion::{CompletionKind, completion_item::check_completion};
92 fn check_reference_completion(code: &str, expected_completions: &str) {
93 check_completion(code, expected_completions, CompletionKind::Reference);
97 fn inserts_parens_for_function_calls() {
98 covers!(inserts_parens_for_function_calls);
99 check_reference_completion(
100 "inserts_parens_for_function_calls1",
106 check_reference_completion(
107 "inserts_parens_for_function_calls2",
109 fn with_args(x: i32, y: String) {}
110 fn main() { with_<|> }
113 check_reference_completion(
114 "inserts_parens_for_function_calls3",
128 fn dont_render_function_parens_in_use_item() {
129 check_reference_completion(
130 "dont_render_function_parens_in_use_item",
133 mod m { pub fn foo() {} }
140 fn dont_render_function_parens_if_already_call() {
141 check_reference_completion(
142 "dont_render_function_parens_if_already_call",
151 check_reference_completion(
152 "dont_render_function_parens_if_already_call_assoc_fn",
156 impl Foo { fn new() -> Foo {} }