1pub(crate) mod const_;
5pub(crate) mod function;
6pub(crate) mod literal;
7pub(crate) mod macro_;
8pub(crate) mod pattern;
9pub(crate) mod type_alias;
10pub(crate) mod union_literal;
11pub(crate) mod variant;
12
13use hir::{AsAssocItem, HasAttrs, HirDisplay, ModuleDef, ScopeDef, Type};
14use ide_db::text_edit::TextEdit;
15use ide_db::{
16 RootDatabase, SnippetCap, SymbolKind,
17 documentation::{Documentation, HasDocs},
18 helpers::item_name,
19 imports::import_assets::LocatedImport,
20};
21use syntax::{AstNode, SmolStr, SyntaxKind, TextRange, ToSmolStr, ast, format_smolstr};
22
23use crate::{
24 CompletionContext, CompletionItem, CompletionItemKind, CompletionItemRefMode,
25 CompletionRelevance,
26 context::{DotAccess, DotAccessKind, PathCompletionCtx, PathKind, PatternContext},
27 item::{Builder, CompletionRelevanceTypeMatch},
28 render::{
29 function::render_fn,
30 literal::render_variant_lit,
31 macro_::{render_macro, render_macro_pat},
32 },
33};
34#[derive(Debug, Clone)]
36pub(crate) struct RenderContext<'a> {
37 completion: &'a CompletionContext<'a>,
38 is_private_editable: bool,
39 import_to_add: Option<LocatedImport>,
40 doc_aliases: Vec<SmolStr>,
41}
42
43impl<'a> RenderContext<'a> {
44 pub(crate) fn new(completion: &'a CompletionContext<'a>) -> RenderContext<'a> {
45 RenderContext {
46 completion,
47 is_private_editable: false,
48 import_to_add: None,
49 doc_aliases: vec![],
50 }
51 }
52
53 pub(crate) fn private_editable(mut self, private_editable: bool) -> Self {
54 self.is_private_editable = private_editable;
55 self
56 }
57
58 pub(crate) fn import_to_add(mut self, import_to_add: Option<LocatedImport>) -> Self {
59 self.import_to_add = import_to_add;
60 self
61 }
62
63 pub(crate) fn doc_aliases(mut self, doc_aliases: Vec<SmolStr>) -> Self {
64 self.doc_aliases = doc_aliases;
65 self
66 }
67
68 fn snippet_cap(&self) -> Option<SnippetCap> {
69 self.completion.config.snippet_cap
70 }
71
72 fn db(&self) -> &'a RootDatabase {
73 self.completion.db
74 }
75
76 fn source_range(&self) -> TextRange {
77 self.completion.source_range()
78 }
79
80 fn completion_relevance(&self) -> CompletionRelevance {
81 CompletionRelevance {
82 is_private_editable: self.is_private_editable,
83 requires_import: self.import_to_add.is_some(),
84 ..Default::default()
85 }
86 }
87
88 fn is_immediately_after_macro_bang(&self) -> bool {
89 self.completion.token.kind() == SyntaxKind::BANG
90 && self.completion.token.parent().is_some_and(|it| it.kind() == SyntaxKind::MACRO_CALL)
91 }
92
93 fn is_deprecated(&self, def: impl HasAttrs) -> bool {
94 def.attrs(self.db()).is_deprecated()
95 }
96
97 fn is_deprecated_assoc_item(&self, as_assoc_item: impl AsAssocItem) -> bool {
98 let db = self.db();
99 let assoc = match as_assoc_item.as_assoc_item(db) {
100 Some(assoc) => assoc,
101 None => return false,
102 };
103
104 let is_assoc_deprecated = match assoc {
105 hir::AssocItem::Function(it) => self.is_deprecated(it),
106 hir::AssocItem::Const(it) => self.is_deprecated(it),
107 hir::AssocItem::TypeAlias(it) => self.is_deprecated(it),
108 };
109 is_assoc_deprecated
110 || assoc
111 .container_or_implemented_trait(db)
112 .map(|trait_| self.is_deprecated(trait_))
113 .unwrap_or(false)
114 }
115
116 fn docs(&self, def: impl HasDocs) -> Option<Documentation<'a>> {
118 def.docs(self.db())
119 }
120}
121
122pub(crate) fn render_field(
123 ctx: RenderContext<'_>,
124 dot_access: &DotAccess<'_>,
125 receiver: Option<SmolStr>,
126 field: hir::Field,
127 ty: &hir::Type<'_>,
128) -> CompletionItem {
129 let db = ctx.db();
130 let is_deprecated = ctx.is_deprecated(field);
131 let name = field.name(db);
132 let (name, escaped_name) =
133 (name.as_str().to_smolstr(), name.display_no_db(ctx.completion.edition).to_smolstr());
134 let mut item = CompletionItem::new(
135 SymbolKind::Field,
136 ctx.source_range(),
137 field_with_receiver(receiver.as_deref(), &name),
138 ctx.completion.edition,
139 );
140 item.set_relevance(CompletionRelevance {
141 type_match: compute_type_match(ctx.completion, ty),
142 exact_name_match: compute_exact_name_match(ctx.completion, &name),
143 is_skipping_completion: receiver.is_some(),
144 ..CompletionRelevance::default()
145 });
146 item.detail(ty.display(db, ctx.completion.display_target).to_string())
147 .set_documentation(field.docs(db))
148 .set_deprecated(is_deprecated)
149 .lookup_by(name);
150
151 let is_field_access = matches!(dot_access.kind, DotAccessKind::Field { .. });
152 if !is_field_access || ty.is_fn() || ty.is_closure() {
153 let mut builder = TextEdit::builder();
154 builder.replace(
159 ctx.source_range(),
160 field_with_receiver(receiver.as_deref(), &escaped_name).into(),
161 );
162
163 let expected_fn_type =
164 ctx.completion.expected_type.as_ref().is_some_and(|ty| ty.is_fn() || ty.is_closure());
165
166 if !expected_fn_type
167 && let Some(receiver) = &dot_access.receiver
168 && let Some(receiver) = ctx.completion.sema.original_ast_node(receiver.clone())
169 {
170 builder.insert(receiver.syntax().text_range().start(), "(".to_owned());
171 builder.insert(ctx.source_range().end(), ")".to_owned());
172
173 let is_parens_needed = !matches!(dot_access.kind, DotAccessKind::Method);
174
175 if is_parens_needed {
176 builder.insert(ctx.source_range().end(), "()".to_owned());
177 }
178 }
179
180 item.text_edit(builder.finish());
181 } else {
182 item.insert_text(field_with_receiver(receiver.as_deref(), &escaped_name));
183 }
184 if let Some(receiver) = &dot_access.receiver
185 && let Some(original) = ctx.completion.sema.original_ast_node(receiver.clone())
186 && let Some(ref_mode) = compute_ref_match(ctx.completion, ty)
187 {
188 item.ref_match(ref_mode, original.syntax().text_range().start());
189 }
190 item.doc_aliases(ctx.doc_aliases);
191 item.build(db)
192}
193
194fn field_with_receiver(receiver: Option<&str>, field_name: &str) -> SmolStr {
195 receiver
196 .map_or_else(|| field_name.into(), |receiver| format_smolstr!("{}.{field_name}", receiver))
197}
198
199pub(crate) fn render_tuple_field(
200 ctx: RenderContext<'_>,
201 receiver: Option<SmolStr>,
202 field: usize,
203 ty: &hir::Type<'_>,
204) -> CompletionItem {
205 let mut item = CompletionItem::new(
206 SymbolKind::Field,
207 ctx.source_range(),
208 field_with_receiver(receiver.as_deref(), &field.to_string()),
209 ctx.completion.edition,
210 );
211 item.detail(ty.display(ctx.db(), ctx.completion.display_target).to_string())
212 .lookup_by(field.to_string());
213 item.set_relevance(CompletionRelevance {
214 is_skipping_completion: receiver.is_some(),
215 ..ctx.completion_relevance()
216 });
217 item.build(ctx.db())
218}
219
220pub(crate) fn render_type_inference(
221 ty_string: String,
222 ctx: &CompletionContext<'_>,
223) -> CompletionItem {
224 let mut builder = CompletionItem::new(
225 CompletionItemKind::InferredType,
226 ctx.source_range(),
227 ty_string,
228 ctx.edition,
229 );
230 builder.set_relevance(CompletionRelevance {
231 type_match: Some(CompletionRelevanceTypeMatch::Exact),
232 exact_name_match: true,
233 ..Default::default()
234 });
235 builder.build(ctx.db)
236}
237
238pub(crate) fn render_path_resolution(
239 ctx: RenderContext<'_>,
240 path_ctx: &PathCompletionCtx<'_>,
241 local_name: hir::Name,
242 resolution: ScopeDef,
243) -> Builder {
244 render_resolution_path(ctx, path_ctx, local_name, None, resolution)
245}
246
247pub(crate) fn render_pattern_resolution(
248 ctx: RenderContext<'_>,
249 pattern_ctx: &PatternContext,
250 local_name: hir::Name,
251 resolution: ScopeDef,
252) -> Builder {
253 render_resolution_pat(ctx, pattern_ctx, local_name, None, resolution)
254}
255
256pub(crate) fn render_resolution_with_import(
257 ctx: RenderContext<'_>,
258 path_ctx: &PathCompletionCtx<'_>,
259 import_edit: LocatedImport,
260) -> Option<Builder> {
261 let resolution = ScopeDef::from(import_edit.original_item);
262 let local_name = get_import_name(resolution, &ctx, &import_edit)?;
263 let doc_aliases = ctx.completion.doc_aliases_in_scope(resolution);
265 let ctx = ctx.doc_aliases(doc_aliases);
266 Some(render_resolution_path(ctx, path_ctx, local_name, Some(import_edit), resolution))
267}
268
269pub(crate) fn render_resolution_with_import_pat(
270 ctx: RenderContext<'_>,
271 pattern_ctx: &PatternContext,
272 import_edit: LocatedImport,
273) -> Option<Builder> {
274 let resolution = ScopeDef::from(import_edit.original_item);
275 let local_name = get_import_name(resolution, &ctx, &import_edit)?;
276 Some(render_resolution_pat(ctx, pattern_ctx, local_name, Some(import_edit), resolution))
277}
278
279pub(crate) fn render_expr(
280 ctx: &CompletionContext<'_>,
281 expr: &hir::term_search::Expr<'_>,
282) -> Option<Builder> {
283 let mut i = 1;
284 let mut snippet_formatter = |ty: &hir::Type<'_>| {
285 let arg_name = ty
286 .as_adt()
287 .map(|adt| stdx::to_lower_snake_case(adt.name(ctx.db).as_str()))
288 .unwrap_or_else(|| String::from("_"));
289 let res = format!("${{{i}:{arg_name}}}");
290 i += 1;
291 res
292 };
293
294 let mut label_formatter = |ty: &hir::Type<'_>| {
295 ty.as_adt()
296 .map(|adt| stdx::to_lower_snake_case(adt.name(ctx.db).as_str()))
297 .unwrap_or_else(|| String::from("..."))
298 };
299
300 let cfg = ctx.config.find_path_config(ctx.is_nightly);
301
302 let label =
303 expr.gen_source_code(&ctx.scope, &mut label_formatter, cfg, ctx.display_target).ok()?;
304
305 let source_range = match ctx.original_token.parent() {
306 Some(node) => match node.ancestors().find_map(ast::Path::cast) {
307 Some(path) => path.syntax().text_range(),
308 None => node.text_range(),
309 },
310 None => ctx.source_range(),
311 };
312
313 let mut item =
314 CompletionItem::new(CompletionItemKind::Expression, source_range, label, ctx.edition);
315
316 let snippet = format!(
317 "{}$0",
318 expr.gen_source_code(&ctx.scope, &mut snippet_formatter, cfg, ctx.display_target).ok()?
319 );
320 let edit = TextEdit::replace(source_range, snippet);
321 item.snippet_edit(ctx.config.snippet_cap?, edit);
322 item.documentation(Documentation::new_owned(String::from(
323 "Autogenerated expression by term search",
324 )));
325 item.set_relevance(crate::CompletionRelevance {
326 type_match: compute_type_match(ctx, &expr.ty(ctx.db)),
327 ..Default::default()
328 });
329 for trait_ in expr.traits_used(ctx.db) {
330 let trait_item = hir::ItemInNs::from(hir::ModuleDef::from(trait_));
331 let Some(path) = ctx.module.find_path(ctx.db, trait_item, cfg) else {
332 continue;
333 };
334
335 item.add_import(LocatedImport::new_no_completion(path, trait_item, trait_item));
336 }
337
338 Some(item)
339}
340
341fn get_import_name(
342 resolution: ScopeDef,
343 ctx: &RenderContext<'_>,
344 import_edit: &LocatedImport,
345) -> Option<hir::Name> {
346 if import_edit.item_to_import == import_edit.original_item {
353 import_edit.import_path.segments().last().cloned()
354 } else {
355 scope_def_to_name(resolution, ctx, import_edit)
356 }
357}
358
359fn scope_def_to_name(
360 resolution: ScopeDef,
361 ctx: &RenderContext<'_>,
362 import_edit: &LocatedImport,
363) -> Option<hir::Name> {
364 Some(match resolution {
365 ScopeDef::ModuleDef(hir::ModuleDef::Function(f)) => f.name(ctx.completion.db),
366 ScopeDef::ModuleDef(hir::ModuleDef::Const(c)) => c.name(ctx.completion.db)?,
367 ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(t)) => t.name(ctx.completion.db),
368 _ => item_name(ctx.db(), import_edit.original_item)?,
369 })
370}
371
372fn render_resolution_pat(
373 ctx: RenderContext<'_>,
374 pattern_ctx: &PatternContext,
375 local_name: hir::Name,
376 import_to_add: Option<LocatedImport>,
377 resolution: ScopeDef,
378) -> Builder {
379 let _p = tracing::info_span!("render_resolution_pat").entered();
380 use hir::ModuleDef::*;
381
382 if let ScopeDef::ModuleDef(Macro(mac)) = resolution {
383 let ctx = ctx.import_to_add(import_to_add);
384 render_macro_pat(ctx, pattern_ctx, local_name, mac)
385 } else {
386 render_resolution_simple_(ctx, &local_name, import_to_add, resolution)
387 }
388}
389
390fn render_resolution_path(
391 ctx: RenderContext<'_>,
392 path_ctx: &PathCompletionCtx<'_>,
393 local_name: hir::Name,
394 import_to_add: Option<LocatedImport>,
395 resolution: ScopeDef,
396) -> Builder {
397 let _p = tracing::info_span!("render_resolution_path").entered();
398 use hir::ModuleDef::*;
399
400 let krate = ctx.completion.display_target;
401
402 match resolution {
403 ScopeDef::ModuleDef(Macro(mac)) => {
404 let ctx = ctx.import_to_add(import_to_add);
405 return render_macro(ctx, path_ctx, local_name, mac);
406 }
407 ScopeDef::ModuleDef(Function(func)) => {
408 let ctx = ctx.import_to_add(import_to_add);
409 return render_fn(ctx, path_ctx, Some(local_name), func);
410 }
411 ScopeDef::ModuleDef(Variant(var)) => {
412 let ctx = ctx.clone().import_to_add(import_to_add.clone());
413 if let Some(item) =
414 render_variant_lit(ctx, path_ctx, Some(local_name.clone()), var, None)
415 {
416 return item;
417 }
418 }
419 _ => (),
420 }
421
422 let completion = ctx.completion;
423 let cap = ctx.snippet_cap();
424 let db = completion.db;
425 let config = completion.config;
426 let requires_import = import_to_add.is_some();
427
428 let name = local_name.display_no_db(ctx.completion.edition).to_smolstr();
429 let mut item = render_resolution_simple_(ctx, &local_name, import_to_add, resolution);
430 if local_name.needs_escape(completion.edition) {
431 item.insert_text(local_name.display_no_db(completion.edition).to_smolstr());
432 }
433 let type_path_no_ty_args = matches!(
435 path_ctx,
436 PathCompletionCtx { kind: PathKind::Type { .. }, has_type_args: false, .. }
437 ) && config.callable.is_some();
438 if type_path_no_ty_args && let Some(cap) = cap {
439 let has_non_default_type_params = match resolution {
440 ScopeDef::ModuleDef(hir::ModuleDef::Adt(it)) => it.has_non_default_type_params(db),
441 ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(it)) => {
442 it.has_non_default_type_params(db)
443 }
444 _ => false,
445 };
446
447 if has_non_default_type_params {
448 cov_mark::hit!(inserts_angle_brackets_for_generics);
449 item.lookup_by(name.clone())
450 .label(SmolStr::from_iter([&name, "<…>"]))
451 .trigger_call_info()
452 .insert_snippet(cap, format!("{}<$0>", local_name.display(db, completion.edition)));
453 }
454 }
455
456 let mut set_item_relevance = |ty: Type<'_>| {
457 if !ty.is_unknown() {
458 item.detail(ty.display(db, krate).to_string());
459 }
460
461 item.set_relevance(CompletionRelevance {
462 type_match: compute_type_match(completion, &ty),
463 exact_name_match: compute_exact_name_match(completion, &name),
464 is_local: matches!(resolution, ScopeDef::Local(_)),
465 requires_import,
466 ..CompletionRelevance::default()
467 });
468
469 path_ref_match(completion, path_ctx, &ty, &mut item);
470 };
471
472 match resolution {
473 ScopeDef::Local(local) => set_item_relevance(local.ty(db)),
474 ScopeDef::ModuleDef(ModuleDef::Adt(adt)) | ScopeDef::AdtSelfType(adt) => {
475 set_item_relevance(adt.ty(db))
476 }
477 ScopeDef::ModuleDef(
479 ModuleDef::Function(_) | ModuleDef::Variant(_) | ModuleDef::Macro(_),
480 ) => (),
481 ScopeDef::ModuleDef(ModuleDef::Const(konst)) => set_item_relevance(konst.ty(db)),
482 ScopeDef::ModuleDef(ModuleDef::Static(stat)) => set_item_relevance(stat.ty(db)),
483 ScopeDef::ModuleDef(ModuleDef::BuiltinType(bt)) => set_item_relevance(bt.ty(db)),
484 ScopeDef::ImplSelfType(imp) => set_item_relevance(imp.self_ty(db)),
485 ScopeDef::GenericParam(_)
486 | ScopeDef::Label(_)
487 | ScopeDef::Unknown
488 | ScopeDef::ModuleDef(
489 ModuleDef::Trait(_) | ModuleDef::Module(_) | ModuleDef::TypeAlias(_),
490 ) => (),
491 };
492
493 item
494}
495
496fn render_resolution_simple_(
497 ctx: RenderContext<'_>,
498 local_name: &hir::Name,
499 import_to_add: Option<LocatedImport>,
500 resolution: ScopeDef,
501) -> Builder {
502 let _p = tracing::info_span!("render_resolution_simple_").entered();
503
504 let db = ctx.db();
505 let ctx = ctx.import_to_add(import_to_add);
506 let kind = res_to_kind(resolution);
507
508 let mut item = CompletionItem::new(
509 kind,
510 ctx.source_range(),
511 local_name.as_str().to_smolstr(),
512 ctx.completion.edition,
513 );
514 item.set_relevance(ctx.completion_relevance())
515 .set_documentation(scope_def_docs(db, resolution))
516 .set_deprecated(scope_def_is_deprecated(&ctx, resolution));
517
518 if let Some(import_to_add) = ctx.import_to_add {
519 item.add_import(import_to_add);
520 }
521
522 item.doc_aliases(ctx.doc_aliases);
523 item
524}
525
526fn res_to_kind(resolution: ScopeDef) -> CompletionItemKind {
527 use hir::ModuleDef::*;
528 match resolution {
529 ScopeDef::Unknown => CompletionItemKind::UnresolvedReference,
530 ScopeDef::ModuleDef(Function(_)) => CompletionItemKind::SymbolKind(SymbolKind::Function),
531 ScopeDef::ModuleDef(Variant(_)) => CompletionItemKind::SymbolKind(SymbolKind::Variant),
532 ScopeDef::ModuleDef(Macro(_)) => CompletionItemKind::SymbolKind(SymbolKind::Macro),
533 ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::SymbolKind(SymbolKind::Module),
534 ScopeDef::ModuleDef(Adt(adt)) => CompletionItemKind::SymbolKind(match adt {
535 hir::Adt::Struct(_) => SymbolKind::Struct,
536 hir::Adt::Union(_) => SymbolKind::Union,
537 hir::Adt::Enum(_) => SymbolKind::Enum,
538 }),
539 ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::SymbolKind(SymbolKind::Const),
540 ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::SymbolKind(SymbolKind::Static),
541 ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::SymbolKind(SymbolKind::Trait),
542 ScopeDef::ModuleDef(TypeAlias(..)) => CompletionItemKind::SymbolKind(SymbolKind::TypeAlias),
543 ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType,
544 ScopeDef::GenericParam(param) => CompletionItemKind::SymbolKind(match param {
545 hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam,
546 hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam,
547 hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam,
548 }),
549 ScopeDef::Local(..) => CompletionItemKind::SymbolKind(SymbolKind::Local),
550 ScopeDef::Label(..) => CompletionItemKind::SymbolKind(SymbolKind::Label),
551 ScopeDef::AdtSelfType(..) | ScopeDef::ImplSelfType(..) => {
552 CompletionItemKind::SymbolKind(SymbolKind::SelfParam)
553 }
554 }
555}
556
557fn scope_def_docs(db: &RootDatabase, resolution: ScopeDef) -> Option<Documentation<'_>> {
558 use hir::ModuleDef::*;
559 match resolution {
560 ScopeDef::ModuleDef(Module(it)) => it.docs(db),
561 ScopeDef::ModuleDef(Adt(it)) => it.docs(db),
562 ScopeDef::ModuleDef(Variant(it)) => it.docs(db),
563 ScopeDef::ModuleDef(Const(it)) => it.docs(db),
564 ScopeDef::ModuleDef(Static(it)) => it.docs(db),
565 ScopeDef::ModuleDef(Trait(it)) => it.docs(db),
566 ScopeDef::ModuleDef(TypeAlias(it)) => it.docs(db),
567 _ => None,
568 }
569}
570
571fn scope_def_is_deprecated(ctx: &RenderContext<'_>, resolution: ScopeDef) -> bool {
572 match resolution {
573 ScopeDef::ModuleDef(it) => ctx.is_deprecated_assoc_item(it),
574 ScopeDef::GenericParam(it) => ctx.is_deprecated(it),
575 ScopeDef::AdtSelfType(it) => ctx.is_deprecated(it),
576 _ => false,
577 }
578}
579
580fn match_types(
582 ctx: &CompletionContext<'_>,
583 ty1: &hir::Type<'_>,
584 ty2: &hir::Type<'_>,
585) -> Option<CompletionRelevanceTypeMatch> {
586 if ty1 == ty2 {
587 Some(CompletionRelevanceTypeMatch::Exact)
588 } else if ty1.could_unify_with(ctx.db, ty2) {
589 Some(CompletionRelevanceTypeMatch::CouldUnify)
590 } else {
591 None
592 }
593}
594
595fn compute_type_match(
596 ctx: &CompletionContext<'_>,
597 completion_ty: &hir::Type<'_>,
598) -> Option<CompletionRelevanceTypeMatch> {
599 let expected_type = ctx.expected_type.as_ref()?;
600
601 if expected_type.is_unit() {
604 return None;
605 }
606
607 if completion_ty.is_mutable_reference()
609 && let Some(expected_type) = expected_type.remove_ref()
610 && let Some(completion_ty) = completion_ty.remove_ref()
611 {
612 return match_types(ctx, &expected_type, &completion_ty);
613 }
614
615 match_types(ctx, expected_type, completion_ty)
616}
617
618fn compute_exact_name_match(ctx: &CompletionContext<'_>, completion_name: &str) -> bool {
619 ctx.expected_name.as_ref().is_some_and(|name| name.text() == completion_name)
620}
621
622fn compute_ref_match(
623 ctx: &CompletionContext<'_>,
624 completion_ty: &hir::Type<'_>,
625) -> Option<CompletionItemRefMode> {
626 let expected_type = ctx.expected_type.as_ref()?;
627 let expected_without_ref = expected_type.remove_ref();
628 let completion_without_ref = completion_ty.remove_ref();
629 if expected_type.could_unify_with(ctx.db, completion_ty) {
630 return None;
631 }
632 if let Some(expected_without_ref) = &expected_without_ref
633 && completion_without_ref.is_none()
634 && completion_ty.autoderef(ctx.db).any(|ty| ty == *expected_without_ref)
635 {
636 cov_mark::hit!(suggest_ref);
637 let mutability = if expected_type.is_mutable_reference() {
638 hir::Mutability::Mut
639 } else {
640 hir::Mutability::Shared
641 };
642 return Some(CompletionItemRefMode::Reference(mutability));
643 }
644
645 if let Some(completion_without_ref) = completion_without_ref
646 && completion_without_ref == *expected_type
647 && completion_without_ref.is_copy(ctx.db)
648 {
649 cov_mark::hit!(suggest_deref);
650 return Some(CompletionItemRefMode::Dereference);
651 }
652
653 None
654}
655
656fn path_ref_match(
657 completion: &CompletionContext<'_>,
658 path_ctx: &PathCompletionCtx<'_>,
659 ty: &hir::Type<'_>,
660 item: &mut Builder,
661) {
662 if let Some(original_path) = &path_ctx.original_path {
663 if let Some(original_path) = completion.sema.original_ast_node(original_path.clone())
665 && let Some(ref_mode) = compute_ref_match(completion, ty)
666 {
667 item.ref_match(ref_mode, original_path.syntax().text_range().start());
668 }
669 } else {
670 if let Some(ref_mode) = compute_ref_match(completion, ty) {
674 item.ref_match(ref_mode, completion.position.offset);
675 }
676 }
677}
678
679#[cfg(test)]
680mod tests {
681 use std::cmp;
682
683 use expect_test::{Expect, expect};
684 use ide_db::SymbolKind;
685 use itertools::Itertools;
686
687 use crate::{
688 CompletionItem, CompletionItemKind, CompletionRelevance, CompletionRelevancePostfixMatch,
689 item::CompletionRelevanceTypeMatch,
690 tests::{TEST_CONFIG, check_edit, do_completion, get_all_items},
691 };
692
693 #[track_caller]
694 fn check(
695 #[rust_analyzer::rust_fixture] ra_fixture: &str,
696 kind: impl Into<CompletionItemKind>,
697 expect: Expect,
698 ) {
699 let actual = do_completion(ra_fixture, kind.into());
700 expect.assert_debug_eq(&actual);
701 }
702
703 #[track_caller]
704 fn check_kinds(
705 #[rust_analyzer::rust_fixture] ra_fixture: &str,
706 kinds: &[CompletionItemKind],
707 expect: Expect,
708 ) {
709 let actual: Vec<_> =
710 kinds.iter().flat_map(|&kind| do_completion(ra_fixture, kind)).collect();
711 expect.assert_debug_eq(&actual);
712 }
713
714 #[track_caller]
715 fn check_function_relevance(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
716 let actual: Vec<_> =
717 do_completion(ra_fixture, CompletionItemKind::SymbolKind(SymbolKind::Method))
718 .into_iter()
719 .map(|item| (item.detail.unwrap_or_default(), item.relevance.function))
720 .collect();
721
722 expect.assert_debug_eq(&actual);
723 }
724
725 #[track_caller]
726 fn check_relevance_for_kinds(
727 #[rust_analyzer::rust_fixture] ra_fixture: &str,
728 kinds: &[CompletionItemKind],
729 expect: Expect,
730 ) {
731 let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
732 actual.retain(|it| kinds.contains(&it.kind));
733 actual.sort_by_key(|it| (cmp::Reverse(it.relevance.score()), it.label.primary.clone()));
734 check_relevance_(actual, expect);
735 }
736
737 #[track_caller]
738 fn check_relevance(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
739 let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
740 actual.retain(|it| it.kind != CompletionItemKind::Snippet);
741 actual.retain(|it| it.kind != CompletionItemKind::Keyword);
742 actual.retain(|it| it.kind != CompletionItemKind::BuiltinType);
743 actual.sort_by_key(|it| (cmp::Reverse(it.relevance.score()), it.label.primary.clone()));
744 check_relevance_(actual, expect);
745 }
746
747 #[track_caller]
748 fn check_relevance_(actual: Vec<CompletionItem>, expect: Expect) {
749 let actual = actual
750 .into_iter()
751 .flat_map(|it| {
752 let mut items = vec![];
753
754 let tag = it.kind.tag();
755 let relevance = display_relevance(it.relevance);
756 items.push(format!(
757 "{tag} {} {} {relevance}\n",
758 it.label.primary,
759 it.label.detail_right.clone().unwrap_or_default(),
760 ));
761
762 if let Some((label, _indel, relevance)) = it.ref_match() {
763 let relevance = display_relevance(relevance);
764
765 items.push(format!("{tag} {label} {relevance}\n"));
766 }
767
768 items
769 })
770 .collect::<String>();
771
772 expect.assert_eq(&actual);
773
774 fn display_relevance(relevance: CompletionRelevance) -> String {
775 let relevance_factors = vec![
776 (relevance.type_match == Some(CompletionRelevanceTypeMatch::Exact), "type"),
777 (
778 relevance.type_match == Some(CompletionRelevanceTypeMatch::CouldUnify),
779 "type_could_unify",
780 ),
781 (relevance.exact_name_match, "name"),
782 (relevance.is_local, "local"),
783 (
784 relevance.postfix_match == Some(CompletionRelevancePostfixMatch::Exact),
785 "snippet",
786 ),
787 (relevance.trait_.is_some_and(|it| it.is_op_method), "op_method"),
788 (relevance.requires_import, "requires_import"),
789 ]
790 .into_iter()
791 .filter_map(|(cond, desc)| if cond { Some(desc) } else { None })
792 .join("+");
793
794 format!("[{relevance_factors}]")
795 }
796 }
797
798 #[test]
799 fn set_struct_type_completion_info() {
800 check_relevance(
801 r#"
802//- /lib.rs crate:dep
803
804pub mod test_mod_b {
805 pub struct Struct {}
806}
807
808pub mod test_mod_a {
809 pub struct Struct {}
810}
811
812//- /main.rs crate:main deps:dep
813
814fn test(input: dep::test_mod_b::Struct) { }
815
816fn main() {
817 test(Struct$0);
818}
819"#,
820 expect![[r#"
821 st dep::test_mod_b::Struct {…} dep::test_mod_b::Struct { } [type_could_unify]
822 ex dep::test_mod_b::Struct { } [type_could_unify]
823 st Struct Struct [type_could_unify+requires_import]
824 md dep []
825 fn main() fn() []
826 fn test(…) fn(Struct) []
827 st Struct Struct [requires_import]
828 "#]],
829 );
830 }
831
832 #[test]
833 fn set_union_type_completion_info() {
834 check_relevance(
835 r#"
836//- /lib.rs crate:dep
837
838pub mod test_mod_b {
839 pub union Union {
840 a: i32,
841 b: i32
842 }
843}
844
845pub mod test_mod_a {
846 pub enum Union {
847 a: i32,
848 b: i32
849 }
850}
851
852//- /main.rs crate:main deps:dep
853
854fn test(input: dep::test_mod_b::Union) { }
855
856fn main() {
857 test(Union$0);
858}
859"#,
860 expect![[r#"
861 un Union Union [type_could_unify+requires_import]
862 md dep []
863 fn main() fn() []
864 fn test(…) fn(Union) []
865 en Union Union [requires_import]
866 "#]],
867 );
868 }
869
870 #[test]
871 fn set_enum_type_completion_info() {
872 check_relevance(
873 r#"
874//- /lib.rs crate:dep
875
876pub mod test_mod_b {
877 pub enum Enum {
878 variant
879 }
880}
881
882pub mod test_mod_a {
883 pub enum Enum {
884 variant
885 }
886}
887
888//- /main.rs crate:main deps:dep
889
890fn test(input: dep::test_mod_b::Enum) { }
891
892fn main() {
893 test(Enum$0);
894}
895"#,
896 expect![[r#"
897 ev dep::test_mod_b::Enum::variant dep::test_mod_b::Enum::variant [type_could_unify]
898 ex dep::test_mod_b::Enum::variant [type_could_unify]
899 en Enum Enum [type_could_unify+requires_import]
900 md dep []
901 fn main() fn() []
902 fn test(…) fn(Enum) []
903 en Enum Enum [requires_import]
904 "#]],
905 );
906 }
907
908 #[test]
909 fn set_enum_variant_type_completion_info() {
910 check_relevance(
911 r#"
912//- /lib.rs crate:dep
913
914pub mod test_mod_b {
915 pub enum Enum {
916 Variant
917 }
918}
919
920pub mod test_mod_a {
921 pub enum Enum {
922 Variant
923 }
924}
925
926//- /main.rs crate:main deps:dep
927
928fn test(input: dep::test_mod_b::Enum) { }
929
930fn main() {
931 test(Variant$0);
932}
933"#,
934 expect![[r#"
935 ev dep::test_mod_b::Enum::Variant dep::test_mod_b::Enum::Variant [type_could_unify]
936 ex dep::test_mod_b::Enum::Variant [type_could_unify]
937 md dep []
938 fn main() fn() []
939 fn test(…) fn(Enum) []
940 "#]],
941 );
942 }
943
944 #[test]
945 fn set_fn_type_completion_info() {
946 check_relevance(
947 r#"
948//- /lib.rs crate:dep
949
950pub mod test_mod_b {
951 pub fn function(j: isize) -> i32 {}
952}
953
954pub mod test_mod_a {
955 pub fn function(i: usize) -> i32 {}
956}
957
958//- /main.rs crate:main deps:dep
959
960fn test(input: fn(usize) -> i32) { }
961
962fn main() {
963 test(function$0);
964}
965"#,
966 expect![[r#"
967 md dep []
968 fn main() fn() []
969 fn test(…) fn(fn(usize) -> i32) []
970 fn function fn(usize) -> i32 [requires_import]
971 fn function(…) fn(isize) -> i32 [requires_import]
972 "#]],
973 );
974 }
975
976 #[test]
977 fn set_const_type_completion_info() {
978 check_relevance(
979 r#"
980//- /lib.rs crate:dep
981
982pub mod test_mod_b {
983 pub const CONST: i32 = 1;
984}
985
986pub mod test_mod_a {
987 pub const CONST: i64 = 2;
988}
989
990//- /main.rs crate:main deps:dep
991
992fn test(input: i32) { }
993
994fn main() {
995 test(CONST$0);
996}
997"#,
998 expect![[r#"
999 ct CONST i32 [type_could_unify+requires_import]
1000 md dep []
1001 fn main() fn() []
1002 fn test(…) fn(i32) []
1003 ct CONST i64 [requires_import]
1004 "#]],
1005 );
1006 }
1007
1008 #[test]
1009 fn set_static_type_completion_info() {
1010 check_relevance(
1011 r#"
1012//- /lib.rs crate:dep
1013
1014pub mod test_mod_b {
1015 pub static STATIC: i32 = 5;
1016}
1017
1018pub mod test_mod_a {
1019 pub static STATIC: i64 = 5;
1020}
1021
1022//- /main.rs crate:main deps:dep
1023
1024fn test(input: i32) { }
1025
1026fn main() {
1027 test(STATIC$0);
1028}
1029"#,
1030 expect![[r#"
1031 sc STATIC i32 [type_could_unify+requires_import]
1032 md dep []
1033 fn main() fn() []
1034 fn test(…) fn(i32) []
1035 sc STATIC i64 [requires_import]
1036 "#]],
1037 );
1038 }
1039
1040 #[test]
1041 fn set_self_type_completion_info_with_params() {
1042 check_relevance(
1043 r#"
1044//- /lib.rs crate:dep
1045pub struct Struct;
1046
1047impl Struct {
1048 pub fn Function(&self, input: i32) -> bool {
1049 false
1050 }
1051}
1052
1053
1054//- /main.rs crate:main deps:dep
1055
1056use dep::Struct;
1057
1058
1059fn test(input: fn(&dep::Struct, i32) -> bool) { }
1060
1061fn main() {
1062 test(Struct::Function$0);
1063}
1064
1065"#,
1066 expect![[r#"
1067 me Function fn(&self, i32) -> bool []
1068 "#]],
1069 );
1070 }
1071
1072 #[test]
1073 fn set_self_type_completion_info() {
1074 check_relevance(
1075 r#"
1076//- /main.rs crate:main
1077
1078struct Struct;
1079
1080impl Struct {
1081fn test(&self) {
1082 func(Self$0);
1083 }
1084}
1085
1086fn func(input: Struct) { }
1087
1088"#,
1089 expect![[r#"
1090 st Self Self [type]
1091 st Struct Struct [type]
1092 sp Self Struct [type]
1093 st Struct Struct [type]
1094 ex Struct [type]
1095 lc self &Struct [local]
1096 fn func(…) fn(Struct) []
1097 me self.test() fn(&self) []
1098 "#]],
1099 );
1100 }
1101
1102 #[test]
1103 fn set_builtin_type_completion_info() {
1104 check_relevance(
1105 r#"
1106//- /main.rs crate:main
1107
1108fn test(input: bool) { }
1109 pub Input: bool = false;
1110
1111fn main() {
1112 let input = false;
1113 let inputbad = 3;
1114 test(inp$0);
1115}
1116"#,
1117 expect![[r#"
1118 lc input bool [type+name+local]
1119 ex false [type]
1120 ex input [type]
1121 ex true [type]
1122 lc inputbad i32 [local]
1123 fn main() fn() []
1124 fn test(…) fn(bool) []
1125 "#]],
1126 );
1127 }
1128
1129 #[test]
1130 fn enum_detail_includes_record_fields() {
1131 check(
1132 r#"
1133enum Foo { Foo { x: i32, y: i32 } }
1134
1135fn main() { Foo::Fo$0 }
1136"#,
1137 SymbolKind::Variant,
1138 expect![[r#"
1139 [
1140 CompletionItem {
1141 label: "Foo {…}",
1142 detail_left: None,
1143 detail_right: Some(
1144 "Foo { x: i32, y: i32 }",
1145 ),
1146 source_range: 54..56,
1147 delete: 54..56,
1148 insert: "Foo { x: ${1:()}, y: ${2:()} }$0",
1149 kind: SymbolKind(
1150 Variant,
1151 ),
1152 lookup: "Foo{}",
1153 detail: "Foo { x: i32, y: i32 }",
1154 relevance: CompletionRelevance {
1155 exact_name_match: false,
1156 type_match: None,
1157 is_local: false,
1158 trait_: None,
1159 is_name_already_imported: false,
1160 requires_import: false,
1161 is_private_editable: false,
1162 postfix_match: None,
1163 function: Some(
1164 CompletionRelevanceFn {
1165 has_params: true,
1166 has_self_param: false,
1167 return_type: DirectConstructor,
1168 },
1169 ),
1170 is_skipping_completion: false,
1171 },
1172 trigger_call_info: true,
1173 },
1174 ]
1175 "#]],
1176 );
1177 }
1178
1179 #[test]
1180 fn enum_detail_includes_tuple_fields() {
1181 check(
1182 r#"
1183enum Foo { Foo (i32, i32) }
1184
1185fn main() { Foo::Fo$0 }
1186"#,
1187 SymbolKind::Variant,
1188 expect![[r#"
1189 [
1190 CompletionItem {
1191 label: "Foo(…)",
1192 detail_left: None,
1193 detail_right: Some(
1194 "Foo(i32, i32)",
1195 ),
1196 source_range: 46..48,
1197 delete: 46..48,
1198 insert: "Foo(${1:()}, ${2:()})$0",
1199 kind: SymbolKind(
1200 Variant,
1201 ),
1202 lookup: "Foo()",
1203 detail: "Foo(i32, i32)",
1204 relevance: CompletionRelevance {
1205 exact_name_match: false,
1206 type_match: None,
1207 is_local: false,
1208 trait_: None,
1209 is_name_already_imported: false,
1210 requires_import: false,
1211 is_private_editable: false,
1212 postfix_match: None,
1213 function: Some(
1214 CompletionRelevanceFn {
1215 has_params: true,
1216 has_self_param: false,
1217 return_type: DirectConstructor,
1218 },
1219 ),
1220 is_skipping_completion: false,
1221 },
1222 trigger_call_info: true,
1223 },
1224 ]
1225 "#]],
1226 );
1227 }
1228
1229 #[test]
1230 fn fn_detail_includes_args_and_return_type() {
1231 check(
1232 r#"
1233fn foo<T>(a: u32, b: u32, t: T) -> (u32, T) { (a, t) }
1234
1235fn main() { fo$0 }
1236"#,
1237 SymbolKind::Function,
1238 expect![[r#"
1239 [
1240 CompletionItem {
1241 label: "foo(…)",
1242 detail_left: None,
1243 detail_right: Some(
1244 "fn(u32, u32, T) -> (u32, T)",
1245 ),
1246 source_range: 68..70,
1247 delete: 68..70,
1248 insert: "foo(${1:a}, ${2:b}, ${3:t})$0",
1249 kind: SymbolKind(
1250 Function,
1251 ),
1252 lookup: "foo",
1253 detail: "fn(u32, u32, T) -> (u32, T)",
1254 trigger_call_info: true,
1255 },
1256 CompletionItem {
1257 label: "main()",
1258 detail_left: None,
1259 detail_right: Some(
1260 "fn()",
1261 ),
1262 source_range: 68..70,
1263 delete: 68..70,
1264 insert: "main();$0",
1265 kind: SymbolKind(
1266 Function,
1267 ),
1268 lookup: "main",
1269 detail: "fn()",
1270 },
1271 ]
1272 "#]],
1273 );
1274 }
1275
1276 #[test]
1277 fn fn_detail_includes_variadics() {
1278 check(
1279 r#"
1280unsafe extern "C" fn foo(a: u32, b: u32, ...) {}
1281
1282fn main() { fo$0 }
1283"#,
1284 SymbolKind::Function,
1285 expect![[r#"
1286 [
1287 CompletionItem {
1288 label: "foo(…)",
1289 detail_left: None,
1290 detail_right: Some(
1291 "unsafe fn(u32, u32, ...)",
1292 ),
1293 source_range: 62..64,
1294 delete: 62..64,
1295 insert: "foo(${1:a}, ${2:b});$0",
1296 kind: SymbolKind(
1297 Function,
1298 ),
1299 lookup: "foo",
1300 detail: "unsafe fn(u32, u32, ...)",
1301 trigger_call_info: true,
1302 },
1303 CompletionItem {
1304 label: "main()",
1305 detail_left: None,
1306 detail_right: Some(
1307 "fn()",
1308 ),
1309 source_range: 62..64,
1310 delete: 62..64,
1311 insert: "main();$0",
1312 kind: SymbolKind(
1313 Function,
1314 ),
1315 lookup: "main",
1316 detail: "fn()",
1317 },
1318 ]
1319 "#]],
1320 );
1321 }
1322
1323 #[test]
1324 fn enum_detail_just_name_for_unit() {
1325 check(
1326 r#"
1327enum Foo { Foo }
1328
1329fn main() { Foo::Fo$0 }
1330"#,
1331 SymbolKind::Variant,
1332 expect![[r#"
1333 [
1334 CompletionItem {
1335 label: "Foo",
1336 detail_left: None,
1337 detail_right: Some(
1338 "Foo",
1339 ),
1340 source_range: 35..37,
1341 delete: 35..37,
1342 insert: "Foo$0",
1343 kind: SymbolKind(
1344 Variant,
1345 ),
1346 detail: "Foo",
1347 relevance: CompletionRelevance {
1348 exact_name_match: false,
1349 type_match: None,
1350 is_local: false,
1351 trait_: None,
1352 is_name_already_imported: false,
1353 requires_import: false,
1354 is_private_editable: false,
1355 postfix_match: None,
1356 function: Some(
1357 CompletionRelevanceFn {
1358 has_params: false,
1359 has_self_param: false,
1360 return_type: DirectConstructor,
1361 },
1362 ),
1363 is_skipping_completion: false,
1364 },
1365 trigger_call_info: true,
1366 },
1367 ]
1368 "#]],
1369 );
1370 }
1371
1372 #[test]
1373 fn lookup_enums_by_two_qualifiers() {
1374 check_kinds(
1375 r#"
1376mod m {
1377 pub enum Spam { Foo, Bar(i32) }
1378}
1379fn main() { let _: m::Spam = S$0 }
1380"#,
1381 &[
1382 CompletionItemKind::SymbolKind(SymbolKind::Function),
1383 CompletionItemKind::SymbolKind(SymbolKind::Module),
1384 CompletionItemKind::SymbolKind(SymbolKind::Variant),
1385 ],
1386 expect![[r#"
1387 [
1388 CompletionItem {
1389 label: "main()",
1390 detail_left: None,
1391 detail_right: Some(
1392 "fn()",
1393 ),
1394 source_range: 75..76,
1395 delete: 75..76,
1396 insert: "main();$0",
1397 kind: SymbolKind(
1398 Function,
1399 ),
1400 lookup: "main",
1401 detail: "fn()",
1402 },
1403 CompletionItem {
1404 label: "m",
1405 detail_left: None,
1406 detail_right: None,
1407 source_range: 75..76,
1408 delete: 75..76,
1409 insert: "m",
1410 kind: SymbolKind(
1411 Module,
1412 ),
1413 },
1414 CompletionItem {
1415 label: "m::Spam::Bar(…)",
1416 detail_left: None,
1417 detail_right: Some(
1418 "m::Spam::Bar(i32)",
1419 ),
1420 source_range: 75..76,
1421 delete: 75..76,
1422 insert: "m::Spam::Bar(${1:()})$0",
1423 kind: SymbolKind(
1424 Variant,
1425 ),
1426 lookup: "Spam::Bar()",
1427 detail: "m::Spam::Bar(i32)",
1428 relevance: CompletionRelevance {
1429 exact_name_match: false,
1430 type_match: Some(
1431 Exact,
1432 ),
1433 is_local: false,
1434 trait_: None,
1435 is_name_already_imported: false,
1436 requires_import: false,
1437 is_private_editable: false,
1438 postfix_match: None,
1439 function: Some(
1440 CompletionRelevanceFn {
1441 has_params: true,
1442 has_self_param: false,
1443 return_type: DirectConstructor,
1444 },
1445 ),
1446 is_skipping_completion: false,
1447 },
1448 trigger_call_info: true,
1449 },
1450 CompletionItem {
1451 label: "m::Spam::Foo",
1452 detail_left: None,
1453 detail_right: Some(
1454 "m::Spam::Foo",
1455 ),
1456 source_range: 75..76,
1457 delete: 75..76,
1458 insert: "m::Spam::Foo$0",
1459 kind: SymbolKind(
1460 Variant,
1461 ),
1462 lookup: "Spam::Foo",
1463 detail: "m::Spam::Foo",
1464 relevance: CompletionRelevance {
1465 exact_name_match: false,
1466 type_match: Some(
1467 Exact,
1468 ),
1469 is_local: false,
1470 trait_: None,
1471 is_name_already_imported: false,
1472 requires_import: false,
1473 is_private_editable: false,
1474 postfix_match: None,
1475 function: Some(
1476 CompletionRelevanceFn {
1477 has_params: false,
1478 has_self_param: false,
1479 return_type: DirectConstructor,
1480 },
1481 ),
1482 is_skipping_completion: false,
1483 },
1484 trigger_call_info: true,
1485 },
1486 ]
1487 "#]],
1488 )
1489 }
1490
1491 #[test]
1492 fn sets_deprecated_flag_in_items() {
1493 check(
1494 r#"
1495#[deprecated]
1496fn something_deprecated() {}
1497
1498fn main() { som$0 }
1499"#,
1500 SymbolKind::Function,
1501 expect![[r#"
1502 [
1503 CompletionItem {
1504 label: "main()",
1505 detail_left: None,
1506 detail_right: Some(
1507 "fn()",
1508 ),
1509 source_range: 56..59,
1510 delete: 56..59,
1511 insert: "main();$0",
1512 kind: SymbolKind(
1513 Function,
1514 ),
1515 lookup: "main",
1516 detail: "fn()",
1517 },
1518 CompletionItem {
1519 label: "something_deprecated()",
1520 detail_left: None,
1521 detail_right: Some(
1522 "fn()",
1523 ),
1524 source_range: 56..59,
1525 delete: 56..59,
1526 insert: "something_deprecated();$0",
1527 kind: SymbolKind(
1528 Function,
1529 ),
1530 lookup: "something_deprecated",
1531 detail: "fn()",
1532 deprecated: true,
1533 },
1534 ]
1535 "#]],
1536 );
1537
1538 check(
1539 r#"
1540struct A { #[deprecated] the_field: u32 }
1541fn foo() { A { the$0 } }
1542"#,
1543 SymbolKind::Field,
1544 expect![[r#"
1545 [
1546 CompletionItem {
1547 label: "the_field",
1548 detail_left: None,
1549 detail_right: Some(
1550 "u32",
1551 ),
1552 source_range: 57..60,
1553 delete: 57..60,
1554 insert: "the_field",
1555 kind: SymbolKind(
1556 Field,
1557 ),
1558 detail: "u32",
1559 deprecated: true,
1560 relevance: CompletionRelevance {
1561 exact_name_match: false,
1562 type_match: Some(
1563 CouldUnify,
1564 ),
1565 is_local: false,
1566 trait_: None,
1567 is_name_already_imported: false,
1568 requires_import: false,
1569 is_private_editable: false,
1570 postfix_match: None,
1571 function: None,
1572 is_skipping_completion: false,
1573 },
1574 },
1575 ]
1576 "#]],
1577 );
1578 }
1579
1580 #[test]
1581 fn renders_docs() {
1582 check_kinds(
1583 r#"
1584struct S {
1585 /// Field docs
1586 foo:
1587}
1588impl S {
1589 /// Method docs
1590 fn bar(self) { self.$0 }
1591}"#,
1592 &[
1593 CompletionItemKind::SymbolKind(SymbolKind::Method),
1594 CompletionItemKind::SymbolKind(SymbolKind::Field),
1595 ],
1596 expect![[r#"
1597 [
1598 CompletionItem {
1599 label: "bar()",
1600 detail_left: None,
1601 detail_right: Some(
1602 "fn(self)",
1603 ),
1604 source_range: 94..94,
1605 delete: 94..94,
1606 insert: "bar();$0",
1607 kind: SymbolKind(
1608 Method,
1609 ),
1610 lookup: "bar",
1611 detail: "fn(self)",
1612 documentation: Documentation(
1613 "Method docs",
1614 ),
1615 relevance: CompletionRelevance {
1616 exact_name_match: false,
1617 type_match: None,
1618 is_local: false,
1619 trait_: None,
1620 is_name_already_imported: false,
1621 requires_import: false,
1622 is_private_editable: false,
1623 postfix_match: None,
1624 function: Some(
1625 CompletionRelevanceFn {
1626 has_params: true,
1627 has_self_param: true,
1628 return_type: Other,
1629 },
1630 ),
1631 is_skipping_completion: false,
1632 },
1633 },
1634 CompletionItem {
1635 label: "foo",
1636 detail_left: None,
1637 detail_right: Some(
1638 "{unknown}",
1639 ),
1640 source_range: 94..94,
1641 delete: 94..94,
1642 insert: "foo",
1643 kind: SymbolKind(
1644 Field,
1645 ),
1646 detail: "{unknown}",
1647 documentation: Documentation(
1648 "Field docs",
1649 ),
1650 },
1651 ]
1652 "#]],
1653 );
1654
1655 check_kinds(
1656 r#"
1657use self::my$0;
1658
1659/// mod docs
1660mod my { }
1661
1662/// enum docs
1663enum E {
1664 /// variant docs
1665 V
1666}
1667use self::E::*;
1668"#,
1669 &[
1670 CompletionItemKind::SymbolKind(SymbolKind::Module),
1671 CompletionItemKind::SymbolKind(SymbolKind::Variant),
1672 CompletionItemKind::SymbolKind(SymbolKind::Enum),
1673 ],
1674 expect![[r#"
1675 [
1676 CompletionItem {
1677 label: "my",
1678 detail_left: None,
1679 detail_right: None,
1680 source_range: 10..12,
1681 delete: 10..12,
1682 insert: "my",
1683 kind: SymbolKind(
1684 Module,
1685 ),
1686 documentation: Documentation(
1687 "mod docs",
1688 ),
1689 },
1690 CompletionItem {
1691 label: "V",
1692 detail_left: None,
1693 detail_right: Some(
1694 "V",
1695 ),
1696 source_range: 10..12,
1697 delete: 10..12,
1698 insert: "V$0",
1699 kind: SymbolKind(
1700 Variant,
1701 ),
1702 detail: "V",
1703 documentation: Documentation(
1704 "variant docs",
1705 ),
1706 relevance: CompletionRelevance {
1707 exact_name_match: false,
1708 type_match: None,
1709 is_local: false,
1710 trait_: None,
1711 is_name_already_imported: false,
1712 requires_import: false,
1713 is_private_editable: false,
1714 postfix_match: None,
1715 function: Some(
1716 CompletionRelevanceFn {
1717 has_params: false,
1718 has_self_param: false,
1719 return_type: DirectConstructor,
1720 },
1721 ),
1722 is_skipping_completion: false,
1723 },
1724 trigger_call_info: true,
1725 },
1726 CompletionItem {
1727 label: "E",
1728 detail_left: None,
1729 detail_right: Some(
1730 "E",
1731 ),
1732 source_range: 10..12,
1733 delete: 10..12,
1734 insert: "E",
1735 kind: SymbolKind(
1736 Enum,
1737 ),
1738 detail: "E",
1739 documentation: Documentation(
1740 "enum docs",
1741 ),
1742 },
1743 ]
1744 "#]],
1745 )
1746 }
1747
1748 #[test]
1749 fn dont_render_attrs() {
1750 check(
1751 r#"
1752struct S;
1753impl S {
1754 #[inline]
1755 fn the_method(&self) { }
1756}
1757fn foo(s: S) { s.$0 }
1758"#,
1759 CompletionItemKind::SymbolKind(SymbolKind::Method),
1760 expect![[r#"
1761 [
1762 CompletionItem {
1763 label: "the_method()",
1764 detail_left: None,
1765 detail_right: Some(
1766 "fn(&self)",
1767 ),
1768 source_range: 81..81,
1769 delete: 81..81,
1770 insert: "the_method();$0",
1771 kind: SymbolKind(
1772 Method,
1773 ),
1774 lookup: "the_method",
1775 detail: "fn(&self)",
1776 relevance: CompletionRelevance {
1777 exact_name_match: false,
1778 type_match: None,
1779 is_local: false,
1780 trait_: None,
1781 is_name_already_imported: false,
1782 requires_import: false,
1783 is_private_editable: false,
1784 postfix_match: None,
1785 function: Some(
1786 CompletionRelevanceFn {
1787 has_params: true,
1788 has_self_param: true,
1789 return_type: Other,
1790 },
1791 ),
1792 is_skipping_completion: false,
1793 },
1794 },
1795 ]
1796 "#]],
1797 )
1798 }
1799
1800 #[test]
1801 fn no_call_parens_if_fn_ptr_needed() {
1802 cov_mark::check!(no_call_parens_if_fn_ptr_needed);
1803 check_edit(
1804 "foo",
1805 r#"
1806fn foo(foo: u8, bar: u8) {}
1807struct ManualVtable { f: fn(u8, u8) }
1808
1809fn main() -> ManualVtable {
1810 ManualVtable { f: f$0 }
1811}
1812"#,
1813 r#"
1814fn foo(foo: u8, bar: u8) {}
1815struct ManualVtable { f: fn(u8, u8) }
1816
1817fn main() -> ManualVtable {
1818 ManualVtable { f: foo }
1819}
1820"#,
1821 );
1822 check_edit(
1823 "type",
1824 r#"
1825struct RawIdentTable { r#type: u32 }
1826
1827fn main() -> RawIdentTable {
1828 RawIdentTable { t$0: 42 }
1829}
1830"#,
1831 r#"
1832struct RawIdentTable { r#type: u32 }
1833
1834fn main() -> RawIdentTable {
1835 RawIdentTable { r#type: 42 }
1836}
1837"#,
1838 );
1839 }
1840
1841 #[test]
1842 fn no_parens_in_use_item() {
1843 check_edit(
1844 "foo",
1845 r#"
1846mod m { pub fn foo() {} }
1847use crate::m::f$0;
1848"#,
1849 r#"
1850mod m { pub fn foo() {} }
1851use crate::m::foo;
1852"#,
1853 );
1854 }
1855
1856 #[test]
1857 fn no_parens_in_call() {
1858 check_edit(
1859 "foo",
1860 r#"
1861fn foo(x: i32) {}
1862fn main() { f$0(); }
1863"#,
1864 r#"
1865fn foo(x: i32) {}
1866fn main() { foo(); }
1867"#,
1868 );
1869 check_edit(
1870 "foo",
1871 r#"
1872struct Foo;
1873impl Foo { fn foo(&self){} }
1874fn f(foo: &Foo) { foo.f$0(); }
1875"#,
1876 r#"
1877struct Foo;
1878impl Foo { fn foo(&self){} }
1879fn f(foo: &Foo) { foo.foo(); }
1880"#,
1881 );
1882 }
1883
1884 #[test]
1885 fn inserts_angle_brackets_for_generics() {
1886 cov_mark::check!(inserts_angle_brackets_for_generics);
1887 check_edit(
1888 "Vec",
1889 r#"
1890struct Vec<T> {}
1891fn foo(xs: Ve$0)
1892"#,
1893 r#"
1894struct Vec<T> {}
1895fn foo(xs: Vec<$0>)
1896"#,
1897 );
1898 check_edit(
1899 "Vec",
1900 r#"
1901type Vec<T> = (T,);
1902fn foo(xs: Ve$0)
1903"#,
1904 r#"
1905type Vec<T> = (T,);
1906fn foo(xs: Vec<$0>)
1907"#,
1908 );
1909 check_edit(
1910 "Vec",
1911 r#"
1912struct Vec<T = i128> {}
1913fn foo(xs: Ve$0)
1914"#,
1915 r#"
1916struct Vec<T = i128> {}
1917fn foo(xs: Vec)
1918"#,
1919 );
1920 check_edit(
1921 "Vec",
1922 r#"
1923struct Vec<T> {}
1924fn foo(xs: Ve$0<i128>)
1925"#,
1926 r#"
1927struct Vec<T> {}
1928fn foo(xs: Vec<i128>)
1929"#,
1930 );
1931 }
1932
1933 #[test]
1934 fn active_param_relevance() {
1935 check_relevance(
1936 r#"
1937struct S { foo: i64, bar: u32, baz: u32 }
1938fn test(bar: u32) { }
1939fn foo(s: S) { test(s.$0) }
1940"#,
1941 expect![[r#"
1942 fd bar u32 [type+name]
1943 fd baz u32 [type]
1944 fd foo i64 []
1945 "#]],
1946 );
1947 }
1948
1949 #[test]
1950 fn record_field_relevances() {
1951 check_relevance(
1952 r#"
1953struct A { foo: i64, bar: u32, baz: u32 }
1954struct B { x: (), y: f32, bar: u32 }
1955fn foo(a: A) { B { bar: a.$0 }; }
1956"#,
1957 expect![[r#"
1958 fd bar u32 [type+name]
1959 fd baz u32 [type]
1960 fd foo i64 []
1961 "#]],
1962 )
1963 }
1964
1965 #[test]
1966 fn tuple_field_detail() {
1967 check(
1968 r#"
1969struct S(i32);
1970
1971fn f() -> i32 {
1972 let s = S(0);
1973 s.0$0
1974}
1975"#,
1976 SymbolKind::Field,
1977 expect![[r#"
1978 [
1979 CompletionItem {
1980 label: "0",
1981 detail_left: None,
1982 detail_right: Some(
1983 "i32",
1984 ),
1985 source_range: 56..57,
1986 delete: 56..57,
1987 insert: "0",
1988 kind: SymbolKind(
1989 Field,
1990 ),
1991 detail: "i32",
1992 relevance: CompletionRelevance {
1993 exact_name_match: false,
1994 type_match: Some(
1995 Exact,
1996 ),
1997 is_local: false,
1998 trait_: None,
1999 is_name_already_imported: false,
2000 requires_import: false,
2001 is_private_editable: false,
2002 postfix_match: None,
2003 function: None,
2004 is_skipping_completion: false,
2005 },
2006 },
2007 ]
2008 "#]],
2009 );
2010 }
2011
2012 #[test]
2013 fn record_field_and_call_relevances() {
2014 check_relevance(
2015 r#"
2016struct A { foo: i64, bar: u32, baz: u32 }
2017struct B { x: (), y: f32, bar: u32 }
2018fn f(foo: i64) { }
2019fn foo(a: A) { B { bar: f(a.$0) }; }
2020"#,
2021 expect![[r#"
2022 fd foo i64 [type+name]
2023 fd bar u32 []
2024 fd baz u32 []
2025 "#]],
2026 );
2027 check_relevance(
2028 r#"
2029struct A { foo: i64, bar: u32, baz: u32 }
2030struct B { x: (), y: f32, bar: u32 }
2031fn f(foo: i64) { }
2032fn foo(a: A) { f(B { bar: a.$0 }); }
2033"#,
2034 expect![[r#"
2035 fd bar u32 [type+name]
2036 fd baz u32 [type]
2037 fd foo i64 []
2038 "#]],
2039 );
2040 }
2041
2042 #[test]
2043 fn prioritize_exact_ref_match() {
2044 check_relevance(
2045 r#"
2046struct WorldSnapshot { _f: () };
2047fn go(world: &WorldSnapshot) { go(w$0) }
2048"#,
2049 expect![[r#"
2050 lc world &WorldSnapshot [type+name+local]
2051 ex world [type]
2052 st WorldSnapshot {…} WorldSnapshot { _f: () } []
2053 st &WorldSnapshot {…} [type]
2054 st WorldSnapshot WorldSnapshot []
2055 st &WorldSnapshot [type]
2056 fn go(…) fn(&WorldSnapshot) []
2057 "#]],
2058 );
2059 }
2060
2061 #[test]
2062 fn prioritize_mutable_ref_as_immutable_ref_match() {
2063 check_relevance(
2064 r#"fn foo(r: &mut i32) -> &i32 { $0 }"#,
2065 expect![[r#"
2066 lc r &mut i32 [type+local]
2067 fn foo(…) fn(&mut i32) -> &i32 [type]
2068 "#]],
2069 );
2070 }
2071
2072 #[test]
2073 fn too_many_arguments() {
2074 cov_mark::check!(too_many_arguments);
2075 check_relevance(
2076 r#"
2077struct Foo;
2078fn f(foo: &Foo) { f(foo, w$0) }
2079"#,
2080 expect![[r#"
2081 lc foo &Foo [local]
2082 st Foo Foo []
2083 fn f(…) fn(&Foo) []
2084 "#]],
2085 );
2086 }
2087
2088 #[test]
2089 fn score_fn_type_and_name_match() {
2090 check_relevance(
2091 r#"
2092struct A { bar: u8 }
2093fn baz() -> u8 { 0 }
2094fn bar() -> u8 { 0 }
2095fn f() { A { bar: b$0 }; }
2096"#,
2097 expect![[r#"
2098 fn bar() fn() -> u8 [type+name]
2099 ex bar() [type]
2100 fn baz() fn() -> u8 [type]
2101 ex baz() [type]
2102 st A A []
2103 fn f() fn() []
2104 "#]],
2105 );
2106 }
2107
2108 #[test]
2109 fn score_method_type_and_name_match() {
2110 check_relevance(
2111 r#"
2112fn baz(aaa: u32){}
2113struct Foo;
2114impl Foo {
2115fn aaa(&self) -> u32 { 0 }
2116fn bbb(&self) -> u32 { 0 }
2117fn ccc(&self) -> u64 { 0 }
2118}
2119fn f() {
2120 baz(Foo.$0
2121}
2122"#,
2123 expect![[r#"
2124 me aaa() fn(&self) -> u32 [type+name]
2125 me bbb() fn(&self) -> u32 [type]
2126 me ccc() fn(&self) -> u64 []
2127 "#]],
2128 );
2129 }
2130
2131 #[test]
2132 fn score_method_name_match_only() {
2133 check_relevance(
2134 r#"
2135fn baz(aaa: u32){}
2136struct Foo;
2137impl Foo {
2138fn aaa(&self) -> u64 { 0 }
2139}
2140fn f() {
2141 baz(Foo.$0
2142}
2143"#,
2144 expect![[r#"
2145 me aaa() fn(&self) -> u64 [name]
2146 "#]],
2147 );
2148 }
2149
2150 #[test]
2151 fn test_avoid_redundant_suggestion() {
2152 check_relevance(
2153 r#"
2154struct aa([u8]);
2155
2156impl aa {
2157 fn from_bytes(bytes: &[u8]) -> &Self {
2158 unsafe { &*(bytes as *const [u8] as *const aa) }
2159 }
2160}
2161
2162fn bb()-> &'static aa {
2163 let bytes = b"hello";
2164 aa::$0
2165}
2166"#,
2167 expect![[r#"
2168 ex bb() [type]
2169 fn from_bytes(…) fn(&[u8]) -> &aa [type_could_unify]
2170 "#]],
2171 );
2172 }
2173
2174 #[test]
2175 fn suggest_ref_mut() {
2176 cov_mark::check!(suggest_ref);
2177 check_relevance(
2178 r#"
2179struct S;
2180fn foo(s: &mut S) {}
2181fn main() {
2182 let mut s = S;
2183 foo($0);
2184}
2185 "#,
2186 expect![[r#"
2187 lc s S [name+local]
2188 lc &mut s [type+name+local]
2189 st S S []
2190 st &mut S [type]
2191 st S S []
2192 st &mut S [type]
2193 fn foo(…) fn(&mut S) []
2194 fn main() fn() []
2195 "#]],
2196 );
2197 check_relevance(
2198 r#"
2199struct S;
2200fn foo(s: &mut S) {}
2201fn main() {
2202 let mut s = S;
2203 foo(&mut $0);
2204}
2205 "#,
2206 expect![[r#"
2207 lc s S [type+name+local]
2208 st S S [type]
2209 st S S [type]
2210 ex S [type]
2211 ex s [type]
2212 fn foo(…) fn(&mut S) []
2213 fn main() fn() []
2214 "#]],
2215 );
2216 check_relevance(
2217 r#"
2218struct S;
2219fn foo(s: &mut S) {}
2220fn main() {
2221 let mut ssss = S;
2222 foo(&mut s$0);
2223}
2224 "#,
2225 expect![[r#"
2226 st S S [type]
2227 lc ssss S [type+local]
2228 st S S [type]
2229 ex S [type]
2230 ex ssss [type]
2231 fn foo(…) fn(&mut S) []
2232 fn main() fn() []
2233 "#]],
2234 );
2235 }
2236
2237 #[test]
2238 fn suggest_deref_copy() {
2239 cov_mark::check!(suggest_deref);
2240 check_relevance(
2241 r#"
2242//- minicore: copy
2243struct Foo;
2244
2245impl Copy for Foo {}
2246impl Clone for Foo {
2247 fn clone(&self) -> Self { *self }
2248}
2249
2250fn bar(x: Foo) {}
2251
2252fn main() {
2253 let foo = &Foo;
2254 bar($0);
2255}
2256"#,
2257 expect![[r#"
2258 st Foo Foo [type]
2259 st Foo Foo [type]
2260 ex Foo [type]
2261 lc foo &Foo [local]
2262 lc *foo [type+local]
2263 tt Clone []
2264 tt Copy []
2265 fn bar(…) fn(Foo) []
2266 md core []
2267 fn main() fn() []
2268 "#]],
2269 );
2270 }
2271
2272 #[test]
2273 fn suggest_deref_trait() {
2274 check_relevance(
2275 r#"
2276//- minicore: deref
2277struct S;
2278struct T(S);
2279
2280impl core::ops::Deref for T {
2281 type Target = S;
2282
2283 fn deref(&self) -> &Self::Target {
2284 &self.0
2285 }
2286}
2287
2288fn foo(s: &S) {}
2289
2290fn main() {
2291 let t = T(S);
2292 let m = 123;
2293
2294 foo($0);
2295}
2296 "#,
2297 expect![[r#"
2298 st S S []
2299 st &S [type]
2300 ex core::ops::Deref::deref(&t) [type_could_unify]
2301 lc m i32 [local]
2302 lc t T [local]
2303 lc &t [type+local]
2304 st S S []
2305 st &S [type]
2306 st T T []
2307 st &T [type]
2308 md core []
2309 fn foo(…) fn(&S) []
2310 fn main() fn() []
2311 "#]],
2312 )
2313 }
2314
2315 #[test]
2316 fn suggest_deref_mut() {
2317 check_relevance(
2318 r#"
2319//- minicore: deref_mut
2320struct S;
2321struct T(S);
2322
2323impl core::ops::Deref for T {
2324 type Target = S;
2325
2326 fn deref(&self) -> &Self::Target {
2327 &self.0
2328 }
2329}
2330
2331impl core::ops::DerefMut for T {
2332 fn deref_mut(&mut self) -> &mut Self::Target {
2333 &mut self.0
2334 }
2335}
2336
2337fn foo(s: &mut S) {}
2338
2339fn main() {
2340 let t = T(S);
2341 let m = 123;
2342
2343 foo($0);
2344}
2345 "#,
2346 expect![[r#"
2347 st S S []
2348 st &mut S [type]
2349 ex core::ops::DerefMut::deref_mut(&mut t) [type_could_unify]
2350 lc m i32 [local]
2351 lc t T [local]
2352 lc &mut t [type+local]
2353 st S S []
2354 st &mut S [type]
2355 st T T []
2356 st &mut T [type]
2357 md core []
2358 fn foo(…) fn(&mut S) []
2359 fn main() fn() []
2360 "#]],
2361 )
2362 }
2363
2364 #[test]
2365 fn locals() {
2366 check_relevance(
2367 r#"
2368fn foo(bar: u32) {
2369 let baz = 0;
2370
2371 f$0
2372}
2373"#,
2374 expect![[r#"
2375 lc bar u32 [local]
2376 lc baz i32 [local]
2377 fn foo(…) fn(u32) []
2378 "#]],
2379 );
2380 }
2381
2382 #[test]
2383 fn enum_owned() {
2384 check_relevance(
2385 r#"
2386enum Foo { A, B }
2387fn foo() {
2388 bar($0);
2389}
2390fn bar(t: Foo) {}
2391"#,
2392 expect![[r#"
2393 ev Foo::A Foo::A [type]
2394 ev Foo::B Foo::B [type]
2395 en Foo Foo [type]
2396 ex Foo::A [type]
2397 ex Foo::B [type]
2398 fn bar(…) fn(Foo) []
2399 fn foo() fn() []
2400 "#]],
2401 );
2402 }
2403
2404 #[test]
2405 fn enum_ref() {
2406 check_relevance(
2407 r#"
2408enum Foo { A, B }
2409fn foo() {
2410 bar($0);
2411}
2412fn bar(t: &Foo) {}
2413"#,
2414 expect![[r#"
2415 ev Foo::A Foo::A []
2416 ev &Foo::A [type]
2417 ev Foo::B Foo::B []
2418 ev &Foo::B [type]
2419 en Foo Foo []
2420 en &Foo [type]
2421 fn bar(…) fn(&Foo) []
2422 fn foo() fn() []
2423 "#]],
2424 );
2425 }
2426
2427 #[test]
2428 fn suggest_deref_fn_ret() {
2429 check_relevance(
2430 r#"
2431//- minicore: deref
2432struct S;
2433struct T(S);
2434
2435impl core::ops::Deref for T {
2436 type Target = S;
2437
2438 fn deref(&self) -> &Self::Target {
2439 &self.0
2440 }
2441}
2442
2443fn foo(s: &S) {}
2444fn bar() -> T {}
2445
2446fn main() {
2447 foo($0);
2448}
2449"#,
2450 expect![[r#"
2451 st S S []
2452 st &S [type]
2453 ex core::ops::Deref::deref(&bar()) [type_could_unify]
2454 st S S []
2455 st &S [type]
2456 st T T []
2457 st &T [type]
2458 fn bar() fn() -> T []
2459 fn &bar() [type]
2460 md core []
2461 fn foo(…) fn(&S) []
2462 fn main() fn() []
2463 "#]],
2464 )
2465 }
2466
2467 #[test]
2468 fn op_function_relevances() {
2469 check_relevance(
2470 r#"
2471#[lang = "sub"]
2472trait Sub {
2473 fn sub(self, other: Self) -> Self { self }
2474}
2475impl Sub for u32 {}
2476fn foo(a: u32) { a.$0 }
2477"#,
2478 expect![[r#"
2479 me sub(…) fn(self, Self) -> Self [op_method]
2480 "#]],
2481 );
2482 check_relevance(
2483 r#"
2484struct Foo;
2485impl Foo {
2486 fn new() -> Self {}
2487}
2488#[lang = "eq"]
2489pub trait PartialEq<Rhs: ?Sized = Self> {
2490 fn eq(&self, other: &Rhs) -> bool;
2491 fn ne(&self, other: &Rhs) -> bool;
2492}
2493
2494impl PartialEq for Foo {}
2495fn main() {
2496 Foo::$0
2497}
2498"#,
2499 expect![[r#"
2500 fn new() fn() -> Foo []
2501 me eq(…) fn(&self, &Rhs) -> bool [op_method]
2502 me ne(…) fn(&self, &Rhs) -> bool [op_method]
2503 "#]],
2504 );
2505 }
2506
2507 #[test]
2508 fn constructor_order_simple() {
2509 check_relevance(
2510 r#"
2511struct Foo;
2512struct Other;
2513struct Option<T>(T);
2514
2515impl Foo {
2516 fn fn_ctr() -> Foo { unimplemented!() }
2517 fn fn_another(n: u32) -> Other { unimplemented!() }
2518 fn fn_ctr_self() -> Option<Self> { unimplemented!() }
2519}
2520
2521fn test() {
2522 let a = Foo::$0;
2523}
2524"#,
2525 expect![[r#"
2526 fn fn_ctr() fn() -> Foo [type_could_unify]
2527 fn fn_ctr_self() fn() -> Option<Foo> [type_could_unify]
2528 fn fn_another(…) fn(u32) -> Other [type_could_unify]
2529 "#]],
2530 );
2531 }
2532
2533 #[test]
2534 fn constructor_order_kind() {
2535 check_function_relevance(
2536 r#"
2537struct Foo;
2538struct Bar;
2539struct Option<T>(T);
2540enum Result<T, E> { Ok(T), Err(E) };
2541
2542impl Foo {
2543 fn fn_ctr(&self) -> Foo { unimplemented!() }
2544 fn fn_ctr_with_args(&self, n: u32) -> Foo { unimplemented!() }
2545 fn fn_another(&self, n: u32) -> Bar { unimplemented!() }
2546 fn fn_ctr_wrapped(&self, ) -> Option<Self> { unimplemented!() }
2547 fn fn_ctr_wrapped_2(&self, ) -> Result<Self, Bar> { unimplemented!() }
2548 fn fn_ctr_wrapped_3(&self, ) -> Result<Bar, Self> { unimplemented!() } // Self is not the first type
2549 fn fn_ctr_wrapped_with_args(&self, m: u32) -> Option<Self> { unimplemented!() }
2550 fn fn_another_unit(&self) { unimplemented!() }
2551}
2552
2553fn test() {
2554 let a = self::Foo::$0;
2555}
2556"#,
2557 expect![[r#"
2558 [
2559 (
2560 "fn(&self, u32) -> Bar",
2561 Some(
2562 CompletionRelevanceFn {
2563 has_params: true,
2564 has_self_param: true,
2565 return_type: Other,
2566 },
2567 ),
2568 ),
2569 (
2570 "fn(&self)",
2571 Some(
2572 CompletionRelevanceFn {
2573 has_params: true,
2574 has_self_param: true,
2575 return_type: Other,
2576 },
2577 ),
2578 ),
2579 (
2580 "fn(&self) -> Foo",
2581 Some(
2582 CompletionRelevanceFn {
2583 has_params: true,
2584 has_self_param: true,
2585 return_type: DirectConstructor,
2586 },
2587 ),
2588 ),
2589 (
2590 "fn(&self, u32) -> Foo",
2591 Some(
2592 CompletionRelevanceFn {
2593 has_params: true,
2594 has_self_param: true,
2595 return_type: DirectConstructor,
2596 },
2597 ),
2598 ),
2599 (
2600 "fn(&self) -> Option<Foo>",
2601 Some(
2602 CompletionRelevanceFn {
2603 has_params: true,
2604 has_self_param: true,
2605 return_type: Constructor,
2606 },
2607 ),
2608 ),
2609 (
2610 "fn(&self) -> Result<Foo, Bar>",
2611 Some(
2612 CompletionRelevanceFn {
2613 has_params: true,
2614 has_self_param: true,
2615 return_type: Constructor,
2616 },
2617 ),
2618 ),
2619 (
2620 "fn(&self) -> Result<Bar, Foo>",
2621 Some(
2622 CompletionRelevanceFn {
2623 has_params: true,
2624 has_self_param: true,
2625 return_type: Constructor,
2626 },
2627 ),
2628 ),
2629 (
2630 "fn(&self, u32) -> Option<Foo>",
2631 Some(
2632 CompletionRelevanceFn {
2633 has_params: true,
2634 has_self_param: true,
2635 return_type: Constructor,
2636 },
2637 ),
2638 ),
2639 ]
2640 "#]],
2641 );
2642 }
2643
2644 #[test]
2645 fn constructor_order_relevance() {
2646 check_relevance(
2647 r#"
2648struct Foo;
2649struct FooBuilder;
2650struct Result<T>(T);
2651
2652impl Foo {
2653 fn fn_no_ret(&self) {}
2654 fn fn_ctr_with_args(input: u32) -> Foo { unimplemented!() }
2655 fn fn_direct_ctr() -> Self { unimplemented!() }
2656 fn fn_ctr() -> Result<Self> { unimplemented!() }
2657 fn fn_other() -> Result<u32> { unimplemented!() }
2658 fn fn_builder() -> FooBuilder { unimplemented!() }
2659}
2660
2661fn test() {
2662 let a = self::Foo::$0;
2663}
2664"#,
2665 expect![[r#"
2672 fn fn_direct_ctr() fn() -> Foo [type_could_unify]
2673 fn fn_ctr_with_args(…) fn(u32) -> Foo [type_could_unify]
2674 fn fn_builder() fn() -> FooBuilder [type_could_unify]
2675 fn fn_ctr() fn() -> Result<Foo> [type_could_unify]
2676 me fn_no_ret(…) fn(&self) [type_could_unify]
2677 fn fn_other() fn() -> Result<u32> [type_could_unify]
2678 "#]],
2679 );
2680
2681 }
2683
2684 #[test]
2685 fn function_relevance_generic_1() {
2686 check_relevance(
2687 r#"
2688struct Foo<T: Default>(T);
2689struct FooBuilder;
2690struct Option<T>(T);
2691enum Result<T, E>{Ok(T), Err(E)};
2692
2693impl<T: Default> Foo<T> {
2694 fn fn_returns_unit(&self) {}
2695 fn fn_ctr_with_args(input: T) -> Foo<T> { unimplemented!() }
2696 fn fn_direct_ctr() -> Self { unimplemented!() }
2697 fn fn_ctr_wrapped() -> Option<Self> { unimplemented!() }
2698 fn fn_ctr_wrapped_2() -> Result<Self, u32> { unimplemented!() }
2699 fn fn_other() -> Option<u32> { unimplemented!() }
2700 fn fn_builder() -> FooBuilder { unimplemented!() }
2701}
2702
2703fn test() {
2704 let a = self::Foo::<u32>::$0;
2705}
2706 "#,
2707 expect![[r#"
2708 fn fn_direct_ctr() fn() -> Foo<T> [type_could_unify]
2709 fn fn_ctr_with_args(…) fn(T) -> Foo<T> [type_could_unify]
2710 fn fn_builder() fn() -> FooBuilder [type_could_unify]
2711 fn fn_ctr_wrapped() fn() -> Option<Foo<T>> [type_could_unify]
2712 fn fn_ctr_wrapped_2() fn() -> Result<Foo<T>, u32> [type_could_unify]
2713 fn fn_other() fn() -> Option<u32> [type_could_unify]
2714 me fn_returns_unit(…) fn(&self) [type_could_unify]
2715 "#]],
2716 );
2717 }
2718
2719 #[test]
2720 fn function_relevance_generic_2() {
2721 check_relevance(
2723 r#"
2724struct Foo<T: Default>(T);
2725struct FooBuilder;
2726struct Option<T>(T);
2727enum Result<T, E>{Ok(T), Err(E)};
2728
2729impl<T: Default> Foo<T> {
2730 fn fn_no_ret(&self) {}
2731 fn fn_ctr_with_args(input: T) -> Foo<T> { unimplemented!() }
2732 fn fn_direct_ctr() -> Self { unimplemented!() }
2733 fn fn_ctr() -> Option<Self> { unimplemented!() }
2734 fn fn_ctr2() -> Result<Self, u32> { unimplemented!() }
2735 fn fn_other() -> Option<u32> { unimplemented!() }
2736 fn fn_builder() -> FooBuilder { unimplemented!() }
2737}
2738
2739fn test() {
2740 let a : Res<Foo<u32>> = Foo::$0;
2741}
2742 "#,
2743 expect![[r#"
2744 fn fn_direct_ctr() fn() -> Foo<T> [type_could_unify]
2745 fn fn_ctr_with_args(…) fn(T) -> Foo<T> [type_could_unify]
2746 fn fn_builder() fn() -> FooBuilder [type_could_unify]
2747 fn fn_ctr() fn() -> Option<Foo<T>> [type_could_unify]
2748 fn fn_ctr2() fn() -> Result<Foo<T>, u32> [type_could_unify]
2749 me fn_no_ret(…) fn(&self) [type_could_unify]
2750 fn fn_other() fn() -> Option<u32> [type_could_unify]
2751 "#]],
2752 );
2753 }
2754
2755 #[test]
2756 fn struct_field_method_ref() {
2757 check_kinds(
2758 r#"
2759struct Foo { bar: u32, qux: fn() }
2760impl Foo { fn baz(&self) -> u32 { 0 } }
2761
2762fn foo(f: Foo) { let _: &u32 = f.b$0 }
2763"#,
2764 &[
2765 CompletionItemKind::SymbolKind(SymbolKind::Method),
2766 CompletionItemKind::SymbolKind(SymbolKind::Field),
2767 ],
2768 expect![[r#"
2769 [
2770 CompletionItem {
2771 label: "baz()",
2772 detail_left: None,
2773 detail_right: Some(
2774 "fn(&self) -> u32",
2775 ),
2776 source_range: 109..110,
2777 delete: 109..110,
2778 insert: "baz()$0",
2779 kind: SymbolKind(
2780 Method,
2781 ),
2782 lookup: "baz",
2783 detail: "fn(&self) -> u32",
2784 relevance: CompletionRelevance {
2785 exact_name_match: false,
2786 type_match: None,
2787 is_local: false,
2788 trait_: None,
2789 is_name_already_imported: false,
2790 requires_import: false,
2791 is_private_editable: false,
2792 postfix_match: None,
2793 function: Some(
2794 CompletionRelevanceFn {
2795 has_params: true,
2796 has_self_param: true,
2797 return_type: Other,
2798 },
2799 ),
2800 is_skipping_completion: false,
2801 },
2802 ref_match: "&@107",
2803 },
2804 CompletionItem {
2805 label: "bar",
2806 detail_left: None,
2807 detail_right: Some(
2808 "u32",
2809 ),
2810 source_range: 109..110,
2811 delete: 109..110,
2812 insert: "bar",
2813 kind: SymbolKind(
2814 Field,
2815 ),
2816 detail: "u32",
2817 ref_match: "&@107",
2818 },
2819 CompletionItem {
2820 label: "qux",
2821 detail_left: None,
2822 detail_right: Some(
2823 "fn()",
2824 ),
2825 source_range: 109..110,
2826 text_edit: TextEdit {
2827 indels: [
2828 Indel {
2829 insert: "(",
2830 delete: 107..107,
2831 },
2832 Indel {
2833 insert: "qux)()",
2834 delete: 109..110,
2835 },
2836 ],
2837 annotation: None,
2838 },
2839 kind: SymbolKind(
2840 Field,
2841 ),
2842 detail: "fn()",
2843 },
2844 ]
2845 "#]],
2846 );
2847 }
2848
2849 #[test]
2850 fn expected_fn_type_ref() {
2851 check_kinds(
2852 r#"
2853struct S { field: fn() }
2854
2855fn foo() {
2856 let foo: fn() = S { fields: || {}}.fi$0;
2857}
2858"#,
2859 &[CompletionItemKind::SymbolKind(SymbolKind::Field)],
2860 expect![[r#"
2861 [
2862 CompletionItem {
2863 label: "field",
2864 detail_left: None,
2865 detail_right: Some(
2866 "fn()",
2867 ),
2868 source_range: 76..78,
2869 delete: 76..78,
2870 insert: "field",
2871 kind: SymbolKind(
2872 Field,
2873 ),
2874 detail: "fn()",
2875 relevance: CompletionRelevance {
2876 exact_name_match: false,
2877 type_match: Some(
2878 Exact,
2879 ),
2880 is_local: false,
2881 trait_: None,
2882 is_name_already_imported: false,
2883 requires_import: false,
2884 is_private_editable: false,
2885 postfix_match: None,
2886 function: None,
2887 is_skipping_completion: false,
2888 },
2889 },
2890 ]
2891 "#]],
2892 )
2893 }
2894
2895 #[test]
2896 fn qualified_path_ref() {
2897 check_kinds(
2898 r#"
2899struct S;
2900
2901struct T;
2902impl T {
2903 fn foo() -> S {}
2904}
2905
2906fn bar(s: &S) {}
2907
2908fn main() {
2909 bar(T::$0);
2910}
2911"#,
2912 &[CompletionItemKind::SymbolKind(SymbolKind::Function)],
2913 expect![[r#"
2914 [
2915 CompletionItem {
2916 label: "foo()",
2917 detail_left: None,
2918 detail_right: Some(
2919 "fn() -> S",
2920 ),
2921 source_range: 95..95,
2922 delete: 95..95,
2923 insert: "foo()$0",
2924 kind: SymbolKind(
2925 Function,
2926 ),
2927 lookup: "foo",
2928 detail: "fn() -> S",
2929 relevance: CompletionRelevance {
2930 exact_name_match: false,
2931 type_match: None,
2932 is_local: false,
2933 trait_: None,
2934 is_name_already_imported: false,
2935 requires_import: false,
2936 is_private_editable: false,
2937 postfix_match: None,
2938 function: Some(
2939 CompletionRelevanceFn {
2940 has_params: false,
2941 has_self_param: false,
2942 return_type: Other,
2943 },
2944 ),
2945 is_skipping_completion: false,
2946 },
2947 ref_match: "&@92",
2948 },
2949 ]
2950 "#]],
2951 );
2952 }
2953
2954 #[test]
2955 fn generic_enum() {
2956 check_relevance(
2957 r#"
2958enum Foo<T> { A(T), B }
2959// bar() should not be an exact type match
2960// because the generic parameters are different
2961fn bar() -> Foo<u8> { Foo::B }
2962// FIXME baz() should be an exact type match
2963// because the types could unify, but it currently
2964// is not. This is due to the T here being
2965// TyKind::Placeholder rather than TyKind::Missing.
2966fn baz<T>() -> Foo<T> { Foo::B }
2967fn foo() {
2968 let foo: Foo<u32> = Foo::B;
2969 let _: Foo<u32> = f$0;
2970}
2971"#,
2972 expect![[r#"
2973 ev Foo::B Foo::B [type_could_unify]
2974 ev Foo::A(…) Foo::A(T) [type_could_unify]
2975 lc foo Foo<u32> [type+local]
2976 ex Foo::B [type]
2977 ex foo [type]
2978 en Foo Foo<{unknown}> [type_could_unify]
2979 fn bar() fn() -> Foo<u8> []
2980 fn baz() fn() -> Foo<T> []
2981 fn foo() fn() []
2982 "#]],
2983 );
2984 }
2985
2986 #[test]
2987 fn postfix_exact_match_is_high_priority() {
2988 cov_mark::check!(postfix_exact_match_is_high_priority);
2989 check_relevance_for_kinds(
2990 r#"
2991mod ops {
2992 pub trait Not {
2993 type Output;
2994 fn not(self) -> Self::Output;
2995 }
2996
2997 impl Not for bool {
2998 type Output = bool;
2999 fn not(self) -> bool { if self { false } else { true }}
3000 }
3001}
3002
3003fn main() {
3004 let _: bool = (9 > 2).not$0;
3005}
3006 "#,
3007 &[CompletionItemKind::Snippet, CompletionItemKind::SymbolKind(SymbolKind::Method)],
3008 expect![[r#"
3009 sn not !expr [snippet]
3010 sn box Box::new(expr) []
3011 sn call function(expr) []
3012 sn const const {} []
3013 sn dbg dbg!(expr) []
3014 sn dbgr dbg!(&expr) []
3015 sn deref *expr []
3016 sn if if expr {} []
3017 sn match match expr {} []
3018 sn ref &expr []
3019 sn refm &mut expr []
3020 sn return return expr []
3021 sn unsafe unsafe {} []
3022 sn while while expr {} []
3023 me not() fn(self) -> <Self as Not>::Output [requires_import]
3024 "#]],
3025 );
3026 }
3027
3028 #[test]
3029 fn postfix_inexact_match_is_low_priority() {
3030 cov_mark::check!(postfix_inexact_match_is_low_priority);
3031 check_relevance_for_kinds(
3032 r#"
3033struct S;
3034impl S {
3035 fn f(&self) {}
3036}
3037fn main() {
3038 S.$0
3039}
3040 "#,
3041 &[CompletionItemKind::Snippet, CompletionItemKind::SymbolKind(SymbolKind::Method)],
3042 expect![[r#"
3043 me f() fn(&self) []
3044 sn box Box::new(expr) []
3045 sn call function(expr) []
3046 sn const const {} []
3047 sn dbg dbg!(expr) []
3048 sn dbgr dbg!(&expr) []
3049 sn deref *expr []
3050 sn let let []
3051 sn letm let mut []
3052 sn match match expr {} []
3053 sn ref &expr []
3054 sn refm &mut expr []
3055 sn return return expr []
3056 sn unsafe unsafe {} []
3057 "#]],
3058 );
3059 }
3060
3061 #[test]
3062 fn flyimport_reduced_relevance() {
3063 check_relevance(
3064 r#"
3065mod std {
3066 pub mod io {
3067 pub trait BufRead {}
3068 pub struct BufReader;
3069 pub struct BufWriter;
3070 }
3071}
3072struct Buffer;
3073
3074fn f() {
3075 Buf$0
3076}
3077"#,
3078 expect![[r#"
3079 st Buffer Buffer []
3080 fn f() fn() []
3081 md std []
3082 tt BufRead [requires_import]
3083 st BufReader BufReader [requires_import]
3084 st BufWriter BufWriter [requires_import]
3085 "#]],
3086 );
3087 }
3088
3089 #[test]
3090 fn completes_struct_with_raw_identifier() {
3091 check_edit(
3092 "type",
3093 r#"
3094mod m { pub struct r#type {} }
3095fn main() {
3096 let r#type = m::t$0;
3097}
3098"#,
3099 r#"
3100mod m { pub struct r#type {} }
3101fn main() {
3102 let r#type = m::r#type;
3103}
3104"#,
3105 )
3106 }
3107
3108 #[test]
3109 fn completes_fn_with_raw_identifier() {
3110 check_edit(
3111 "type",
3112 r#"
3113mod m { pub fn r#type {} }
3114fn main() {
3115 m::t$0
3116}
3117"#,
3118 r#"
3119mod m { pub fn r#type {} }
3120fn main() {
3121 m::r#type();$0
3122}
3123"#,
3124 )
3125 }
3126
3127 #[test]
3128 fn completes_macro_with_raw_identifier() {
3129 check_edit(
3130 "let!",
3131 r#"
3132macro_rules! r#let { () => {} }
3133fn main() {
3134 $0
3135}
3136"#,
3137 r#"
3138macro_rules! r#let { () => {} }
3139fn main() {
3140 r#let!($0)
3141}
3142"#,
3143 )
3144 }
3145
3146 #[test]
3147 fn completes_variant_with_raw_identifier() {
3148 check_edit(
3149 "type",
3150 r#"
3151enum A { r#type }
3152fn main() {
3153 let a = A::t$0
3154}
3155"#,
3156 r#"
3157enum A { r#type }
3158fn main() {
3159 let a = A::r#type$0
3160}
3161"#,
3162 )
3163 }
3164
3165 #[test]
3166 fn completes_field_with_raw_identifier() {
3167 check_edit(
3168 "fn",
3169 r#"
3170mod r#type {
3171 pub struct r#struct {
3172 pub r#fn: u32
3173 }
3174}
3175
3176fn main() {
3177 let a = r#type::r#struct {};
3178 a.$0
3179}
3180"#,
3181 r#"
3182mod r#type {
3183 pub struct r#struct {
3184 pub r#fn: u32
3185 }
3186}
3187
3188fn main() {
3189 let a = r#type::r#struct {};
3190 a.r#fn
3191}
3192"#,
3193 )
3194 }
3195
3196 #[test]
3197 fn completes_const_with_raw_identifier() {
3198 check_edit(
3199 "type",
3200 r#"
3201struct r#struct {}
3202impl r#struct { pub const r#type: u8 = 1; }
3203fn main() {
3204 r#struct::t$0
3205}
3206"#,
3207 r#"
3208struct r#struct {}
3209impl r#struct { pub const r#type: u8 = 1; }
3210fn main() {
3211 r#struct::r#type
3212}
3213"#,
3214 )
3215 }
3216
3217 #[test]
3218 fn completes_type_alias_with_raw_identifier() {
3219 check_edit(
3220 "type type",
3221 r#"
3222struct r#struct {}
3223trait r#trait { type r#type; }
3224impl r#trait for r#struct { type t$0 }
3225"#,
3226 r#"
3227struct r#struct {}
3228trait r#trait { type r#type; }
3229impl r#trait for r#struct { type r#type = $0; }
3230"#,
3231 )
3232 }
3233
3234 #[test]
3235 fn field_access_includes_self() {
3236 check_edit(
3237 "length",
3238 r#"
3239struct S {
3240 length: i32
3241}
3242
3243impl S {
3244 fn some_fn(&self) {
3245 let l = len$0
3246 }
3247}
3248"#,
3249 r#"
3250struct S {
3251 length: i32
3252}
3253
3254impl S {
3255 fn some_fn(&self) {
3256 let l = self.length
3257 }
3258}
3259"#,
3260 )
3261 }
3262
3263 #[test]
3264 fn notable_traits_method_relevance() {
3265 check_kinds(
3266 r#"
3267#[doc(notable_trait)]
3268trait Write {
3269 fn write(&self);
3270 fn flush(&self);
3271}
3272
3273struct Writer;
3274
3275impl Write for Writer {
3276 fn write(&self) {}
3277 fn flush(&self) {}
3278}
3279
3280fn main() {
3281 Writer.$0
3282}
3283"#,
3284 &[
3285 CompletionItemKind::SymbolKind(SymbolKind::Method),
3286 CompletionItemKind::SymbolKind(SymbolKind::Field),
3287 CompletionItemKind::SymbolKind(SymbolKind::Function),
3288 ],
3289 expect![[r#"
3290 [
3291 CompletionItem {
3292 label: "flush()",
3293 detail_left: Some(
3294 "(as Write)",
3295 ),
3296 detail_right: Some(
3297 "fn(&self)",
3298 ),
3299 source_range: 193..193,
3300 delete: 193..193,
3301 insert: "flush();$0",
3302 kind: SymbolKind(
3303 Method,
3304 ),
3305 lookup: "flush",
3306 detail: "fn(&self)",
3307 relevance: CompletionRelevance {
3308 exact_name_match: false,
3309 type_match: None,
3310 is_local: false,
3311 trait_: Some(
3312 CompletionRelevanceTraitInfo {
3313 notable_trait: true,
3314 is_op_method: false,
3315 },
3316 ),
3317 is_name_already_imported: false,
3318 requires_import: false,
3319 is_private_editable: false,
3320 postfix_match: None,
3321 function: None,
3322 is_skipping_completion: false,
3323 },
3324 },
3325 CompletionItem {
3326 label: "write()",
3327 detail_left: Some(
3328 "(as Write)",
3329 ),
3330 detail_right: Some(
3331 "fn(&self)",
3332 ),
3333 source_range: 193..193,
3334 delete: 193..193,
3335 insert: "write();$0",
3336 kind: SymbolKind(
3337 Method,
3338 ),
3339 lookup: "write",
3340 detail: "fn(&self)",
3341 relevance: CompletionRelevance {
3342 exact_name_match: false,
3343 type_match: None,
3344 is_local: false,
3345 trait_: Some(
3346 CompletionRelevanceTraitInfo {
3347 notable_trait: true,
3348 is_op_method: false,
3349 },
3350 ),
3351 is_name_already_imported: false,
3352 requires_import: false,
3353 is_private_editable: false,
3354 postfix_match: None,
3355 function: None,
3356 is_skipping_completion: false,
3357 },
3358 },
3359 ]
3360 "#]],
3361 );
3362 }
3363}