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