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, 'db> {
39 completion: &'a CompletionContext<'a, 'db>,
40 is_private_editable: bool,
41 import_to_add: Option<LocatedImport>,
42 doc_aliases: Vec<SmolStr>,
43}
44
45impl<'a, 'db> RenderContext<'a, 'db> {
46 pub(crate) fn new(completion: &'a CompletionContext<'a, 'db>) -> RenderContext<'a, 'db> {
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) -> &'db 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, def_as_assoc_item: Option<hir::AssocItem>) -> bool {
114 let db = self.db();
115 def.attrs(db).is_deprecated()
116 || def_as_assoc_item
117 .and_then(|assoc| assoc.container_or_implemented_trait(db))
118 .is_some_and(|trait_| {
119 self.is_deprecated(trait_, None )
120 })
121 }
122
123 fn is_variant_deprecated(&self, variant: hir::EnumVariant) -> bool {
128 let db = self.db();
129 variant.attrs(db).is_deprecated() || variant.parent_enum(db).attrs(db).is_deprecated()
130 }
131
132 fn docs(&self, def: impl HasDocs) -> Option<Documentation<'a>> {
134 def.docs(self.db())
135 }
136}
137
138pub(crate) fn render_field(
139 ctx: RenderContext<'_, '_>,
140 dot_access: &DotAccess<'_>,
141 receiver: Option<SmolStr>,
142 field: hir::Field,
143 ty: &hir::Type<'_>,
144) -> CompletionItem {
145 let db = ctx.db();
146 let is_deprecated = ctx.is_deprecated(field, None );
147 let name = field.name(db);
148 let (name, escaped_name) =
149 (name.as_str().to_smolstr(), name.display_no_db(ctx.completion.edition).to_smolstr());
150 let mut item = CompletionItem::new(
151 SymbolKind::Field,
152 ctx.source_range(),
153 field_with_receiver(receiver.as_deref(), &name),
154 ctx.completion.edition,
155 );
156 item.set_relevance(CompletionRelevance {
157 type_match: compute_type_match(ctx.completion, ty),
158 exact_name_match: compute_exact_name_match(ctx.completion, &name),
159 is_skipping_completion: receiver.is_some(),
160 ..CompletionRelevance::default()
161 });
162 item.detail(ty.display(db, ctx.completion.display_target).to_string())
163 .set_documentation(field.docs(db))
164 .set_deprecated(is_deprecated)
165 .lookup_by(name);
166
167 let is_field_access = matches!(dot_access.kind, DotAccessKind::Field { .. });
168 if !is_field_access || ty.is_fn() || ty.is_closure() {
169 let mut builder = TextEdit::builder();
170 builder.replace(
175 ctx.source_range(),
176 field_with_receiver(receiver.as_deref(), &escaped_name).into(),
177 );
178
179 let expected_fn_type =
180 ctx.completion.expected_type.as_ref().is_some_and(|ty| ty.is_fn() || ty.is_closure());
181
182 if !expected_fn_type
183 && let Some(receiver) = &dot_access.receiver
184 && let Some(receiver) = ctx.completion.sema.original_range_opt(receiver.syntax())
185 {
186 builder.insert(receiver.range.start(), "(".to_owned());
187 builder.insert(ctx.source_range().end(), ")".to_owned());
188
189 let is_parens_needed = !matches!(dot_access.kind, DotAccessKind::Method);
190
191 if is_parens_needed {
192 builder.insert(ctx.source_range().end(), "()".to_owned());
193 }
194 }
195
196 item.text_edit(builder.finish());
197 } else {
198 item.insert_text(field_with_receiver(receiver.as_deref(), &escaped_name));
199 }
200 if let Some(receiver) = &dot_access.receiver
201 && let Some(original) = ctx.completion.sema.original_range_opt(receiver.syntax())
202 && let Some(ref_mode) = compute_ref_match(ctx.completion, ty)
203 {
204 item.ref_match(ref_mode, original.range.start());
205 }
206 item.doc_aliases(ctx.doc_aliases);
207 item.build(db)
208}
209
210fn field_with_receiver(receiver: Option<&str>, field_name: &str) -> SmolStr {
211 receiver
212 .map_or_else(|| field_name.into(), |receiver| format_smolstr!("{}.{field_name}", receiver))
213}
214
215pub(crate) fn render_tuple_field(
216 ctx: RenderContext<'_, '_>,
217 receiver: Option<SmolStr>,
218 field: usize,
219 ty: &hir::Type<'_>,
220) -> CompletionItem {
221 let mut item = CompletionItem::new(
222 SymbolKind::Field,
223 ctx.source_range(),
224 field_with_receiver(receiver.as_deref(), &field.to_string()),
225 ctx.completion.edition,
226 );
227 item.detail(ty.display(ctx.db(), ctx.completion.display_target).to_string())
228 .lookup_by(field.to_string());
229 item.set_relevance(CompletionRelevance {
230 is_skipping_completion: receiver.is_some(),
231 ..ctx.completion_relevance()
232 });
233 item.build(ctx.db())
234}
235
236pub(crate) fn render_type_inference(
237 ty_string: String,
238 ctx: &CompletionContext<'_, '_>,
239 path_ctx: &PathCompletionCtx<'_>,
240) -> CompletionItem {
241 let mut builder = CompletionItem::new(
242 CompletionItemKind::InferredType,
243 ctx.source_range(),
244 &ty_string,
245 ctx.edition,
246 );
247 adds_ret_type_arrow(ctx, path_ctx, &mut builder, ty_string);
248 builder.set_relevance(CompletionRelevance {
249 type_match: Some(CompletionRelevanceTypeMatch::Exact),
250 exact_name_match: true,
251 ..Default::default()
252 });
253 builder.build(ctx.db)
254}
255
256pub(crate) fn render_path_resolution<'db>(
257 ctx: RenderContext<'_, 'db>,
258 path_ctx: &PathCompletionCtx<'_>,
259 local_name: hir::Name,
260 resolution: ScopeDef<'db>,
261) -> Builder {
262 render_resolution_path(ctx, path_ctx, local_name, None, resolution)
263}
264
265pub(crate) fn render_pattern_resolution<'db>(
266 ctx: RenderContext<'_, 'db>,
267 pattern_ctx: &PatternContext,
268 local_name: hir::Name,
269 resolution: ScopeDef<'db>,
270) -> Builder {
271 render_resolution_pat(ctx, pattern_ctx, local_name, None, resolution)
272}
273
274pub(crate) fn render_resolution_with_import(
275 ctx: RenderContext<'_, '_>,
276 path_ctx: &PathCompletionCtx<'_>,
277 import_edit: LocatedImport,
278) -> Option<Builder> {
279 let resolution = ScopeDef::from(import_edit.original_item);
280 let local_name = get_import_name(resolution, &ctx, &import_edit)?;
281 let doc_aliases = ctx.completion.doc_aliases_in_scope(resolution);
283 let ctx = ctx.doc_aliases(doc_aliases);
284 Some(render_resolution_path(ctx, path_ctx, local_name, Some(import_edit), resolution))
285}
286
287pub(crate) fn render_resolution_with_import_pat(
288 ctx: RenderContext<'_, '_>,
289 pattern_ctx: &PatternContext,
290 import_edit: LocatedImport,
291) -> Option<Builder> {
292 let resolution = ScopeDef::from(import_edit.original_item);
293 let local_name = get_import_name(resolution, &ctx, &import_edit)?;
294 Some(render_resolution_pat(ctx, pattern_ctx, local_name, Some(import_edit), resolution))
295}
296
297pub(crate) fn render_expr<'db>(
298 ctx: &CompletionContext<'_, 'db>,
299 expr: &hir::term_search::Expr<'db>,
300) -> Option<Builder> {
301 let mut i = 1;
302 let mut snippet_formatter = |ty: &hir::Type<'_>| {
303 let arg_name = ty
304 .as_adt()
305 .map(|adt| stdx::to_lower_snake_case(adt.name(ctx.db).as_str()))
306 .unwrap_or_else(|| String::from("_"));
307 let res = format!("${{{i}:{arg_name}}}");
308 i += 1;
309 res
310 };
311
312 let mut label_formatter = |ty: &hir::Type<'_>| {
313 ty.as_adt()
314 .map(|adt| stdx::to_lower_snake_case(adt.name(ctx.db).as_str()))
315 .unwrap_or_else(|| String::from("..."))
316 };
317
318 let cfg = ctx.config.find_path_config(ctx.is_nightly);
319
320 let label =
321 expr.gen_source_code(&ctx.scope, &mut label_formatter, cfg, ctx.display_target).ok()?;
322
323 let source_range = match ctx.original_token.parent() {
324 Some(node) => match node.ancestors().find_map(ast::Path::cast) {
325 Some(path) => path.syntax().text_range(),
326 None => node.text_range(),
327 },
328 None => ctx.source_range(),
329 };
330
331 let mut item =
332 CompletionItem::new(CompletionItemKind::Expression, source_range, label, ctx.edition);
333
334 let snippet = format!(
335 "{}$0",
336 expr.gen_source_code(&ctx.scope, &mut snippet_formatter, cfg, ctx.display_target).ok()?
337 );
338 let edit = TextEdit::replace(source_range, snippet);
339 item.snippet_edit(ctx.config.snippet_cap?, edit);
340 item.documentation(Documentation::new_owned(String::from(
341 "Autogenerated expression by term search",
342 )));
343 item.set_relevance(crate::CompletionRelevance {
344 type_match: compute_type_match(ctx, &ctx.rebase_ty(&expr.ty(ctx.db))),
345 ..Default::default()
346 });
347 for trait_ in expr.traits_used(ctx.db) {
348 let trait_item = hir::ItemInNs::from(hir::ModuleDef::from(trait_));
349 let Some(path) = ctx.module.find_path(ctx.db, trait_item, cfg) else {
350 continue;
351 };
352
353 item.add_import(LocatedImport::new_no_completion(path, trait_item, trait_item));
354 }
355
356 Some(item)
357}
358
359fn get_import_name<'db>(
360 resolution: ScopeDef<'db>,
361 ctx: &RenderContext<'_, 'db>,
362 import_edit: &LocatedImport,
363) -> Option<hir::Name> {
364 if import_edit.item_to_import == import_edit.original_item {
371 import_edit.import_path.segments().last().cloned()
372 } else {
373 scope_def_to_name(resolution, ctx, import_edit)
374 }
375}
376
377fn scope_def_to_name<'db>(
378 resolution: ScopeDef<'db>,
379 ctx: &RenderContext<'_, 'db>,
380 import_edit: &LocatedImport,
381) -> Option<hir::Name> {
382 Some(match resolution {
383 ScopeDef::ModuleDef(hir::ModuleDef::Function(f)) => f.name(ctx.completion.db),
384 ScopeDef::ModuleDef(hir::ModuleDef::Const(c)) => c.name(ctx.completion.db)?,
385 ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(t)) => t.name(ctx.completion.db),
386 _ => item_name(ctx.db(), import_edit.original_item)?,
387 })
388}
389
390fn render_resolution_pat<'db>(
391 ctx: RenderContext<'_, 'db>,
392 pattern_ctx: &PatternContext,
393 local_name: hir::Name,
394 import_to_add: Option<LocatedImport>,
395 resolution: ScopeDef<'db>,
396) -> Builder {
397 let _p = tracing::info_span!("render_resolution_pat").entered();
398 use hir::ModuleDef::*;
399
400 if let ScopeDef::ModuleDef(Macro(mac)) = resolution {
401 let ctx = ctx.import_to_add(import_to_add);
402 render_macro_pat(ctx, pattern_ctx, local_name, mac)
403 } else {
404 render_resolution_simple_(ctx, &local_name, import_to_add, resolution)
405 }
406}
407
408fn render_resolution_path<'db>(
409 ctx: RenderContext<'_, 'db>,
410 path_ctx: &PathCompletionCtx<'_>,
411 local_name: hir::Name,
412 import_to_add: Option<LocatedImport>,
413 resolution: ScopeDef<'db>,
414) -> Builder {
415 let _p = tracing::info_span!("render_resolution_path").entered();
416 use hir::ModuleDef::*;
417
418 let krate = ctx.completion.display_target;
419
420 match resolution {
421 ScopeDef::ModuleDef(Macro(mac)) => {
422 let ctx = ctx.import_to_add(import_to_add);
423 return render_macro(ctx, path_ctx, local_name, mac);
424 }
425 ScopeDef::ModuleDef(Function(func)) => {
426 let ctx = ctx.import_to_add(import_to_add);
427 return render_fn(ctx, path_ctx, Some(local_name), func);
428 }
429 ScopeDef::ModuleDef(EnumVariant(var)) => {
430 let ctx = ctx.clone().import_to_add(import_to_add.clone());
431 if let Some(item) =
432 render_variant_lit(ctx, path_ctx, Some(local_name.clone()), var, None)
433 {
434 return item;
435 }
436 }
437 _ => (),
438 }
439
440 let completion = ctx.completion;
441 let module = completion.module;
442 let cap = ctx.snippet_cap();
443 let db = completion.db;
444 let config = completion.config;
445 let requires_import = import_to_add.is_some();
446
447 let name = local_name.display(db, completion.edition).to_smolstr();
448 let mut item = render_resolution_simple_(ctx, &local_name, import_to_add, resolution);
449 let mut insert_text = name.clone();
450
451 let type_path_no_ty_args = matches!(
453 path_ctx,
454 PathCompletionCtx { kind: PathKind::Type { .. }, has_type_args: false, .. }
455 ) && config.callable.is_some();
456 if type_path_no_ty_args && let Some(cap) = cap {
457 let has_non_default_type_params = match resolution {
458 ScopeDef::ModuleDef(hir::ModuleDef::Adt(it)) => it.has_non_default_type_params(db),
459 ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(it)) => {
460 it.has_non_default_type_params(db)
461 }
462 _ => false,
463 };
464
465 if has_non_default_type_params {
466 cov_mark::hit!(inserts_angle_brackets_for_generics);
467 insert_text = format_smolstr!("{insert_text}<$0>");
468 item.lookup_by(name.clone())
469 .label(SmolStr::from_iter([&name, "<…>"]))
470 .trigger_call_info()
471 .insert_snippet(cap, ""); }
473 }
474 let allow_module_path = matches!(path_ctx.kind, PathKind::Use)
475 || completion.token.next_token().is_some_and(|it| it.kind() == syntax::T![::])
476 || !config.add_colons_to_module;
477 if !allow_module_path && matches!(resolution, ScopeDef::ModuleDef(Module(_))) {
478 insert_text = format_smolstr!("{insert_text}::");
479 item.lookup_by(name.clone()).label(insert_text.clone());
480 }
481 adds_ret_type_arrow(completion, path_ctx, &mut item, insert_text.into());
482
483 let mut set_item_relevance = |ty: Type<'db>| {
484 if !ty.is_unknown() {
485 item.detail(ty.display(db, krate).to_string());
486 }
487
488 let ty = completion.rebase_ty(&ty);
489 item.set_relevance(CompletionRelevance {
490 type_match: compute_type_match(completion, &ty),
491 exact_name_match: compute_exact_name_match(completion, &name),
492 is_local: matches!(resolution, ScopeDef::Local(_)),
493 requires_import,
494 has_local_inherent_impl: compute_has_local_inherent_impl(db, path_ctx, &ty, module),
495 ..CompletionRelevance::default()
496 });
497
498 match resolution {
499 ScopeDef::Local(_)
500 | ScopeDef::ModuleDef(ModuleDef::Const(_) | ModuleDef::Static(_)) => {
501 path_ref_match(completion, path_ctx, &ty, &mut item)
502 }
503 _ => (),
504 }
505 };
506
507 match resolution {
508 ScopeDef::Local(local) => set_item_relevance(local.ty(db)),
509 ScopeDef::ModuleDef(ModuleDef::Adt(adt)) | ScopeDef::AdtSelfType(adt) => {
510 set_item_relevance(adt.ty(db))
511 }
512 ScopeDef::ModuleDef(
514 ModuleDef::Function(_) | ModuleDef::EnumVariant(_) | ModuleDef::Macro(_),
515 ) => (),
516 ScopeDef::ModuleDef(ModuleDef::Const(konst)) => set_item_relevance(konst.ty(db)),
517 ScopeDef::ModuleDef(ModuleDef::Static(stat)) => set_item_relevance(stat.ty(db)),
518 ScopeDef::ModuleDef(ModuleDef::BuiltinType(bt)) => set_item_relevance(bt.ty(db)),
519 ScopeDef::ModuleDef(ModuleDef::TypeAlias(ta)) => set_item_relevance(ta.ty(db)),
520 ScopeDef::ImplSelfType(imp) => set_item_relevance(imp.self_ty(db)),
521 ScopeDef::GenericParam(_)
522 | ScopeDef::Label(_)
523 | ScopeDef::Unknown
524 | ScopeDef::ModuleDef(ModuleDef::Trait(_) | ModuleDef::Module(_)) => (),
525 };
526
527 item
528}
529
530fn render_resolution_simple_<'db>(
531 ctx: RenderContext<'_, 'db>,
532 local_name: &hir::Name,
533 import_to_add: Option<LocatedImport>,
534 resolution: ScopeDef<'db>,
535) -> Builder {
536 let _p = tracing::info_span!("render_resolution_simple_").entered();
537
538 let db = ctx.db();
539 let ctx = ctx.import_to_add(import_to_add);
540 let kind = res_to_kind(resolution);
541
542 let mut item = CompletionItem::new(
543 kind,
544 ctx.source_range(),
545 local_name.as_str().to_smolstr(),
546 ctx.completion.edition,
547 );
548 if let ScopeDef::ModuleDef(ModuleDef::Const(konst)) = resolution {
549 item.const_value(Some(konst), db, ctx.completion.display_target);
550 }
551 item.set_relevance(ctx.completion_relevance())
552 .set_documentation(scope_def_docs(db, resolution))
553 .set_deprecated(scope_def_is_deprecated(&ctx, resolution));
554
555 if let Some(import_to_add) = ctx.import_to_add {
556 item.add_import(import_to_add);
557 }
558
559 item.doc_aliases(ctx.doc_aliases);
560 item
561}
562
563fn res_to_kind(resolution: ScopeDef<'_>) -> CompletionItemKind {
564 use hir::ModuleDef::*;
565 match resolution {
566 ScopeDef::Unknown => CompletionItemKind::UnresolvedReference,
567 ScopeDef::ModuleDef(Function(_)) => CompletionItemKind::SymbolKind(SymbolKind::Function),
568 ScopeDef::ModuleDef(EnumVariant(_)) => CompletionItemKind::SymbolKind(SymbolKind::Variant),
569 ScopeDef::ModuleDef(Macro(_)) => CompletionItemKind::SymbolKind(SymbolKind::Macro),
570 ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::SymbolKind(SymbolKind::Module),
571 ScopeDef::ModuleDef(Adt(adt)) => CompletionItemKind::SymbolKind(match adt {
572 hir::Adt::Struct(_) => SymbolKind::Struct,
573 hir::Adt::Union(_) => SymbolKind::Union,
574 hir::Adt::Enum(_) => SymbolKind::Enum,
575 }),
576 ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::SymbolKind(SymbolKind::Const),
577 ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::SymbolKind(SymbolKind::Static),
578 ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::SymbolKind(SymbolKind::Trait),
579 ScopeDef::ModuleDef(TypeAlias(..)) => CompletionItemKind::SymbolKind(SymbolKind::TypeAlias),
580 ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType,
581 ScopeDef::GenericParam(param) => CompletionItemKind::SymbolKind(match param {
582 hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam,
583 hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam,
584 hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam,
585 }),
586 ScopeDef::Local(..) => CompletionItemKind::SymbolKind(SymbolKind::Local),
587 ScopeDef::Label(..) => CompletionItemKind::SymbolKind(SymbolKind::Label),
588 ScopeDef::AdtSelfType(..) | ScopeDef::ImplSelfType(..) => {
589 CompletionItemKind::SymbolKind(SymbolKind::SelfParam)
590 }
591 }
592}
593
594fn scope_def_docs<'db>(
595 db: &'db RootDatabase,
596 resolution: ScopeDef<'db>,
597) -> Option<Documentation<'db>> {
598 use hir::ModuleDef::*;
599 match resolution {
600 ScopeDef::ModuleDef(Module(it)) => it.docs(db),
601 ScopeDef::ModuleDef(Adt(it)) => it.docs(db),
602 ScopeDef::ModuleDef(EnumVariant(it)) => it.docs(db),
603 ScopeDef::ModuleDef(Const(it)) => it.docs(db),
604 ScopeDef::ModuleDef(Static(it)) => it.docs(db),
605 ScopeDef::ModuleDef(Trait(it)) => it.docs(db),
606 ScopeDef::ModuleDef(TypeAlias(it)) => it.docs(db),
607 _ => None,
608 }
609}
610
611fn scope_def_is_deprecated(ctx: &RenderContext<'_, '_>, resolution: ScopeDef<'_>) -> bool {
612 let db = ctx.db();
613 match resolution {
614 ScopeDef::ModuleDef(hir::ModuleDef::EnumVariant(it)) => ctx.is_variant_deprecated(it),
615 ScopeDef::ModuleDef(it) => ctx.is_deprecated(it, it.as_assoc_item(db)),
616 ScopeDef::GenericParam(it) => {
617 ctx.is_deprecated(it, None )
618 }
619 ScopeDef::AdtSelfType(it) => {
620 ctx.is_deprecated(it, None )
621 }
622 _ => false,
623 }
624}
625
626pub(crate) fn render_type_keyword_snippet(
627 ctx: &CompletionContext<'_, '_>,
628 path_ctx: &PathCompletionCtx<'_>,
629 label: &str,
630 snippet: &str,
631) -> Builder {
632 let source_range = ctx.source_range();
633 let mut item =
634 CompletionItem::new(CompletionItemKind::Keyword, source_range, label, ctx.edition);
635
636 let insert_text = if !snippet.contains('$') {
637 item.insert_text(snippet);
638 snippet
639 } else if let Some(cap) = ctx.config.snippet_cap {
640 item.insert_snippet(cap, snippet);
641 snippet
642 } else {
643 label
644 };
645
646 adds_ret_type_arrow(ctx, path_ctx, &mut item, insert_text.to_owned());
647 item
648}
649
650fn adds_ret_type_arrow(
651 ctx: &CompletionContext<'_, '_>,
652 path_ctx: &PathCompletionCtx<'_>,
653 item: &mut Builder,
654 insert_text: String,
655) {
656 if let Some((arrow, at)) = path_ctx.required_thin_arrow(&ctx.sema) {
657 let mut edit = TextEdit::builder();
658
659 edit.insert(at, arrow.to_owned());
660 edit.replace(ctx.source_range(), insert_text);
661
662 item.text_edit(edit.finish()).adds_text(SmolStr::new_static(arrow));
663 } else {
664 item.insert_text(insert_text);
665 }
666}
667
668fn match_types(
670 ctx: &CompletionContext<'_, '_>,
671 ty1: &hir::Type<'_>,
672 ty2: &hir::Type<'_>,
673) -> Option<CompletionRelevanceTypeMatch> {
674 if ty1 == ty2 {
675 Some(CompletionRelevanceTypeMatch::Exact)
676 } else if ty1.could_unify_with(ctx.db, ty2) {
677 Some(CompletionRelevanceTypeMatch::CouldUnify)
678 } else {
679 None
680 }
681}
682
683fn compute_type_match(
684 ctx: &CompletionContext<'_, '_>,
685 completion_ty: &hir::Type<'_>,
686) -> Option<CompletionRelevanceTypeMatch> {
687 let expected_type = ctx.expected_type.as_ref()?;
688
689 if expected_type.is_unit() || completion_ty.is_unit() {
692 return None;
693 }
694 if expected_type.is_unknown() || completion_ty.is_unknown() {
695 return None;
696 }
697
698 if completion_ty.is_mutable_reference()
700 && let Some((expected_type, _)) = expected_type.as_reference()
701 && let Some((completion_ty, _)) = completion_ty.as_reference()
702 {
703 return match_types(ctx, &expected_type, &completion_ty);
704 }
705
706 match_types(ctx, expected_type, completion_ty)
707}
708
709fn compute_has_local_inherent_impl(
710 db: &RootDatabase,
711 path_ctx: &PathCompletionCtx<'_>,
712 completion_ty: &hir::Type<'_>,
713 curr_module: hir::Module,
714) -> bool {
715 matches!(path_ctx.kind, PathKind::Type { location: TypeLocation::ImplTarget })
716 && Impl::all_for_type(db, completion_ty.clone())
717 .iter()
718 .any(|imp| imp.trait_(db).is_none() && imp.module(db) == curr_module)
719}
720
721fn compute_exact_name_match(ctx: &CompletionContext<'_, '_>, completion_name: &str) -> bool {
722 ctx.expected_name.as_ref().is_some_and(|name| {
723 let name = name.text().strip_prefix("r#").unwrap_or(name.text());
724 let completion_name = completion_name.strip_prefix("r#").unwrap_or(completion_name);
725 name.trim_matches('_') == completion_name.trim_matches('_')
726 })
727}
728
729fn compute_ref_match(
730 ctx: &CompletionContext<'_, '_>,
731 completion_ty: &hir::Type<'_>,
732) -> Option<CompletionItemRefMode> {
733 if compute_type_match(ctx, completion_ty).is_some() || completion_ty.is_unit() {
734 return None;
735 }
736 let expected_type = ctx.expected_type.as_ref()?;
737 let expected_without_ref = expected_type.as_reference();
738 let completion_without_ref = completion_ty.as_reference();
739
740 if let Some((expected_without_ref, _)) = &expected_without_ref
741 && (completion_without_ref.is_none()
742 || completion_ty.could_unify_with(ctx.db, expected_without_ref))
743 && completion_ty
744 .autoderef(ctx.db)
745 .any(|ty| !ty.is_unknown() && ty.could_unify_with(ctx.db, expected_without_ref))
746 {
747 cov_mark::hit!(suggest_ref);
748 let mutability = if expected_type.is_mutable_reference() {
749 hir::Mutability::Mut
750 } else {
751 hir::Mutability::Shared
752 };
753 return Some(CompletionItemRefMode::Reference(mutability));
754 }
755
756 if let Some((completion_without_ref, _)) = completion_without_ref
757 && completion_without_ref == *expected_type
758 && completion_without_ref.is_copy(ctx.db)
759 {
760 cov_mark::hit!(suggest_deref);
761 return Some(CompletionItemRefMode::Dereference);
762 }
763
764 None
765}
766
767fn path_ref_match(
768 completion: &CompletionContext<'_, '_>,
769 path_ctx: &PathCompletionCtx<'_>,
770 ty: &hir::Type<'_>,
771 item: &mut Builder,
772) {
773 if let Some(original_path) = &path_ctx.original_path {
774 if let Some(original_path) = completion.sema.original_range_opt(original_path.syntax())
776 && let Some(ref_mode) = compute_ref_match(completion, ty)
777 {
778 item.ref_match(ref_mode, original_path.range.start());
779 }
780 } else {
781 if let Some(ref_mode) = compute_ref_match(completion, ty) {
785 item.ref_match(ref_mode, completion.source_range().start());
786 }
787 }
788}
789
790#[cfg(test)]
791mod tests {
792 use std::cmp;
793
794 use expect_test::{Expect, expect};
795 use ide_db::SymbolKind;
796 use itertools::Itertools;
797
798 use crate::{
799 CompletionItem, CompletionItemKind, CompletionRelevance, CompletionRelevancePostfixMatch,
800 item::CompletionRelevanceTypeMatch,
801 tests::{TEST_CONFIG, check_edit, do_completion, get_all_items},
802 };
803
804 #[track_caller]
805 fn check(
806 #[rust_analyzer::rust_fixture] ra_fixture: &str,
807 kind: impl Into<CompletionItemKind>,
808 expect: Expect,
809 ) {
810 let actual = do_completion(ra_fixture, kind.into());
811 expect.assert_debug_eq(&actual);
812 }
813
814 #[track_caller]
815 fn check_kinds(
816 #[rust_analyzer::rust_fixture] ra_fixture: &str,
817 kinds: &[CompletionItemKind],
818 expect: Expect,
819 ) {
820 let actual: Vec<_> =
821 kinds.iter().flat_map(|&kind| do_completion(ra_fixture, kind)).collect();
822 expect.assert_debug_eq(&actual);
823 }
824
825 #[track_caller]
826 fn check_function_relevance(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
827 let actual: Vec<_> =
828 do_completion(ra_fixture, CompletionItemKind::SymbolKind(SymbolKind::Method))
829 .into_iter()
830 .map(|item| (item.detail.unwrap_or_default(), item.relevance.function))
831 .collect();
832
833 expect.assert_debug_eq(&actual);
834 }
835
836 #[track_caller]
837 fn check_relevance_for_kinds(
838 #[rust_analyzer::rust_fixture] ra_fixture: &str,
839 kinds: &[CompletionItemKind],
840 expect: Expect,
841 ) {
842 let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
843 actual.retain(|it| kinds.contains(&it.kind));
844 actual.sort_by_key(|it| (cmp::Reverse(it.relevance.score()), it.label.primary.clone()));
845 check_relevance_(actual, expect);
846 }
847
848 #[track_caller]
849 fn check_relevance(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
850 let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
851 actual.retain(|it| it.kind != CompletionItemKind::Snippet);
852 actual.retain(|it| it.kind != CompletionItemKind::Keyword);
853 actual.retain(|it| it.kind != CompletionItemKind::BuiltinType);
854 actual.sort_by_key(|it| (cmp::Reverse(it.relevance.score()), it.label.primary.clone()));
855 check_relevance_(actual, expect);
856 }
857
858 #[track_caller]
859 fn check_relevance_(actual: Vec<CompletionItem>, expect: Expect) {
860 let actual = actual
861 .into_iter()
862 .flat_map(|it| {
863 let mut items = vec![];
864
865 let tag = it.kind.tag();
866 let relevance = display_relevance(it.relevance);
867 items.push(format!(
868 "{tag} {} {} {relevance}\n",
869 it.label.primary,
870 it.label.detail_right.as_deref().unwrap_or_default(),
871 ));
872
873 if let Some((label, _indel, relevance)) = it.ref_match() {
874 let relevance = display_relevance(relevance);
875
876 items.push(format!("{tag} {label} {relevance}\n"));
877 }
878
879 items
880 })
881 .collect::<String>();
882
883 expect.assert_eq(&actual);
884
885 fn display_relevance(relevance: CompletionRelevance) -> String {
886 let CompletionRelevance {
887 exact_name_match,
888 type_match,
889 is_local,
890 is_missing,
891 trait_,
892 is_name_already_imported: _,
893 requires_import,
894 is_private_editable: _,
895 postfix_match,
896 function: _,
897 is_skipping_completion: _,
898 has_local_inherent_impl,
899 is_deprecated,
900 } = relevance;
901 let relevance_factors = [
902 (type_match == Some(CompletionRelevanceTypeMatch::Exact), "type"),
903 (type_match == Some(CompletionRelevanceTypeMatch::CouldUnify), "type_could_unify"),
904 (exact_name_match, "name"),
905 (is_local, "local"),
906 (is_missing, "missing"),
907 (postfix_match == Some(CompletionRelevancePostfixMatch::Exact), "snippet"),
908 (trait_.is_some_and(|it| it.is_op_method), "op_method"),
909 (requires_import, "requires_import"),
910 (has_local_inherent_impl, "has_local_inherent_impl"),
911 (is_deprecated, "deprecated"),
912 ]
913 .into_iter()
914 .filter_map(|(cond, desc)| cond.then_some(desc))
915 .join("+");
916
917 format!("[{relevance_factors}]")
918 }
919 }
920
921 #[test]
922 fn trait_imported_as_underscore_should_not_appear_auto_import_again() {
923 check_relevance(
926 r#"
927//- /dep.rs crate:dep
928pub trait MyTrait {
929 fn my_method(&self);
930}
931
932//- /main.rs crate:main deps:dep
933use dep::MyTrait as _;
934struct MyStruct;
935impl dep::MyTrait for MyStruct {
936 fn my_method(&self) {}
937}
938fn main() {
939 MyStruct::my_method$0
940}
941"#,
942 expect![[r#"
943 me my_method(…) fn(&self) []
944 "#]],
945 );
946 }
947
948 #[test]
949 fn set_struct_type_completion_info() {
950 check_relevance(
951 r#"
952//- /lib.rs crate:dep
953
954pub mod test_mod_b {
955 pub struct Struct {}
956}
957
958pub mod test_mod_a {
959 pub struct Struct {}
960}
961
962//- /main.rs crate:main deps:dep
963
964fn test(input: dep::test_mod_b::Struct) { }
965
966fn main() {
967 test(Struct$0);
968}
969"#,
970 expect![[r#"
971 st dep::test_mod_b::Struct {…} dep::test_mod_b::Struct { } [type]
972 ex dep::test_mod_b::Struct { } [type]
973 st Struct Struct [type+requires_import]
974 md dep:: []
975 fn main() fn() []
976 fn test(…) fn(Struct) []
977 st Struct Struct [requires_import]
978 "#]],
979 );
980 }
981
982 #[test]
983 fn set_union_type_completion_info() {
984 check_relevance(
985 r#"
986//- /lib.rs crate:dep
987
988pub mod test_mod_b {
989 pub union Union {
990 a: i32,
991 b: i32
992 }
993}
994
995pub mod test_mod_a {
996 pub enum Union {
997 a: i32,
998 b: i32
999 }
1000}
1001
1002//- /main.rs crate:main deps:dep
1003
1004fn test(input: dep::test_mod_b::Union) { }
1005
1006fn main() {
1007 test(Union$0);
1008}
1009"#,
1010 expect![[r#"
1011 un Union Union [type+requires_import]
1012 md dep:: []
1013 fn main() fn() []
1014 fn test(…) fn(Union) []
1015 en Union Union [requires_import]
1016 "#]],
1017 );
1018 }
1019
1020 #[test]
1021 fn set_enum_type_completion_info() {
1022 check_relevance(
1023 r#"
1024//- /lib.rs crate:dep
1025
1026pub mod test_mod_b {
1027 pub enum Enum {
1028 variant
1029 }
1030}
1031
1032pub mod test_mod_a {
1033 pub enum Enum {
1034 variant
1035 }
1036}
1037
1038//- /main.rs crate:main deps:dep
1039
1040fn test(input: dep::test_mod_b::Enum) { }
1041
1042fn main() {
1043 test(Enum$0);
1044}
1045"#,
1046 expect![[r#"
1047 ev dep::test_mod_b::Enum::variant dep::test_mod_b::Enum::variant [type]
1048 ex dep::test_mod_b::Enum::variant [type]
1049 en Enum Enum [type+requires_import]
1050 md dep:: []
1051 fn main() fn() []
1052 fn test(…) fn(Enum) []
1053 en Enum Enum [requires_import]
1054 "#]],
1055 );
1056 }
1057
1058 #[test]
1059 fn set_enum_variant_type_completion_info() {
1060 check_relevance(
1061 r#"
1062//- /lib.rs crate:dep
1063
1064pub mod test_mod_b {
1065 pub enum Enum {
1066 Variant
1067 }
1068}
1069
1070pub mod test_mod_a {
1071 pub enum Enum {
1072 Variant
1073 }
1074}
1075
1076//- /main.rs crate:main deps:dep
1077
1078fn test(input: dep::test_mod_b::Enum) { }
1079
1080fn main() {
1081 test(Variant$0);
1082}
1083"#,
1084 expect![[r#"
1085 ev dep::test_mod_b::Enum::Variant dep::test_mod_b::Enum::Variant [type]
1086 ex dep::test_mod_b::Enum::Variant [type]
1087 ev Variant Variant [type+requires_import]
1088 md dep:: []
1089 fn main() fn() []
1090 fn test(…) fn(Enum) []
1091 ev Variant Variant [requires_import]
1092 "#]],
1093 );
1094 }
1095
1096 #[test]
1097 fn set_fn_type_completion_info() {
1098 check_relevance(
1099 r#"
1100//- /lib.rs crate:dep
1101
1102pub mod test_mod_b {
1103 pub fn function(j: isize) -> i32 {}
1104}
1105
1106pub mod test_mod_a {
1107 pub fn function(i: usize) -> i32 {}
1108}
1109
1110//- /main.rs crate:main deps:dep
1111
1112fn test(input: fn(usize) -> i32) { }
1113
1114fn main() {
1115 test(function$0);
1116}
1117"#,
1118 expect![[r#"
1119 md dep:: []
1120 fn main() fn() []
1121 fn test(…) fn(fn(usize) -> i32) []
1122 fn function fn(usize) -> i32 [requires_import]
1123 fn function(…) fn(isize) -> i32 [requires_import]
1124 "#]],
1125 );
1126 }
1127
1128 #[test]
1129 fn set_const_type_completion_info() {
1130 check_relevance(
1131 r#"
1132//- /lib.rs crate:dep
1133
1134pub mod test_mod_b {
1135 pub const CONST: i32 = 1;
1136}
1137
1138pub mod test_mod_a {
1139 pub const CONST: i64 = 2;
1140}
1141
1142//- /main.rs crate:main deps:dep
1143
1144fn test(input: i32) { }
1145
1146fn main() {
1147 test(CONST$0);
1148}
1149"#,
1150 expect![[r#"
1151 ct CONST i32 [type+requires_import]
1152 md dep:: []
1153 fn main() fn() []
1154 fn test(…) fn(i32) []
1155 ct CONST i64 [requires_import]
1156 "#]],
1157 );
1158 }
1159
1160 #[test]
1161 fn set_static_type_completion_info() {
1162 check_relevance(
1163 r#"
1164//- /lib.rs crate:dep
1165
1166pub mod test_mod_b {
1167 pub static STATIC: i32 = 5;
1168}
1169
1170pub mod test_mod_a {
1171 pub static STATIC: i64 = 5;
1172}
1173
1174//- /main.rs crate:main deps:dep
1175
1176fn test(input: i32) { }
1177
1178fn main() {
1179 test(STATIC$0);
1180}
1181"#,
1182 expect![[r#"
1183 sc STATIC i32 [type+requires_import]
1184 md dep:: []
1185 fn main() fn() []
1186 fn test(…) fn(i32) []
1187 sc STATIC i64 [requires_import]
1188 "#]],
1189 );
1190 }
1191
1192 #[test]
1193 fn set_self_type_completion_info_with_params() {
1194 check_relevance(
1195 r#"
1196//- /lib.rs crate:dep
1197pub struct Struct;
1198
1199impl Struct {
1200 pub fn Function(&self, input: i32) -> bool {
1201 false
1202 }
1203}
1204
1205
1206//- /main.rs crate:main deps:dep
1207
1208use dep::Struct;
1209
1210
1211fn test(input: fn(&dep::Struct, i32) -> bool) { }
1212
1213fn main() {
1214 test(Struct::Function$0);
1215}
1216
1217"#,
1218 expect![[r#"
1219 me Function fn(&self, i32) -> bool []
1220 "#]],
1221 );
1222 }
1223
1224 #[test]
1225 fn set_self_type_completion_info() {
1226 check_relevance(
1227 r#"
1228//- /main.rs crate:main
1229
1230struct Struct;
1231
1232impl Struct {
1233fn test(&self) {
1234 func(Self$0);
1235 }
1236}
1237
1238fn func(input: Struct) { }
1239
1240"#,
1241 expect![[r#"
1242 st Self Self [type]
1243 st Struct Struct [type]
1244 sp Self Struct [type]
1245 st Struct Struct [type]
1246 ex Struct [type]
1247 lc self &Struct [local]
1248 fn func(…) fn(Struct) []
1249 me self.test() fn(&self) []
1250 "#]],
1251 );
1252 }
1253
1254 #[test]
1255 fn set_type_alias_completion_info() {
1256 check_relevance(
1257 r#"
1258//- /main.rs crate:main
1259struct Struct;
1260type Alias = Struct;
1261
1262impl Struct {
1263 fn test(&self) {
1264 func(Self$0);
1265 }
1266}
1267fn func(input: Struct) { }
1268"#,
1269 expect![[r#"
1270 st Self Self [type]
1271 st Struct Struct [type]
1272 ta Alias Struct [type]
1273 sp Self Struct [type]
1274 st Struct Struct [type]
1275 ex Struct [type]
1276 lc self &Struct [local]
1277 fn func(…) fn(Struct) []
1278 me self.test() fn(&self) []
1279 "#]],
1280 );
1281 }
1282
1283 #[test]
1284 fn set_builtin_type_completion_info() {
1285 check_relevance(
1286 r#"
1287//- /main.rs crate:main
1288
1289fn test(input: bool) { }
1290 pub Input: bool = false;
1291
1292fn main() {
1293 let input = false;
1294 let inputbad = 3;
1295 test(inp$0);
1296}
1297"#,
1298 expect![[r#"
1299 lc input bool [type+name+local]
1300 ex false [type]
1301 ex input [type]
1302 ex true [type]
1303 lc inputbad i32 [local]
1304 fn main() fn() []
1305 fn test(…) fn(bool) []
1306 "#]],
1307 );
1308 }
1309
1310 #[test]
1311 fn enum_detail_includes_record_fields() {
1312 check(
1313 r#"
1314enum Foo { Foo { x: i32, y: i32 } }
1315
1316fn main() { Foo::Fo$0 }
1317"#,
1318 SymbolKind::Variant,
1319 expect![[r#"
1320 [
1321 CompletionItem {
1322 label: "Foo {…}",
1323 detail_left: None,
1324 detail_right: Some(
1325 "Foo { x: i32, y: i32 }",
1326 ),
1327 source_range: 54..56,
1328 delete: 54..56,
1329 insert: "Foo { x: ${1:()}, y: ${2:()} }$0",
1330 kind: SymbolKind(
1331 Variant,
1332 ),
1333 lookup: "Foo{}",
1334 detail: "Foo { x: i32, y: i32 }",
1335 relevance: CompletionRelevance {
1336 exact_name_match: false,
1337 type_match: None,
1338 is_local: false,
1339 is_missing: false,
1340 trait_: None,
1341 is_name_already_imported: false,
1342 requires_import: false,
1343 is_private_editable: false,
1344 postfix_match: None,
1345 function: Some(
1346 CompletionRelevanceFn {
1347 has_params: true,
1348 has_self_param: false,
1349 return_type: DirectConstructor,
1350 },
1351 ),
1352 is_skipping_completion: false,
1353 has_local_inherent_impl: false,
1354 is_deprecated: false,
1355 },
1356 trigger_call_info: true,
1357 },
1358 ]
1359 "#]],
1360 );
1361 }
1362
1363 #[test]
1364 fn enum_detail_includes_tuple_fields() {
1365 check(
1366 r#"
1367enum Foo { Foo (i32, i32) }
1368
1369fn main() { Foo::Fo$0 }
1370"#,
1371 SymbolKind::Variant,
1372 expect![[r#"
1373 [
1374 CompletionItem {
1375 label: "Foo(…)",
1376 detail_left: None,
1377 detail_right: Some(
1378 "Foo(i32, i32)",
1379 ),
1380 source_range: 46..48,
1381 delete: 46..48,
1382 insert: "Foo(${1:()}, ${2:()})$0",
1383 kind: SymbolKind(
1384 Variant,
1385 ),
1386 lookup: "Foo()",
1387 detail: "Foo(i32, i32)",
1388 relevance: CompletionRelevance {
1389 exact_name_match: false,
1390 type_match: None,
1391 is_local: false,
1392 is_missing: false,
1393 trait_: None,
1394 is_name_already_imported: false,
1395 requires_import: false,
1396 is_private_editable: false,
1397 postfix_match: None,
1398 function: Some(
1399 CompletionRelevanceFn {
1400 has_params: true,
1401 has_self_param: false,
1402 return_type: DirectConstructor,
1403 },
1404 ),
1405 is_skipping_completion: false,
1406 has_local_inherent_impl: false,
1407 is_deprecated: false,
1408 },
1409 trigger_call_info: true,
1410 },
1411 ]
1412 "#]],
1413 );
1414 }
1415
1416 #[test]
1417 fn fn_detail_includes_args_and_return_type() {
1418 check(
1419 r#"
1420fn foo<T>(a: u32, b: u32, t: T) -> (u32, T) { (a, t) }
1421
1422fn main() { fo$0 }
1423"#,
1424 SymbolKind::Function,
1425 expect![[r#"
1426 [
1427 CompletionItem {
1428 label: "foo(…)",
1429 detail_left: None,
1430 detail_right: Some(
1431 "fn(u32, u32, T) -> (u32, T)",
1432 ),
1433 source_range: 68..70,
1434 delete: 68..70,
1435 insert: "foo(${1:a}, ${2:b}, ${3:t})$0",
1436 kind: SymbolKind(
1437 Function,
1438 ),
1439 lookup: "foo",
1440 detail: "fn(u32, u32, T) -> (u32, T)",
1441 trigger_call_info: true,
1442 },
1443 CompletionItem {
1444 label: "main()",
1445 detail_left: None,
1446 detail_right: Some(
1447 "fn()",
1448 ),
1449 source_range: 68..70,
1450 delete: 68..70,
1451 insert: "main();$0",
1452 kind: SymbolKind(
1453 Function,
1454 ),
1455 lookup: "main",
1456 detail: "fn()",
1457 },
1458 ]
1459 "#]],
1460 );
1461 }
1462
1463 #[test]
1464 fn fn_detail_includes_variadics() {
1465 check(
1466 r#"
1467unsafe extern "C" fn foo(a: u32, b: u32, ...) {}
1468
1469fn main() { fo$0 }
1470"#,
1471 SymbolKind::Function,
1472 expect![[r#"
1473 [
1474 CompletionItem {
1475 label: "foo(…)",
1476 detail_left: None,
1477 detail_right: Some(
1478 "unsafe fn(u32, u32, ...)",
1479 ),
1480 source_range: 62..64,
1481 delete: 62..64,
1482 insert: "foo(${1:a}, ${2:b});$0",
1483 kind: SymbolKind(
1484 Function,
1485 ),
1486 lookup: "foo",
1487 detail: "unsafe fn(u32, u32, ...)",
1488 trigger_call_info: true,
1489 },
1490 CompletionItem {
1491 label: "main()",
1492 detail_left: None,
1493 detail_right: Some(
1494 "fn()",
1495 ),
1496 source_range: 62..64,
1497 delete: 62..64,
1498 insert: "main();$0",
1499 kind: SymbolKind(
1500 Function,
1501 ),
1502 lookup: "main",
1503 detail: "fn()",
1504 },
1505 ]
1506 "#]],
1507 );
1508 }
1509
1510 #[test]
1511 fn enum_detail_just_name_for_unit() {
1512 check(
1513 r#"
1514enum Foo { Foo }
1515
1516fn main() { Foo::Fo$0 }
1517"#,
1518 SymbolKind::Variant,
1519 expect![[r#"
1520 [
1521 CompletionItem {
1522 label: "Foo",
1523 detail_left: None,
1524 detail_right: Some(
1525 "Foo",
1526 ),
1527 source_range: 35..37,
1528 delete: 35..37,
1529 insert: "Foo$0",
1530 kind: SymbolKind(
1531 Variant,
1532 ),
1533 detail: "Foo",
1534 relevance: CompletionRelevance {
1535 exact_name_match: false,
1536 type_match: None,
1537 is_local: false,
1538 is_missing: false,
1539 trait_: None,
1540 is_name_already_imported: false,
1541 requires_import: false,
1542 is_private_editable: false,
1543 postfix_match: None,
1544 function: Some(
1545 CompletionRelevanceFn {
1546 has_params: false,
1547 has_self_param: false,
1548 return_type: DirectConstructor,
1549 },
1550 ),
1551 is_skipping_completion: false,
1552 has_local_inherent_impl: false,
1553 is_deprecated: false,
1554 },
1555 trigger_call_info: true,
1556 },
1557 ]
1558 "#]],
1559 );
1560 }
1561
1562 #[test]
1563 fn lookup_enums_by_two_qualifiers() {
1564 check_kinds(
1565 r#"
1566mod m {
1567 pub enum Spam { Foo, Bar(i32) }
1568}
1569fn main() { let _: m::Spam = S$0 }
1570"#,
1571 &[
1572 CompletionItemKind::SymbolKind(SymbolKind::Function),
1573 CompletionItemKind::SymbolKind(SymbolKind::Module),
1574 CompletionItemKind::SymbolKind(SymbolKind::Variant),
1575 ],
1576 expect![[r#"
1577 [
1578 CompletionItem {
1579 label: "main()",
1580 detail_left: None,
1581 detail_right: Some(
1582 "fn()",
1583 ),
1584 source_range: 75..76,
1585 delete: 75..76,
1586 insert: "main();$0",
1587 kind: SymbolKind(
1588 Function,
1589 ),
1590 lookup: "main",
1591 detail: "fn()",
1592 },
1593 CompletionItem {
1594 label: "m::",
1595 detail_left: None,
1596 detail_right: None,
1597 source_range: 75..76,
1598 delete: 75..76,
1599 insert: "m::",
1600 kind: SymbolKind(
1601 Module,
1602 ),
1603 lookup: "m",
1604 },
1605 CompletionItem {
1606 label: "m::Spam::Bar(…)",
1607 detail_left: None,
1608 detail_right: Some(
1609 "m::Spam::Bar(i32)",
1610 ),
1611 source_range: 75..76,
1612 delete: 75..76,
1613 insert: "m::Spam::Bar(${1:()})$0",
1614 kind: SymbolKind(
1615 Variant,
1616 ),
1617 lookup: "Spam::Bar()",
1618 detail: "m::Spam::Bar(i32)",
1619 relevance: CompletionRelevance {
1620 exact_name_match: false,
1621 type_match: Some(
1622 Exact,
1623 ),
1624 is_local: false,
1625 is_missing: false,
1626 trait_: None,
1627 is_name_already_imported: false,
1628 requires_import: false,
1629 is_private_editable: false,
1630 postfix_match: None,
1631 function: Some(
1632 CompletionRelevanceFn {
1633 has_params: true,
1634 has_self_param: false,
1635 return_type: DirectConstructor,
1636 },
1637 ),
1638 is_skipping_completion: false,
1639 has_local_inherent_impl: false,
1640 is_deprecated: false,
1641 },
1642 trigger_call_info: true,
1643 },
1644 CompletionItem {
1645 label: "m::Spam::Foo",
1646 detail_left: None,
1647 detail_right: Some(
1648 "m::Spam::Foo",
1649 ),
1650 source_range: 75..76,
1651 delete: 75..76,
1652 insert: "m::Spam::Foo$0",
1653 kind: SymbolKind(
1654 Variant,
1655 ),
1656 lookup: "Spam::Foo",
1657 detail: "m::Spam::Foo",
1658 relevance: CompletionRelevance {
1659 exact_name_match: false,
1660 type_match: Some(
1661 Exact,
1662 ),
1663 is_local: false,
1664 is_missing: false,
1665 trait_: None,
1666 is_name_already_imported: false,
1667 requires_import: false,
1668 is_private_editable: false,
1669 postfix_match: None,
1670 function: Some(
1671 CompletionRelevanceFn {
1672 has_params: false,
1673 has_self_param: false,
1674 return_type: DirectConstructor,
1675 },
1676 ),
1677 is_skipping_completion: false,
1678 has_local_inherent_impl: false,
1679 is_deprecated: false,
1680 },
1681 trigger_call_info: true,
1682 },
1683 ]
1684 "#]],
1685 )
1686 }
1687
1688 #[test]
1689 fn sets_deprecated_flag_in_items() {
1690 check(
1691 r#"
1692#[deprecated]
1693mod something_deprecated {}
1694
1695fn main() { som$0 }
1696"#,
1697 SymbolKind::Module,
1698 expect![[r#"
1699 [
1700 CompletionItem {
1701 label: "something_deprecated::",
1702 detail_left: None,
1703 detail_right: None,
1704 source_range: 55..58,
1705 delete: 55..58,
1706 insert: "something_deprecated::",
1707 kind: SymbolKind(
1708 Module,
1709 ),
1710 lookup: "something_deprecated",
1711 deprecated: true,
1712 relevance: CompletionRelevance {
1713 exact_name_match: false,
1714 type_match: None,
1715 is_local: false,
1716 is_missing: false,
1717 trait_: None,
1718 is_name_already_imported: false,
1719 requires_import: false,
1720 is_private_editable: false,
1721 postfix_match: None,
1722 function: None,
1723 is_skipping_completion: false,
1724 has_local_inherent_impl: false,
1725 is_deprecated: true,
1726 },
1727 },
1728 ]
1729 "#]],
1730 );
1731
1732 check(
1733 r#"
1734#[deprecated]
1735fn something_deprecated() {}
1736
1737fn main() { som$0 }
1738"#,
1739 SymbolKind::Function,
1740 expect![[r#"
1741 [
1742 CompletionItem {
1743 label: "main()",
1744 detail_left: None,
1745 detail_right: Some(
1746 "fn()",
1747 ),
1748 source_range: 56..59,
1749 delete: 56..59,
1750 insert: "main();$0",
1751 kind: SymbolKind(
1752 Function,
1753 ),
1754 lookup: "main",
1755 detail: "fn()",
1756 },
1757 CompletionItem {
1758 label: "something_deprecated()",
1759 detail_left: None,
1760 detail_right: Some(
1761 "fn()",
1762 ),
1763 source_range: 56..59,
1764 delete: 56..59,
1765 insert: "something_deprecated();$0",
1766 kind: SymbolKind(
1767 Function,
1768 ),
1769 lookup: "something_deprecated",
1770 detail: "fn()",
1771 deprecated: true,
1772 relevance: CompletionRelevance {
1773 exact_name_match: false,
1774 type_match: None,
1775 is_local: false,
1776 is_missing: false,
1777 trait_: None,
1778 is_name_already_imported: false,
1779 requires_import: false,
1780 is_private_editable: false,
1781 postfix_match: None,
1782 function: None,
1783 is_skipping_completion: false,
1784 has_local_inherent_impl: false,
1785 is_deprecated: true,
1786 },
1787 },
1788 ]
1789 "#]],
1790 );
1791
1792 check(
1793 r#"
1794#[deprecated]
1795struct A;
1796
1797fn main() { A$0 }
1798"#,
1799 SymbolKind::Struct,
1800 expect![[r#"
1801 [
1802 CompletionItem {
1803 label: "A",
1804 detail_left: None,
1805 detail_right: Some(
1806 "A",
1807 ),
1808 source_range: 37..38,
1809 delete: 37..38,
1810 insert: "A",
1811 kind: SymbolKind(
1812 Struct,
1813 ),
1814 detail: "A",
1815 deprecated: true,
1816 relevance: CompletionRelevance {
1817 exact_name_match: false,
1818 type_match: None,
1819 is_local: false,
1820 is_missing: false,
1821 trait_: None,
1822 is_name_already_imported: false,
1823 requires_import: false,
1824 is_private_editable: false,
1825 postfix_match: None,
1826 function: None,
1827 is_skipping_completion: false,
1828 has_local_inherent_impl: false,
1829 is_deprecated: true,
1830 },
1831 },
1832 ]
1833 "#]],
1834 );
1835
1836 check(
1837 r#"
1838#[deprecated]
1839enum A {}
1840
1841fn main() { A$0 }
1842"#,
1843 SymbolKind::Enum,
1844 expect![[r#"
1845 [
1846 CompletionItem {
1847 label: "A",
1848 detail_left: None,
1849 detail_right: Some(
1850 "A",
1851 ),
1852 source_range: 37..38,
1853 delete: 37..38,
1854 insert: "A",
1855 kind: SymbolKind(
1856 Enum,
1857 ),
1858 detail: "A",
1859 deprecated: true,
1860 relevance: CompletionRelevance {
1861 exact_name_match: false,
1862 type_match: None,
1863 is_local: false,
1864 is_missing: false,
1865 trait_: None,
1866 is_name_already_imported: false,
1867 requires_import: false,
1868 is_private_editable: false,
1869 postfix_match: None,
1870 function: None,
1871 is_skipping_completion: false,
1872 has_local_inherent_impl: false,
1873 is_deprecated: true,
1874 },
1875 },
1876 ]
1877 "#]],
1878 );
1879
1880 check(
1881 r#"
1882enum A {
1883 Okay,
1884 #[deprecated]
1885 Old,
1886}
1887
1888fn main() { A::$0 }
1889"#,
1890 SymbolKind::Variant,
1891 expect![[r#"
1892 [
1893 CompletionItem {
1894 label: "Okay",
1895 detail_left: None,
1896 detail_right: Some(
1897 "Okay",
1898 ),
1899 source_range: 64..64,
1900 delete: 64..64,
1901 insert: "Okay$0",
1902 kind: SymbolKind(
1903 Variant,
1904 ),
1905 detail: "Okay",
1906 relevance: CompletionRelevance {
1907 exact_name_match: false,
1908 type_match: None,
1909 is_local: false,
1910 is_missing: false,
1911 trait_: None,
1912 is_name_already_imported: false,
1913 requires_import: false,
1914 is_private_editable: false,
1915 postfix_match: None,
1916 function: Some(
1917 CompletionRelevanceFn {
1918 has_params: false,
1919 has_self_param: false,
1920 return_type: DirectConstructor,
1921 },
1922 ),
1923 is_skipping_completion: false,
1924 has_local_inherent_impl: false,
1925 is_deprecated: false,
1926 },
1927 trigger_call_info: true,
1928 },
1929 CompletionItem {
1930 label: "Old",
1931 detail_left: None,
1932 detail_right: Some(
1933 "Old",
1934 ),
1935 source_range: 64..64,
1936 delete: 64..64,
1937 insert: "Old$0",
1938 kind: SymbolKind(
1939 Variant,
1940 ),
1941 detail: "Old",
1942 deprecated: true,
1943 relevance: CompletionRelevance {
1944 exact_name_match: false,
1945 type_match: None,
1946 is_local: false,
1947 is_missing: false,
1948 trait_: None,
1949 is_name_already_imported: false,
1950 requires_import: false,
1951 is_private_editable: false,
1952 postfix_match: None,
1953 function: Some(
1954 CompletionRelevanceFn {
1955 has_params: false,
1956 has_self_param: false,
1957 return_type: DirectConstructor,
1958 },
1959 ),
1960 is_skipping_completion: false,
1961 has_local_inherent_impl: false,
1962 is_deprecated: true,
1963 },
1964 trigger_call_info: true,
1965 },
1966 ]
1967 "#]],
1968 );
1969
1970 check(
1971 r#"
1972#[deprecated]
1973const A: i32 = 0;
1974
1975fn main() { A$0 }
1976"#,
1977 SymbolKind::Const,
1978 expect![[r#"
1979 [
1980 CompletionItem {
1981 label: "A",
1982 detail_left: Some(
1983 " = 0",
1984 ),
1985 detail_right: Some(
1986 "i32",
1987 ),
1988 source_range: 45..46,
1989 delete: 45..46,
1990 insert: "A",
1991 kind: SymbolKind(
1992 Const,
1993 ),
1994 detail: "i32",
1995 deprecated: true,
1996 relevance: CompletionRelevance {
1997 exact_name_match: false,
1998 type_match: None,
1999 is_local: false,
2000 is_missing: false,
2001 trait_: None,
2002 is_name_already_imported: false,
2003 requires_import: false,
2004 is_private_editable: false,
2005 postfix_match: None,
2006 function: None,
2007 is_skipping_completion: false,
2008 has_local_inherent_impl: false,
2009 is_deprecated: true,
2010 },
2011 },
2012 ]
2013 "#]],
2014 );
2015
2016 check(
2017 r#"
2018#[deprecated]
2019static A: i32 = 0;
2020
2021fn main() { A$0 }
2022"#,
2023 SymbolKind::Static,
2024 expect![[r#"
2025 [
2026 CompletionItem {
2027 label: "A",
2028 detail_left: None,
2029 detail_right: Some(
2030 "i32",
2031 ),
2032 source_range: 46..47,
2033 delete: 46..47,
2034 insert: "A",
2035 kind: SymbolKind(
2036 Static,
2037 ),
2038 detail: "i32",
2039 deprecated: true,
2040 relevance: CompletionRelevance {
2041 exact_name_match: false,
2042 type_match: None,
2043 is_local: false,
2044 is_missing: false,
2045 trait_: None,
2046 is_name_already_imported: false,
2047 requires_import: false,
2048 is_private_editable: false,
2049 postfix_match: None,
2050 function: None,
2051 is_skipping_completion: false,
2052 has_local_inherent_impl: false,
2053 is_deprecated: true,
2054 },
2055 },
2056 ]
2057 "#]],
2058 );
2059
2060 check(
2061 r#"
2062#[deprecated]
2063trait A {}
2064
2065impl A$0
2066"#,
2067 SymbolKind::Trait,
2068 expect![[r#"
2069 [
2070 CompletionItem {
2071 label: "A",
2072 detail_left: None,
2073 detail_right: None,
2074 source_range: 31..32,
2075 delete: 31..32,
2076 insert: "A",
2077 kind: SymbolKind(
2078 Trait,
2079 ),
2080 deprecated: true,
2081 relevance: CompletionRelevance {
2082 exact_name_match: false,
2083 type_match: None,
2084 is_local: false,
2085 is_missing: false,
2086 trait_: None,
2087 is_name_already_imported: false,
2088 requires_import: false,
2089 is_private_editable: false,
2090 postfix_match: None,
2091 function: None,
2092 is_skipping_completion: false,
2093 has_local_inherent_impl: false,
2094 is_deprecated: true,
2095 },
2096 },
2097 ]
2098 "#]],
2099 );
2100
2101 check(
2102 r#"
2103#[deprecated]
2104type A = i32;
2105
2106fn main() { A$0 }
2107"#,
2108 SymbolKind::TypeAlias,
2109 expect![[r#"
2110 [
2111 CompletionItem {
2112 label: "A",
2113 detail_left: None,
2114 detail_right: Some(
2115 "i32",
2116 ),
2117 source_range: 41..42,
2118 delete: 41..42,
2119 insert: "A",
2120 kind: SymbolKind(
2121 TypeAlias,
2122 ),
2123 detail: "i32",
2124 deprecated: true,
2125 relevance: CompletionRelevance {
2126 exact_name_match: false,
2127 type_match: None,
2128 is_local: false,
2129 is_missing: false,
2130 trait_: None,
2131 is_name_already_imported: false,
2132 requires_import: false,
2133 is_private_editable: false,
2134 postfix_match: None,
2135 function: None,
2136 is_skipping_completion: false,
2137 has_local_inherent_impl: false,
2138 is_deprecated: true,
2139 },
2140 },
2141 ]
2142 "#]],
2143 );
2144
2145 check(
2146 r#"
2147#[deprecated]
2148macro_rules! a { _ => {}}
2149
2150fn main() { a$0 }
2151"#,
2152 SymbolKind::Macro,
2153 expect![[r#"
2154 [
2155 CompletionItem {
2156 label: "a!(…)",
2157 detail_left: None,
2158 detail_right: Some(
2159 "macro_rules! a",
2160 ),
2161 source_range: 53..54,
2162 delete: 53..54,
2163 insert: "a!($0)",
2164 kind: SymbolKind(
2165 Macro,
2166 ),
2167 lookup: "a!",
2168 detail: "macro_rules! a",
2169 deprecated: true,
2170 relevance: CompletionRelevance {
2171 exact_name_match: false,
2172 type_match: None,
2173 is_local: false,
2174 is_missing: false,
2175 trait_: None,
2176 is_name_already_imported: false,
2177 requires_import: false,
2178 is_private_editable: false,
2179 postfix_match: None,
2180 function: None,
2181 is_skipping_completion: false,
2182 has_local_inherent_impl: false,
2183 is_deprecated: true,
2184 },
2185 },
2186 ]
2187 "#]],
2188 );
2189
2190 check(
2191 r#"
2192struct A { #[deprecated] the_field: u32 }
2193
2194fn main() { A { the$0 } }
2195"#,
2196 SymbolKind::Field,
2197 expect![[r#"
2198 [
2199 CompletionItem {
2200 label: "the_field",
2201 detail_left: None,
2202 detail_right: Some(
2203 "u32",
2204 ),
2205 source_range: 59..62,
2206 delete: 59..62,
2207 insert: "the_field",
2208 kind: SymbolKind(
2209 Field,
2210 ),
2211 detail: "u32",
2212 deprecated: true,
2213 relevance: CompletionRelevance {
2214 exact_name_match: false,
2215 type_match: None,
2216 is_local: false,
2217 is_missing: false,
2218 trait_: None,
2219 is_name_already_imported: false,
2220 requires_import: false,
2221 is_private_editable: false,
2222 postfix_match: None,
2223 function: None,
2224 is_skipping_completion: false,
2225 has_local_inherent_impl: false,
2226 is_deprecated: true,
2227 },
2228 },
2229 ]
2230 "#]],
2231 );
2232 }
2233
2234 #[test]
2235 fn renders_docs() {
2236 check_kinds(
2237 r#"
2238struct S {
2239 /// Field docs
2240 foo:
2241}
2242impl S {
2243 /// Method docs
2244 fn bar(self) { self.$0 }
2245}"#,
2246 &[
2247 CompletionItemKind::SymbolKind(SymbolKind::Method),
2248 CompletionItemKind::SymbolKind(SymbolKind::Field),
2249 ],
2250 expect![[r#"
2251 [
2252 CompletionItem {
2253 label: "bar()",
2254 detail_left: None,
2255 detail_right: Some(
2256 "fn(self)",
2257 ),
2258 source_range: 94..94,
2259 delete: 94..94,
2260 insert: "bar();$0",
2261 kind: SymbolKind(
2262 Method,
2263 ),
2264 lookup: "bar",
2265 detail: "fn(self)",
2266 documentation: Documentation(
2267 "Method docs",
2268 ),
2269 relevance: CompletionRelevance {
2270 exact_name_match: false,
2271 type_match: None,
2272 is_local: false,
2273 is_missing: false,
2274 trait_: None,
2275 is_name_already_imported: false,
2276 requires_import: false,
2277 is_private_editable: false,
2278 postfix_match: None,
2279 function: Some(
2280 CompletionRelevanceFn {
2281 has_params: true,
2282 has_self_param: true,
2283 return_type: Other,
2284 },
2285 ),
2286 is_skipping_completion: false,
2287 has_local_inherent_impl: false,
2288 is_deprecated: false,
2289 },
2290 },
2291 CompletionItem {
2292 label: "foo",
2293 detail_left: None,
2294 detail_right: Some(
2295 "{unknown}",
2296 ),
2297 source_range: 94..94,
2298 delete: 94..94,
2299 insert: "foo",
2300 kind: SymbolKind(
2301 Field,
2302 ),
2303 detail: "{unknown}",
2304 documentation: Documentation(
2305 "Field docs",
2306 ),
2307 },
2308 ]
2309 "#]],
2310 );
2311
2312 check_kinds(
2313 r#"
2314use self::my$0;
2315
2316/// mod docs
2317mod my { }
2318
2319/// enum docs
2320enum E {
2321 /// variant docs
2322 V
2323}
2324use self::E::*;
2325"#,
2326 &[
2327 CompletionItemKind::SymbolKind(SymbolKind::Module),
2328 CompletionItemKind::SymbolKind(SymbolKind::Variant),
2329 CompletionItemKind::SymbolKind(SymbolKind::Enum),
2330 ],
2331 expect![[r#"
2332 [
2333 CompletionItem {
2334 label: "my",
2335 detail_left: None,
2336 detail_right: None,
2337 source_range: 10..12,
2338 delete: 10..12,
2339 insert: "my",
2340 kind: SymbolKind(
2341 Module,
2342 ),
2343 documentation: Documentation(
2344 "mod docs",
2345 ),
2346 },
2347 CompletionItem {
2348 label: "V",
2349 detail_left: None,
2350 detail_right: Some(
2351 "V",
2352 ),
2353 source_range: 10..12,
2354 delete: 10..12,
2355 insert: "V$0",
2356 kind: SymbolKind(
2357 Variant,
2358 ),
2359 detail: "V",
2360 documentation: Documentation(
2361 "variant docs",
2362 ),
2363 relevance: CompletionRelevance {
2364 exact_name_match: false,
2365 type_match: None,
2366 is_local: false,
2367 is_missing: false,
2368 trait_: None,
2369 is_name_already_imported: false,
2370 requires_import: false,
2371 is_private_editable: false,
2372 postfix_match: None,
2373 function: Some(
2374 CompletionRelevanceFn {
2375 has_params: false,
2376 has_self_param: false,
2377 return_type: DirectConstructor,
2378 },
2379 ),
2380 is_skipping_completion: false,
2381 has_local_inherent_impl: false,
2382 is_deprecated: false,
2383 },
2384 trigger_call_info: true,
2385 },
2386 CompletionItem {
2387 label: "E",
2388 detail_left: None,
2389 detail_right: Some(
2390 "E",
2391 ),
2392 source_range: 10..12,
2393 delete: 10..12,
2394 insert: "E",
2395 kind: SymbolKind(
2396 Enum,
2397 ),
2398 detail: "E",
2399 documentation: Documentation(
2400 "enum docs",
2401 ),
2402 },
2403 ]
2404 "#]],
2405 )
2406 }
2407
2408 #[test]
2409 fn dont_render_attrs() {
2410 check(
2411 r#"
2412struct S;
2413impl S {
2414 #[inline]
2415 fn the_method(&self) { }
2416}
2417fn foo(s: S) { s.$0 }
2418"#,
2419 SymbolKind::Method,
2420 expect![[r#"
2421 [
2422 CompletionItem {
2423 label: "the_method()",
2424 detail_left: None,
2425 detail_right: Some(
2426 "fn(&self)",
2427 ),
2428 source_range: 81..81,
2429 delete: 81..81,
2430 insert: "the_method();$0",
2431 kind: SymbolKind(
2432 Method,
2433 ),
2434 lookup: "the_method",
2435 detail: "fn(&self)",
2436 relevance: CompletionRelevance {
2437 exact_name_match: false,
2438 type_match: None,
2439 is_local: false,
2440 is_missing: false,
2441 trait_: None,
2442 is_name_already_imported: false,
2443 requires_import: false,
2444 is_private_editable: false,
2445 postfix_match: None,
2446 function: Some(
2447 CompletionRelevanceFn {
2448 has_params: true,
2449 has_self_param: true,
2450 return_type: Other,
2451 },
2452 ),
2453 is_skipping_completion: false,
2454 has_local_inherent_impl: false,
2455 is_deprecated: false,
2456 },
2457 },
2458 ]
2459 "#]],
2460 )
2461 }
2462
2463 #[test]
2464 fn no_call_parens_if_fn_ptr_needed() {
2465 cov_mark::check!(no_call_parens_if_fn_ptr_needed);
2466 check_edit(
2467 "foo",
2468 r#"
2469fn foo(foo: u8, bar: u8) {}
2470struct ManualVtable { f: fn(u8, u8) }
2471
2472fn main() -> ManualVtable {
2473 ManualVtable { f: f$0 }
2474}
2475"#,
2476 r#"
2477fn foo(foo: u8, bar: u8) {}
2478struct ManualVtable { f: fn(u8, u8) }
2479
2480fn main() -> ManualVtable {
2481 ManualVtable { f: foo }
2482}
2483"#,
2484 );
2485 check_edit(
2486 "type",
2487 r#"
2488struct RawIdentTable { r#type: u32 }
2489
2490fn main() -> RawIdentTable {
2491 RawIdentTable { t$0: 42 }
2492}
2493"#,
2494 r#"
2495struct RawIdentTable { r#type: u32 }
2496
2497fn main() -> RawIdentTable {
2498 RawIdentTable { r#type: 42 }
2499}
2500"#,
2501 );
2502 }
2503
2504 #[test]
2505 fn no_call_parens_if_param_with_fn_bounds() {
2506 cov_mark::check!(no_call_parens_if_ty_with_fn_bounds);
2507 check_edit(
2508 "foo",
2509 r#"
2510//- minicore: fn
2511fn needs_fn(f: impl FnOnce(u8, u8)) {}
2512fn foo(a: u8, b: u8) {
2513 needs_fn(f$0)
2514}
2515"#,
2516 r#"
2517fn needs_fn(f: impl FnOnce(u8, u8)) {}
2518fn foo(a: u8, b: u8) {
2519 needs_fn(foo)
2520}
2521"#,
2522 );
2523 check_edit(
2524 "foo",
2525 r#"
2526//- minicore: fn
2527fn needs_fn<F: FnOnce(u8, u8)>(f: F) {}
2528fn foo(a: u8, b: u8) {
2529 needs_fn(f$0)
2530}
2531"#,
2532 r#"
2533fn needs_fn<F: FnOnce(u8, u8)>(f: F) {}
2534fn foo(a: u8, b: u8) {
2535 needs_fn(foo)
2536}
2537"#,
2538 );
2539 check_edit(
2540 "foo",
2541 r#"
2542//- minicore: fn
2543fn needs_fn<F>(f: F) where F: FnOnce(u8, u8) {}
2544fn foo(a: u8, b: u8) {
2545 needs_fn(f$0)
2546}
2547"#,
2548 r#"
2549fn needs_fn<F>(f: F) where F: FnOnce(u8, u8) {}
2550fn foo(a: u8, b: u8) {
2551 needs_fn(foo)
2552}
2553"#,
2554 );
2555 check_edit(
2556 "unmap",
2557 r#"
2558//- minicore: fn
2559trait Trait {
2560 fn unmap(self) -> i32 { 0 }
2561}
2562mod module {
2563 pub struct Ty;
2564 impl super::Trait for Ty {}
2565}
2566fn needs_fn<T>(f: impl FnOnce(T) -> i32) {}
2567fn foo(a: u8, b: u8) {
2568 needs_fn(module::Ty::u$0)
2569}
2570"#,
2571 r#"
2572trait Trait {
2573 fn unmap(self) -> i32 { 0 }
2574}
2575mod module {
2576 pub struct Ty;
2577 impl super::Trait for Ty {}
2578}
2579fn needs_fn<T>(f: impl FnOnce(T) -> i32) {}
2580fn foo(a: u8, b: u8) {
2581 needs_fn(module::Ty::unmap)
2582}
2583"#,
2584 );
2585 check_edit(
2586 "neg",
2587 r#"
2588//- minicore: iterator, iterators, unary_ops, builtin_impls
2589fn foo(iter: impl Iterator<Item = u32>) {
2590 iter.map(core::ops::Neg::n$0)
2591}
2592"#,
2593 r#"
2594fn foo(iter: impl Iterator<Item = u32>) {
2595 iter.map(core::ops::Neg::neg)
2596}
2597"#,
2598 );
2599 check_edit(
2600 "neg",
2601 r#"
2602//- minicore: iterator, iterators, unary_ops, builtin_impls
2603fn foo(iter: impl Iterator<Item = u32>) {
2604 iter.map(core::ops::Neg::$0)
2605}
2606"#,
2607 r#"
2608fn foo(iter: impl Iterator<Item = u32>) {
2609 iter.map(core::ops::Neg::neg)
2610}
2611"#,
2612 );
2613 }
2614
2615 #[test]
2616 fn call_parens_in_non_direct_expr() {
2617 check_edit(
2618 "foo",
2619 r#"
2620//- minicore: fn
2621fn needs_fn(f: impl FnOnce(u8, u8)) {}
2622fn foo(a: u8, b: u8) {
2623 needs_fn(&f$0)
2624}
2625"#,
2626 r#"
2627fn needs_fn(f: impl FnOnce(u8, u8)) {}
2628fn foo(a: u8, b: u8) {
2629 needs_fn(&foo(${1:a}, ${2:b})$0)
2630}
2631"#,
2632 );
2633 check_edit(
2634 "method",
2635 r#"
2636//- minicore: fn
2637struct Foo;
2638impl Foo { fn method(&self, a: u8, b: u8) {} }
2639fn needs_fn(f: impl FnOnce(u8, u8)) {}
2640fn foo(a: u8, b: u8) {
2641 needs_fn(Foo.m$0)
2642}
2643"#,
2644 r#"
2645struct Foo;
2646impl Foo { fn method(&self, a: u8, b: u8) {} }
2647fn needs_fn(f: impl FnOnce(u8, u8)) {}
2648fn foo(a: u8, b: u8) {
2649 needs_fn(Foo.method(${1:a}, ${2:b})$0)
2650}
2651"#,
2652 );
2653 check_edit(
2654 "method",
2655 r#"
2656//- minicore: fn
2657struct Foo;
2658impl Foo { fn method(&self, a: u8, b: u8) {} }
2659fn needs_fn(f: impl FnOnce(u8, u8)) {}
2660fn foo(a: u8, b: u8) {
2661 needs_fn(Foo.$0)
2662}
2663"#,
2664 r#"
2665struct Foo;
2666impl Foo { fn method(&self, a: u8, b: u8) {} }
2667fn needs_fn(f: impl FnOnce(u8, u8)) {}
2668fn foo(a: u8, b: u8) {
2669 needs_fn(Foo.method(${1:a}, ${2:b})$0)
2670}
2671"#,
2672 );
2673 }
2674
2675 #[test]
2676 fn call_parens_in_bad_case() {
2677 check_edit(
2678 "foo",
2679 r#"
2680//- minicore: fn
2681fn needs_fn(f: impl FnOnce(u8, u8)) {}
2682fn foo(a: u8) {
2683 needs_fn(f$0);
2684}
2685"#,
2686 r#"
2687fn needs_fn(f: impl FnOnce(u8, u8)) {}
2688fn foo(a: u8) {
2689 needs_fn(foo(${1:a})$0);
2690}
2691"#,
2692 );
2693 check_edit(
2694 "foo",
2695 r#"
2696//- minicore: fn
2697fn needs_fn<T>(f: impl FnOnce(u8, u8) -> T) {}
2698fn foo(a: u8, b: u8) -> impl FnOnce(u8, u8) {
2699 needs_fn(f$0);
2700}
2701"#,
2702 r#"
2703fn needs_fn<T>(f: impl FnOnce(u8, u8) -> T) {}
2704fn foo(a: u8, b: u8) -> impl FnOnce(u8, u8) {
2705 needs_fn(foo(${1:a}, ${2:b})$0);
2706}
2707"#,
2708 );
2709 check_edit(
2710 "foo",
2711 r#"
2712//- minicore: fn
2713fn needs_fn(f: impl FnOnce(u8, u8) -> u8) {}
2714fn foo(a: u8, b: u8) -> u16 {
2715 needs_fn(f$0);
2716}
2717"#,
2718 r#"
2719fn needs_fn(f: impl FnOnce(u8, u8) -> u8) {}
2720fn foo(a: u8, b: u8) -> u16 {
2721 needs_fn(foo(${1:a}, ${2:b})$0);
2722}
2723"#,
2724 );
2725 }
2726
2727 #[test]
2728 fn no_parens_in_use_item() {
2729 check_edit(
2730 "foo",
2731 r#"
2732mod m { pub fn foo() {} }
2733use crate::m::f$0;
2734"#,
2735 r#"
2736mod m { pub fn foo() {} }
2737use crate::m::foo;
2738"#,
2739 );
2740 }
2741
2742 #[test]
2743 fn no_parens_in_call() {
2744 check_edit(
2745 "foo",
2746 r#"
2747fn foo(x: i32) {}
2748fn main() { f$0(); }
2749"#,
2750 r#"
2751fn foo(x: i32) {}
2752fn main() { foo(); }
2753"#,
2754 );
2755 check_edit(
2756 "foo",
2757 r#"
2758struct Foo;
2759impl Foo { fn foo(&self){} }
2760fn f(foo: &Foo) { foo.f$0(); }
2761"#,
2762 r#"
2763struct Foo;
2764impl Foo { fn foo(&self){} }
2765fn f(foo: &Foo) { foo.foo(); }
2766"#,
2767 );
2768 }
2769
2770 #[test]
2771 fn inserts_angle_brackets_for_generics() {
2772 cov_mark::check!(inserts_angle_brackets_for_generics);
2773 check_edit(
2774 "Vec",
2775 r#"
2776struct Vec<T> {}
2777fn foo(xs: Ve$0)
2778"#,
2779 r#"
2780struct Vec<T> {}
2781fn foo(xs: Vec<$0>)
2782"#,
2783 );
2784 check_edit(
2785 "Vec",
2786 r#"
2787type Vec<T> = (T,);
2788fn foo(xs: Ve$0)
2789"#,
2790 r#"
2791type Vec<T> = (T,);
2792fn foo(xs: Vec<$0>)
2793"#,
2794 );
2795 check_edit(
2796 "Vec",
2797 r#"
2798struct Vec<T = i128> {}
2799fn foo(xs: Ve$0)
2800"#,
2801 r#"
2802struct Vec<T = i128> {}
2803fn foo(xs: Vec)
2804"#,
2805 );
2806 check_edit(
2807 "Vec",
2808 r#"
2809struct Vec<T> {}
2810fn foo(xs: Ve$0<i128>)
2811"#,
2812 r#"
2813struct Vec<T> {}
2814fn foo(xs: Vec<i128>)
2815"#,
2816 );
2817 }
2818
2819 #[test]
2820 fn active_param_relevance() {
2821 check_relevance(
2822 r#"
2823struct S { foo: i64, bar: u32, baz: u32 }
2824fn test(bar: u32) { }
2825fn foo(s: S) { test(s.$0) }
2826"#,
2827 expect![[r#"
2828 fd bar u32 [type+name]
2829 fd baz u32 [type]
2830 fd foo i64 []
2831 "#]],
2832 );
2833 }
2834
2835 #[test]
2836 fn record_field_relevances() {
2837 check_relevance(
2838 r#"
2839struct A { foo: i64, bar: u32, baz: u32 }
2840struct B { x: (), y: f32, bar: u32 }
2841fn foo(a: A) { B { bar: a.$0 }; }
2842"#,
2843 expect![[r#"
2844 fd bar u32 [type+name]
2845 fd baz u32 [type]
2846 fd foo i64 []
2847 "#]],
2848 )
2849 }
2850
2851 #[test]
2852 fn tuple_field_detail() {
2853 check(
2854 r#"
2855struct S(i32);
2856
2857fn f() -> i32 {
2858 let s = S(0);
2859 s.0$0
2860}
2861"#,
2862 SymbolKind::Field,
2863 expect![[r#"
2864 [
2865 CompletionItem {
2866 label: "0",
2867 detail_left: None,
2868 detail_right: Some(
2869 "i32",
2870 ),
2871 source_range: 56..57,
2872 delete: 56..57,
2873 insert: "0",
2874 kind: SymbolKind(
2875 Field,
2876 ),
2877 detail: "i32",
2878 relevance: CompletionRelevance {
2879 exact_name_match: false,
2880 type_match: Some(
2881 Exact,
2882 ),
2883 is_local: false,
2884 is_missing: false,
2885 trait_: None,
2886 is_name_already_imported: false,
2887 requires_import: false,
2888 is_private_editable: false,
2889 postfix_match: None,
2890 function: None,
2891 is_skipping_completion: false,
2892 has_local_inherent_impl: false,
2893 is_deprecated: false,
2894 },
2895 },
2896 ]
2897 "#]],
2898 );
2899 }
2900
2901 #[test]
2902 fn record_field_and_call_relevances() {
2903 check_relevance(
2904 r#"
2905struct A { foo: i64, bar: u32, baz: u32 }
2906struct B { x: (), y: f32, bar: u32 }
2907fn f(foo: i64) { }
2908fn foo(a: A) { B { bar: f(a.$0) }; }
2909"#,
2910 expect![[r#"
2911 fd foo i64 [type+name]
2912 fd bar u32 []
2913 fd baz u32 []
2914 "#]],
2915 );
2916 check_relevance(
2917 r#"
2918struct A { foo: i64, bar: u32, baz: u32 }
2919struct B { x: (), y: f32, bar: u32 }
2920fn f(foo: i64) { }
2921fn foo(a: A) { f(B { bar: a.$0 }); }
2922"#,
2923 expect![[r#"
2924 fd bar u32 [type+name]
2925 fd baz u32 [type]
2926 fd foo i64 []
2927 "#]],
2928 );
2929 }
2930
2931 #[test]
2932 fn prioritize_exact_ref_match() {
2933 check_relevance(
2934 r#"
2935struct WorldSnapshot { _f: () };
2936fn go(world: &WorldSnapshot) { go(w$0) }
2937"#,
2938 expect![[r#"
2939 lc world &WorldSnapshot [type+name+local]
2940 ex world [type]
2941 st WorldSnapshot {…} WorldSnapshot { _f: () } []
2942 st &WorldSnapshot {…} [type]
2943 st WorldSnapshot WorldSnapshot []
2944 fn go(…) fn(&WorldSnapshot) []
2945 "#]],
2946 );
2947 }
2948
2949 #[test]
2950 fn prioritize_mutable_ref_as_immutable_ref_match() {
2951 check_relevance(
2952 r#"fn foo(r: &mut i32) -> &i32 { $0 }"#,
2953 expect![[r#"
2954 lc r &mut i32 [type+local]
2955 fn foo(…) fn(&mut i32) -> &i32 [type]
2956 "#]],
2957 );
2958 }
2959
2960 #[test]
2961 fn complete_ref_match_after_keyword_prefix() {
2962 check_kinds(
2964 r#"
2965fn foo(data: &i32) {}
2966fn main() {
2967 let indent = 2i32;
2968 foo(in$0)
2969}
2970"#,
2971 &[CompletionItemKind::SymbolKind(SymbolKind::Local)],
2972 expect![[r#"
2973 [
2974 CompletionItem {
2975 label: "indent",
2976 detail_left: None,
2977 detail_right: Some(
2978 "i32",
2979 ),
2980 source_range: 65..67,
2981 delete: 65..67,
2982 insert: "indent",
2983 kind: SymbolKind(
2984 Local,
2985 ),
2986 detail: "i32",
2987 relevance: CompletionRelevance {
2988 exact_name_match: false,
2989 type_match: None,
2990 is_local: true,
2991 is_missing: false,
2992 trait_: None,
2993 is_name_already_imported: false,
2994 requires_import: false,
2995 is_private_editable: false,
2996 postfix_match: None,
2997 function: None,
2998 is_skipping_completion: false,
2999 has_local_inherent_impl: false,
3000 is_deprecated: false,
3001 },
3002 ref_match: "&@65",
3003 },
3004 ]
3005 "#]],
3006 );
3007 }
3008
3009 #[test]
3010 fn complete_ref_match_in_macro() {
3011 check_kinds(
3012 r#"
3013macro_rules! id { ($($t:tt)*) => ($($t)*); }
3014fn foo(data: &i32) {}
3015fn main() {
3016 let indent = 2i32;
3017 id!(foo(i$0))
3018}
3019"#,
3020 &[CompletionItemKind::SymbolKind(SymbolKind::Local)],
3021 expect![[r#"
3022 [
3023 CompletionItem {
3024 label: "indent",
3025 detail_left: None,
3026 detail_right: Some(
3027 "i32",
3028 ),
3029 source_range: 114..115,
3030 delete: 114..115,
3031 insert: "indent",
3032 kind: SymbolKind(
3033 Local,
3034 ),
3035 detail: "i32",
3036 relevance: CompletionRelevance {
3037 exact_name_match: false,
3038 type_match: None,
3039 is_local: true,
3040 is_missing: false,
3041 trait_: None,
3042 is_name_already_imported: false,
3043 requires_import: false,
3044 is_private_editable: false,
3045 postfix_match: None,
3046 function: None,
3047 is_skipping_completion: false,
3048 has_local_inherent_impl: false,
3049 is_deprecated: false,
3050 },
3051 ref_match: "&@114",
3052 },
3053 ]
3054 "#]],
3055 );
3056
3057 check_kinds(
3058 r#"
3059macro_rules! id { ($($t:tt)*) => ($($t)*); }
3060fn foo(data: &i32) {}
3061fn indent() -> i32 { i32 }
3062fn main() {
3063 id!(foo(i$0))
3064}
3065"#,
3066 &[CompletionItemKind::SymbolKind(SymbolKind::Function)],
3067 expect![[r#"
3068 [
3069 CompletionItem {
3070 label: "foo(…)",
3071 detail_left: None,
3072 detail_right: Some(
3073 "fn(&i32)",
3074 ),
3075 source_range: 118..119,
3076 delete: 118..119,
3077 insert: "foo(${1:data})$0",
3078 kind: SymbolKind(
3079 Function,
3080 ),
3081 lookup: "foo",
3082 detail: "fn(&i32)",
3083 trigger_call_info: true,
3084 },
3085 CompletionItem {
3086 label: "indent()",
3087 detail_left: None,
3088 detail_right: Some(
3089 "fn() -> i32",
3090 ),
3091 source_range: 118..119,
3092 delete: 118..119,
3093 insert: "indent()$0",
3094 kind: SymbolKind(
3095 Function,
3096 ),
3097 lookup: "indent",
3098 detail: "fn() -> i32",
3099 ref_match: "&@118",
3100 },
3101 CompletionItem {
3102 label: "main()",
3103 detail_left: None,
3104 detail_right: Some(
3105 "fn()",
3106 ),
3107 source_range: 118..119,
3108 delete: 118..119,
3109 insert: "main()$0",
3110 kind: SymbolKind(
3111 Function,
3112 ),
3113 lookup: "main",
3114 detail: "fn()",
3115 },
3116 ]
3117 "#]],
3118 );
3119
3120 check_kinds(
3122 r#"
3123macro_rules! id { ($($t:tt)*) => ($($t)*); }
3124fn foo(data: &i32) {}
3125struct S;
3126impl S {fn indent(&self) -> i32 { i32 }}
3127fn main() {
3128 id!(foo(S.i$0))
3129}
3130"#,
3131 &[CompletionItemKind::SymbolKind(SymbolKind::Method)],
3132 expect![[r#"
3133 [
3134 CompletionItem {
3135 label: "indent()",
3136 detail_left: None,
3137 detail_right: Some(
3138 "fn(&self) -> i32",
3139 ),
3140 source_range: 144..145,
3141 delete: 144..145,
3142 insert: "indent()$0",
3143 kind: SymbolKind(
3144 Method,
3145 ),
3146 lookup: "indent",
3147 detail: "fn(&self) -> i32",
3148 relevance: CompletionRelevance {
3149 exact_name_match: false,
3150 type_match: None,
3151 is_local: false,
3152 is_missing: false,
3153 trait_: None,
3154 is_name_already_imported: false,
3155 requires_import: false,
3156 is_private_editable: false,
3157 postfix_match: None,
3158 function: Some(
3159 CompletionRelevanceFn {
3160 has_params: true,
3161 has_self_param: true,
3162 return_type: Other,
3163 },
3164 ),
3165 is_skipping_completion: false,
3166 has_local_inherent_impl: false,
3167 is_deprecated: false,
3168 },
3169 ref_match: "&@142",
3170 },
3171 ]
3172 "#]],
3173 );
3174
3175 check_kinds(
3176 r#"
3177macro_rules! id { ($($t:tt)*) => ($($t)*); }
3178fn foo(data: &i32) {}
3179struct S { indent: i32 }
3180fn main(s: S) {
3181 id!(foo(s.i$0))
3182}
3183"#,
3184 &[CompletionItemKind::SymbolKind(SymbolKind::Field)],
3185 expect![[r#"
3186 [
3187 CompletionItem {
3188 label: "indent",
3189 detail_left: None,
3190 detail_right: Some(
3191 "i32",
3192 ),
3193 source_range: 122..123,
3194 delete: 122..123,
3195 insert: "indent",
3196 kind: SymbolKind(
3197 Field,
3198 ),
3199 detail: "i32",
3200 ref_match: "&@120",
3201 },
3202 ]
3203 "#]],
3204 );
3205 }
3206
3207 #[test]
3208 fn too_many_arguments() {
3209 cov_mark::check!(too_many_arguments);
3210 check_relevance(
3211 r#"
3212struct Foo;
3213fn f(foo: &Foo) { f(foo, w$0) }
3214"#,
3215 expect![[r#"
3216 lc foo &Foo [local]
3217 st Foo Foo []
3218 fn f(…) fn(&Foo) []
3219 "#]],
3220 );
3221 }
3222
3223 #[test]
3224 fn score_fn_type_and_name_match() {
3225 check_relevance(
3226 r#"
3227struct A { bar: u8 }
3228fn baz() -> u8 { 0 }
3229fn bar() -> u8 { 0 }
3230fn f() { A { bar: b$0 }; }
3231"#,
3232 expect![[r#"
3233 fn bar() fn() -> u8 [type+name]
3234 ex bar() [type]
3235 fn baz() fn() -> u8 [type]
3236 ex baz() [type]
3237 st A A []
3238 fn f() fn() []
3239 "#]],
3240 );
3241 }
3242
3243 #[test]
3244 fn score_method_type_and_name_match() {
3245 check_relevance(
3246 r#"
3247fn baz(aaa: u32){}
3248struct Foo;
3249impl Foo {
3250fn aaa(&self) -> u32 { 0 }
3251fn bbb(&self) -> u32 { 0 }
3252fn ccc(&self) -> u64 { 0 }
3253}
3254fn f() {
3255 baz(Foo.$0
3256}
3257"#,
3258 expect![[r#"
3259 me aaa() fn(&self) -> u32 [type+name]
3260 me bbb() fn(&self) -> u32 [type]
3261 me ccc() fn(&self) -> u64 []
3262 "#]],
3263 );
3264 }
3265
3266 #[test]
3267 fn score_method_name_match_only() {
3268 check_relevance(
3269 r#"
3270fn baz(aaa: u32){}
3271struct Foo;
3272impl Foo {
3273fn aaa(&self) -> u64 { 0 }
3274}
3275fn f() {
3276 baz(Foo.$0
3277}
3278"#,
3279 expect![[r#"
3280 me aaa() fn(&self) -> u64 [name]
3281 "#]],
3282 );
3283 }
3284
3285 #[test]
3286 fn name_match_special_case() {
3287 check_relevance(
3288 r#"
3289fn foo(_db: &()) {}
3290fn bar(db: &()) {
3291 foo($0)
3292}
3293"#,
3294 expect![[r#"
3295 lc db &() [type+name+local]
3296 ex db [type]
3297 fn bar(…) fn(&()) []
3298 fn foo(…) fn(&()) []
3299 "#]],
3300 );
3301 check_relevance(
3302 r#"
3303fn foo(impl_: &()) {}
3304fn bar(r#impl: &()) {
3305 foo($0)
3306}
3307"#,
3308 expect![[r#"
3309 lc impl &() [type+name+local]
3310 ex r#impl [type]
3311 fn bar(…) fn(&()) []
3312 fn foo(…) fn(&()) []
3313 "#]],
3314 );
3315 check_relevance(
3316 r#"
3317fn foo(r#impl: &()) {}
3318fn bar(impl_: &()) {
3319 foo($0)
3320}
3321"#,
3322 expect![[r#"
3323 lc impl_ &() [type+name+local]
3324 ex impl_ [type]
3325 fn bar(…) fn(&()) []
3326 fn foo(…) fn(&()) []
3327 "#]],
3328 );
3329 }
3330
3331 #[test]
3332 fn score_has_local_inherent_impl() {
3333 check_relevance(
3334 r#"
3335trait Foob {}
3336struct Fooa {}
3337impl Fooa {}
3338
3339impl Foo$0
3340"#,
3341 expect![[r#"
3342 tt Foob []
3343 st Fooa Fooa [has_local_inherent_impl]
3344 "#]],
3345 );
3346
3347 check_relevance(
3349 r#"
3350trait Foob {}
3351struct Fooa {}
3352
3353mod a {
3354 use super::*;
3355 impl Fooa {}
3356}
3357
3358mod b {
3359 use super::*;
3360 impl Foo$0
3361}
3362
3363"#,
3364 expect![[r#"
3365 st Fooa Fooa []
3366 tt Foob []
3367 md a:: []
3368 md b:: []
3369 "#]],
3370 );
3371 }
3372
3373 #[test]
3374 fn score_patterns() {
3375 check_relevance(
3376 r#"
3377struct Foo(Bar);
3378struct Bar { field: i32 }
3379fn go(Foo($0): Foo) {}
3380"#,
3381 expect![[r#"
3382 bn Bar {…} Bar { field$1 }$0 [type]
3383 st Bar []
3384 st Foo []
3385 bn Foo(…) Foo($1)$0 []
3386 "#]],
3387 );
3388
3389 check_relevance(
3390 r#"
3391struct Foo(Bar);
3392enum Bar { Variant { field: i32 } }
3393fn go(foo: Foo) { match foo { Foo($0) } }
3394"#,
3395 expect![[r#"
3396 bn Bar::Variant {…} Bar::Variant { field$1 }$0 [type]
3397 en Bar []
3398 st Foo []
3399 bn Foo(…) Foo($1)$0 []
3400 "#]],
3401 );
3402 }
3403
3404 #[test]
3405 fn not_type_match_useless_types() {
3406 check_relevance(
3407 r#"
3408fn foo() -> Unknown {}
3409fn test() {
3410 let unit = ();
3411 let unknown = unknown;
3412 let _: () = $0;
3413}
3414"#,
3415 expect![[r#"
3416 lc unit () [local]
3417 fn foo() fn() -> {unknown} []
3418 fn test() fn() []
3419 "#]],
3420 );
3421 check_relevance(
3422 r#"
3423fn foo() -> Unknown {}
3424fn test() {
3425 let unit = ();
3426 let unknown = unknown;
3427 let _ = $0;
3428}
3429"#,
3430 expect![[r#"
3431 lc unit () [local]
3432 fn foo() fn() -> {unknown} []
3433 fn test() fn() []
3434 "#]],
3435 );
3436 check_relevance(
3437 r#"
3438struct Matches;
3439impl Matches {
3440 fn opt_present(&self) -> bool {}
3441}
3442mod module {
3443 pub fn max<T>(a: T, b: T) -> T {}
3444 pub fn min<T>(a: T, b: T) -> T {}
3445}
3446use module::max;
3447fn test(matches: &Matches) {
3448 if m$0
3449}
3450"#,
3451 expect![[r#"
3452 ex false [type]
3453 ex true [type]
3454 lc matches &Matches [local]
3455 st Matches Matches []
3456 fn max(…) fn(T, T) -> T []
3457 md module:: []
3458 fn test(…) fn(&Matches) []
3459 fn min(…) fn(T, T) -> T [requires_import]
3460 "#]],
3461 );
3462 }
3463
3464 #[test]
3465 fn test_avoid_redundant_suggestion() {
3466 check_relevance(
3467 r#"
3468struct aa([u8]);
3469
3470impl aa {
3471 fn from_bytes(bytes: &[u8]) -> &Self {
3472 unsafe { &*(bytes as *const [u8] as *const aa) }
3473 }
3474}
3475
3476fn bb()-> &'static aa {
3477 let bytes = b"hello";
3478 aa::$0
3479}
3480"#,
3481 expect![[r#"
3482 fn from_bytes(…) fn(&[u8]) -> &aa [type_could_unify]
3483 "#]],
3484 );
3485 }
3486
3487 #[test]
3488 fn suggest_ref_mut() {
3489 cov_mark::check!(suggest_ref);
3490 check_relevance(
3491 r#"
3492struct S;
3493fn foo(s: &mut S) {}
3494fn main() {
3495 let mut s = S;
3496 foo($0);
3497}
3498 "#,
3499 expect![[r#"
3500 lc s S [name+local]
3501 lc &mut s [type+name+local]
3502 st S S []
3503 st &mut S [type]
3504 st S S []
3505 fn foo(…) fn(&mut S) []
3506 fn main() fn() []
3507 "#]],
3508 );
3509 check_relevance(
3510 r#"
3511struct S;
3512fn foo(s: &mut S) {}
3513fn main() {
3514 let mut s = S;
3515 foo(&mut $0);
3516}
3517 "#,
3518 expect![[r#"
3520 lc s S [type+name+local]
3521 st S S [type]
3522 st S S [type]
3523 ex S [type]
3524 ex s [type]
3525 fn foo(…) fn(&mut S) []
3526 fn main() fn() []
3527 "#]],
3528 );
3529 check_relevance(
3530 r#"
3531struct S;
3532fn foo(s: &mut S) {}
3533fn main() {
3534 let mut ssss = S;
3535 foo(&mut s$0);
3536}
3537 "#,
3538 expect![[r#"
3539 st S S [type]
3540 lc ssss S [type+local]
3541 st S S [type]
3542 ex S [type]
3543 ex ssss [type]
3544 fn foo(…) fn(&mut S) []
3545 fn main() fn() []
3546 "#]],
3547 );
3548 check_relevance(
3549 r#"
3550struct S;
3551fn foo(s: &&S) {}
3552fn main() {
3553 let mut ssss = &S;
3554 foo($0);
3555}
3556 "#,
3557 expect![[r#"
3558 st S S []
3559 lc ssss &S [local]
3560 lc &ssss [type+local]
3561 st S S []
3562 fn foo(…) fn(&&S) []
3563 fn main() fn() []
3564 "#]],
3565 );
3566 check_relevance(
3567 r#"
3568struct S<T>(T);
3569fn foo<T>(s: &mut S<T>) {}
3570fn main() {
3571 let mut ssss = S(2u32);
3572 foo($0);
3573}
3574 "#,
3575 expect![[r#"
3576 st S(…) S(T) []
3577 st &mut S(…) [type]
3578 lc ssss S<u32> [local]
3579 lc &mut ssss [type+local]
3580 st S S<T> []
3581 fn foo(…) fn(&mut S<T>) []
3582 fn main() fn() []
3583 "#]],
3584 );
3585 check_relevance(
3586 r#"
3587struct S { info: u32 }
3588impl S {
3589 fn info(&self) -> u32 { self.info }
3590 fn foo(&self) {
3591 needs(i$0);
3592 }
3593}
3594fn needs(info: &mut u32) {}
3595 "#,
3596 expect![[r#"
3597 fd self.info u32 [name]
3598 fd &mut self.info [type+name]
3599 me self.info() fn(&self) -> u32 [name]
3600 me &mut self.info() [type+name]
3601 lc self &S [local]
3602 st S S []
3603 sp Self S []
3604 fn needs(…) fn(&mut u32) []
3605 me self.foo() fn(&self) []
3606 "#]],
3607 );
3608 check_relevance(
3610 r#"
3611//- minicore: deref
3612struct S<T>(T);
3613impl<T> core::ops::Deref for S<T> {
3614 type Target = T;
3615}
3616fn foo<T>(s: &u32) {}
3617fn main() {
3618 let ssss = S();
3619 foo($0);
3620}
3621 "#,
3622 expect![[r#"
3623 lc ssss S<{unknown}> [local]
3624 st S S<T> []
3625 md core:: []
3626 fn foo(…) fn(&u32) []
3627 fn main() fn() []
3628 "#]],
3629 );
3630 check_relevance(
3631 r#"
3632//- minicore: deref
3633fn foo<T>(s: &T) {}
3634fn main() {
3635 let ssss = &mut 2i32;
3636 foo($0);
3637}
3638 "#,
3639 expect![[r#"
3640 lc ssss &mut i32 [type_could_unify+local]
3641 md core:: []
3642 fn foo(…) fn(&T) []
3643 fn main() fn() []
3644 "#]],
3645 );
3646 }
3647
3648 #[test]
3649 fn suggest_deref_copy() {
3650 cov_mark::check!(suggest_deref);
3651 check_relevance(
3652 r#"
3653//- minicore: copy
3654struct Foo;
3655
3656impl Copy for Foo {}
3657impl Clone for Foo {
3658 fn clone(&self) -> Self { *self }
3659}
3660
3661fn bar(x: Foo) {}
3662
3663fn main() {
3664 let foo = &Foo;
3665 bar($0);
3666}
3667"#,
3668 expect![[r#"
3669 st Foo Foo [type]
3670 st Foo Foo [type]
3671 ex Foo [type]
3672 lc foo &Foo [local]
3673 lc *foo [type+local]
3674 tt Clone []
3675 tt Copy []
3676 fn bar(…) fn(Foo) []
3677 md core:: []
3678 fn main() fn() []
3679 "#]],
3680 );
3681 }
3682
3683 #[test]
3684 fn suggest_deref_trait() {
3685 check_relevance(
3686 r#"
3687//- minicore: deref
3688struct S;
3689struct T(S);
3690
3691impl core::ops::Deref for T {
3692 type Target = S;
3693
3694 fn deref(&self) -> &Self::Target {
3695 &self.0
3696 }
3697}
3698
3699fn foo(s: &S) {}
3700
3701fn main() {
3702 let t = T(S);
3703 let m = 123;
3704
3705 foo($0);
3706}
3707 "#,
3708 expect![[r#"
3709 st S S []
3710 st &S [type]
3711 ex core::ops::Deref::deref(&t) [type_could_unify]
3712 lc m i32 [local]
3713 lc t T [local]
3714 lc &t [type+local]
3715 st S S []
3716 st T T []
3717 md core:: []
3718 fn foo(…) fn(&S) []
3719 fn main() fn() []
3720 "#]],
3721 )
3722 }
3723
3724 #[test]
3725 fn suggest_deref_mut() {
3726 check_relevance(
3727 r#"
3728//- minicore: deref_mut
3729struct S;
3730struct T(S);
3731
3732impl core::ops::Deref for T {
3733 type Target = S;
3734
3735 fn deref(&self) -> &Self::Target {
3736 &self.0
3737 }
3738}
3739
3740impl core::ops::DerefMut for T {
3741 fn deref_mut(&mut self) -> &mut Self::Target {
3742 &mut self.0
3743 }
3744}
3745
3746fn foo(s: &mut S) {}
3747
3748fn main() {
3749 let t = T(S);
3750 let m = 123;
3751
3752 foo($0);
3753}
3754 "#,
3755 expect![[r#"
3756 st S S []
3757 st &mut S [type]
3758 ex core::ops::DerefMut::deref_mut(&mut t) [type_could_unify]
3759 lc m i32 [local]
3760 lc t T [local]
3761 lc &mut t [type+local]
3762 st S S []
3763 st T T []
3764 md core:: []
3765 fn foo(…) fn(&mut S) []
3766 fn main() fn() []
3767 "#]],
3768 )
3769 }
3770
3771 #[test]
3772 fn locals() {
3773 check_relevance(
3774 r#"
3775fn foo(bar: u32) {
3776 let baz = 0;
3777
3778 f$0
3779}
3780"#,
3781 expect![[r#"
3782 lc bar u32 [local]
3783 lc baz i32 [local]
3784 fn foo(…) fn(u32) []
3785 "#]],
3786 );
3787 }
3788
3789 #[test]
3790 fn enum_owned() {
3791 check_relevance(
3792 r#"
3793enum Foo { A, B }
3794fn foo() {
3795 bar($0);
3796}
3797fn bar(t: Foo) {}
3798"#,
3799 expect![[r#"
3800 ev Foo::A Foo::A [type]
3801 ev Foo::B Foo::B [type]
3802 en Foo Foo [type]
3803 ex Foo::A [type]
3804 ex Foo::B [type]
3805 fn bar(…) fn(Foo) []
3806 fn foo() fn() []
3807 "#]],
3808 );
3809 }
3810
3811 #[test]
3812 fn enum_ref() {
3813 check_relevance(
3814 r#"
3815enum Foo { A, B }
3816fn foo() {
3817 bar($0);
3818}
3819fn bar(t: &Foo) {}
3820"#,
3821 expect![[r#"
3822 ev Foo::A Foo::A []
3823 ev &Foo::A [type]
3824 ev Foo::B Foo::B []
3825 ev &Foo::B [type]
3826 en Foo Foo []
3827 fn bar(…) fn(&Foo) []
3828 fn foo() fn() []
3829 "#]],
3830 );
3831 }
3832
3833 #[test]
3834 fn suggest_deref_fn_ret() {
3835 check_relevance(
3836 r#"
3837//- minicore: deref
3838struct S;
3839struct T(S);
3840
3841impl core::ops::Deref for T {
3842 type Target = S;
3843
3844 fn deref(&self) -> &Self::Target {
3845 &self.0
3846 }
3847}
3848
3849fn foo(s: &S) {}
3850fn bar() -> T {}
3851
3852fn main() {
3853 foo($0);
3854}
3855"#,
3856 expect![[r#"
3857 st S S []
3858 st &S [type]
3859 ex core::ops::Deref::deref(&bar()) [type_could_unify]
3860 st S S []
3861 st T T []
3862 fn bar() fn() -> T []
3863 fn &bar() [type]
3864 md core:: []
3865 fn foo(…) fn(&S) []
3866 fn main() fn() []
3867 "#]],
3868 )
3869 }
3870
3871 #[test]
3872 fn op_function_relevances() {
3873 check_relevance(
3874 r#"
3875#[lang = "sub"]
3876trait Sub {
3877 fn sub(self, other: Self) -> Self { self }
3878}
3879impl Sub for u32 {}
3880fn foo(a: u32) { a.$0 }
3881"#,
3882 expect![[r#"
3883 me sub(…) fn(self, Self) -> Self [op_method]
3884 "#]],
3885 );
3886 check_relevance(
3887 r#"
3888struct Foo;
3889impl Foo {
3890 fn new() -> Self {}
3891}
3892#[lang = "eq"]
3893pub trait PartialEq<Rhs: ?Sized = Self> {
3894 fn eq(&self, other: &Rhs) -> bool;
3895 fn ne(&self, other: &Rhs) -> bool;
3896}
3897
3898impl PartialEq for Foo {}
3899fn main() {
3900 Foo::$0
3901}
3902"#,
3903 expect![[r#"
3904 fn new() fn() -> Foo []
3905 me eq(…) fn(&self, &Rhs) -> bool [op_method]
3906 me ne(…) fn(&self, &Rhs) -> bool [op_method]
3907 "#]],
3908 );
3909 }
3910
3911 #[test]
3912 fn constructor_order_simple() {
3913 check_relevance(
3914 r#"
3915struct Foo;
3916struct Other;
3917struct Option<T>(T);
3918
3919impl Foo {
3920 fn fn_ctr() -> Foo { unimplemented!() }
3921 fn fn_another(n: u32) -> Other { unimplemented!() }
3922 fn fn_ctr_self() -> Option<Self> { unimplemented!() }
3923}
3924
3925fn test() {
3926 let a = Foo::$0;
3927}
3928"#,
3929 expect![[r#"
3930 fn fn_ctr() fn() -> Foo []
3931 fn fn_ctr_self() fn() -> Option<Foo> []
3932 fn fn_another(…) fn(u32) -> Other []
3933 "#]],
3934 );
3935 }
3936
3937 #[test]
3938 fn trait_items_order() {
3939 check_relevance(
3940 r#"
3941trait T{
3942 fn a_optional() {}
3943 fn b_required();
3944}
3945
3946impl T for (){
3947 $0
3948}
3949"#,
3950 expect![[r#"
3951 fn fn b_required() [name+missing]
3952 fn fn a_optional() [name]
3953 "#]],
3954 );
3955 check_relevance(
3956 r#"
3957trait T{
3958 type Item;
3959 fn optional() {}
3960}
3961impl T for (){
3962 $0
3963}
3964"#,
3965 expect![[r#"
3966 ta type Item = [name+missing]
3967 fn fn optional() [name]
3968 "#]],
3969 );
3970 check_relevance(
3971 r#"
3972trait T{
3973 const A: usize = 0;
3974 const B: usize;
3975}
3976impl T for (){
3977 $0
3978}
3979"#,
3980 expect![[r#"
3981 ct const B: usize = [name+missing]
3982 ct const A: usize = [name]
3983 "#]],
3984 );
3985 }
3986
3987 #[test]
3988 fn constructor_order_kind() {
3989 check_function_relevance(
3990 r#"
3991struct Foo;
3992struct Bar;
3993struct Option<T>(T);
3994enum Result<T, E> { Ok(T), Err(E) };
3995
3996impl Foo {
3997 fn fn_ctr(&self) -> Foo { unimplemented!() }
3998 fn fn_ctr_with_args(&self, n: u32) -> Foo { unimplemented!() }
3999 fn fn_another(&self, n: u32) -> Bar { unimplemented!() }
4000 fn fn_ctr_wrapped(&self, ) -> Option<Self> { unimplemented!() }
4001 fn fn_ctr_wrapped_2(&self, ) -> Result<Self, Bar> { unimplemented!() }
4002 fn fn_ctr_wrapped_3(&self, ) -> Result<Bar, Self> { unimplemented!() } // Self is not the first type
4003 fn fn_ctr_wrapped_with_args(&self, m: u32) -> Option<Self> { unimplemented!() }
4004 fn fn_another_unit(&self) { unimplemented!() }
4005}
4006
4007fn test() {
4008 let a = self::Foo::$0;
4009}
4010"#,
4011 expect![[r#"
4012 [
4013 (
4014 "fn(&self, u32) -> Bar",
4015 Some(
4016 CompletionRelevanceFn {
4017 has_params: true,
4018 has_self_param: true,
4019 return_type: Other,
4020 },
4021 ),
4022 ),
4023 (
4024 "fn(&self)",
4025 Some(
4026 CompletionRelevanceFn {
4027 has_params: true,
4028 has_self_param: true,
4029 return_type: Other,
4030 },
4031 ),
4032 ),
4033 (
4034 "fn(&self) -> Foo",
4035 Some(
4036 CompletionRelevanceFn {
4037 has_params: true,
4038 has_self_param: true,
4039 return_type: DirectConstructor,
4040 },
4041 ),
4042 ),
4043 (
4044 "fn(&self, u32) -> Foo",
4045 Some(
4046 CompletionRelevanceFn {
4047 has_params: true,
4048 has_self_param: true,
4049 return_type: DirectConstructor,
4050 },
4051 ),
4052 ),
4053 (
4054 "fn(&self) -> Option<Foo>",
4055 Some(
4056 CompletionRelevanceFn {
4057 has_params: true,
4058 has_self_param: true,
4059 return_type: Constructor,
4060 },
4061 ),
4062 ),
4063 (
4064 "fn(&self) -> Result<Foo, Bar>",
4065 Some(
4066 CompletionRelevanceFn {
4067 has_params: true,
4068 has_self_param: true,
4069 return_type: Constructor,
4070 },
4071 ),
4072 ),
4073 (
4074 "fn(&self) -> Result<Bar, Foo>",
4075 Some(
4076 CompletionRelevanceFn {
4077 has_params: true,
4078 has_self_param: true,
4079 return_type: Constructor,
4080 },
4081 ),
4082 ),
4083 (
4084 "fn(&self, u32) -> Option<Foo>",
4085 Some(
4086 CompletionRelevanceFn {
4087 has_params: true,
4088 has_self_param: true,
4089 return_type: Constructor,
4090 },
4091 ),
4092 ),
4093 ]
4094 "#]],
4095 );
4096 }
4097
4098 #[test]
4099 fn constructor_order_relevance() {
4100 check_relevance(
4101 r#"
4102struct Foo;
4103struct FooBuilder;
4104struct Result<T>(T);
4105
4106impl Foo {
4107 fn fn_no_ret(&self) {}
4108 fn fn_ctr_with_args(input: u32) -> Foo { unimplemented!() }
4109 fn fn_direct_ctr() -> Self { unimplemented!() }
4110 fn fn_ctr() -> Result<Self> { unimplemented!() }
4111 fn fn_other() -> Result<u32> { unimplemented!() }
4112 fn fn_builder() -> FooBuilder { unimplemented!() }
4113}
4114
4115fn test() {
4116 let a = self::Foo::$0;
4117}
4118"#,
4119 expect![[r#"
4126 fn fn_direct_ctr() fn() -> Foo []
4127 fn fn_ctr_with_args(…) fn(u32) -> Foo []
4128 fn fn_builder() fn() -> FooBuilder []
4129 fn fn_ctr() fn() -> Result<Foo> []
4130 me fn_no_ret(…) fn(&self) []
4131 fn fn_other() fn() -> Result<u32> []
4132 "#]],
4133 );
4134
4135 }
4137
4138 #[test]
4139 fn function_relevance_generic_1() {
4140 check_relevance(
4141 r#"
4142struct Foo<T: Default>(T);
4143struct FooBuilder;
4144struct Option<T>(T);
4145enum Result<T, E>{Ok(T), Err(E)};
4146
4147impl<T: Default> Foo<T> {
4148 fn fn_returns_unit(&self) {}
4149 fn fn_ctr_with_args(input: T) -> Foo<T> { unimplemented!() }
4150 fn fn_direct_ctr() -> Self { unimplemented!() }
4151 fn fn_ctr_wrapped() -> Option<Self> { unimplemented!() }
4152 fn fn_ctr_wrapped_2() -> Result<Self, u32> { unimplemented!() }
4153 fn fn_other() -> Option<u32> { unimplemented!() }
4154 fn fn_builder() -> FooBuilder { unimplemented!() }
4155}
4156
4157fn test() {
4158 let a = self::Foo::<u32>::$0;
4159}
4160 "#,
4161 expect![[r#"
4162 fn fn_direct_ctr() fn() -> Foo<T> []
4163 fn fn_ctr_with_args(…) fn(T) -> Foo<T> []
4164 fn fn_builder() fn() -> FooBuilder []
4165 fn fn_ctr_wrapped() fn() -> Option<Foo<T>> []
4166 fn fn_ctr_wrapped_2() fn() -> Result<Foo<T>, u32> []
4167 fn fn_other() fn() -> Option<u32> []
4168 me fn_returns_unit(…) fn(&self) []
4169 "#]],
4170 );
4171 }
4172
4173 #[test]
4174 fn function_relevance_generic_2() {
4175 check_relevance(
4177 r#"
4178struct Foo<T: Default>(T);
4179struct FooBuilder;
4180struct Option<T>(T);
4181enum Result<T, E>{Ok(T), Err(E)};
4182
4183impl<T: Default> Foo<T> {
4184 fn fn_no_ret(&self) {}
4185 fn fn_ctr_with_args(input: T) -> Foo<T> { unimplemented!() }
4186 fn fn_direct_ctr() -> Self { unimplemented!() }
4187 fn fn_ctr() -> Option<Self> { unimplemented!() }
4188 fn fn_ctr2() -> Result<Self, u32> { unimplemented!() }
4189 fn fn_other() -> Option<u32> { unimplemented!() }
4190 fn fn_builder() -> FooBuilder { unimplemented!() }
4191}
4192
4193fn test() {
4194 let a : Res<Foo<u32>> = Foo::$0;
4195}
4196 "#,
4197 expect![[r#"
4198 fn fn_direct_ctr() fn() -> Foo<T> []
4199 fn fn_ctr_with_args(…) fn(T) -> Foo<T> []
4200 fn fn_builder() fn() -> FooBuilder []
4201 fn fn_ctr() fn() -> Option<Foo<T>> []
4202 fn fn_ctr2() fn() -> Result<Foo<T>, u32> []
4203 me fn_no_ret(…) fn(&self) []
4204 fn fn_other() fn() -> Option<u32> []
4205 "#]],
4206 );
4207 }
4208
4209 #[test]
4210 fn struct_field_method_ref() {
4211 check_kinds(
4212 r#"
4213struct Foo { bar: u32, qux: fn() }
4214impl Foo { fn baz(&self) -> u32 { 0 } }
4215
4216fn foo(f: Foo) { let _: &u32 = f.b$0 }
4217"#,
4218 &[
4219 CompletionItemKind::SymbolKind(SymbolKind::Method),
4220 CompletionItemKind::SymbolKind(SymbolKind::Field),
4221 ],
4222 expect![[r#"
4223 [
4224 CompletionItem {
4225 label: "baz()",
4226 detail_left: None,
4227 detail_right: Some(
4228 "fn(&self) -> u32",
4229 ),
4230 source_range: 109..110,
4231 delete: 109..110,
4232 insert: "baz()$0",
4233 kind: SymbolKind(
4234 Method,
4235 ),
4236 lookup: "baz",
4237 detail: "fn(&self) -> u32",
4238 relevance: CompletionRelevance {
4239 exact_name_match: false,
4240 type_match: None,
4241 is_local: false,
4242 is_missing: false,
4243 trait_: None,
4244 is_name_already_imported: false,
4245 requires_import: false,
4246 is_private_editable: false,
4247 postfix_match: None,
4248 function: Some(
4249 CompletionRelevanceFn {
4250 has_params: true,
4251 has_self_param: true,
4252 return_type: Other,
4253 },
4254 ),
4255 is_skipping_completion: false,
4256 has_local_inherent_impl: false,
4257 is_deprecated: false,
4258 },
4259 ref_match: "&@107",
4260 },
4261 CompletionItem {
4262 label: "bar",
4263 detail_left: None,
4264 detail_right: Some(
4265 "u32",
4266 ),
4267 source_range: 109..110,
4268 delete: 109..110,
4269 insert: "bar",
4270 kind: SymbolKind(
4271 Field,
4272 ),
4273 detail: "u32",
4274 ref_match: "&@107",
4275 },
4276 CompletionItem {
4277 label: "qux",
4278 detail_left: None,
4279 detail_right: Some(
4280 "fn()",
4281 ),
4282 source_range: 109..110,
4283 text_edit: TextEdit {
4284 indels: [
4285 Indel {
4286 insert: "(",
4287 delete: 107..107,
4288 },
4289 Indel {
4290 insert: "qux)()",
4291 delete: 109..110,
4292 },
4293 ],
4294 annotation: None,
4295 },
4296 kind: SymbolKind(
4297 Field,
4298 ),
4299 detail: "fn()",
4300 },
4301 ]
4302 "#]],
4303 );
4304 }
4305
4306 #[test]
4307 fn expected_fn_type_ref() {
4308 check_kinds(
4309 r#"
4310struct S { field: fn() }
4311
4312fn foo() {
4313 let foo: fn() = S { fields: || {}}.fi$0;
4314}
4315"#,
4316 &[CompletionItemKind::SymbolKind(SymbolKind::Field)],
4317 expect![[r#"
4318 [
4319 CompletionItem {
4320 label: "field",
4321 detail_left: None,
4322 detail_right: Some(
4323 "fn()",
4324 ),
4325 source_range: 76..78,
4326 delete: 76..78,
4327 insert: "field",
4328 kind: SymbolKind(
4329 Field,
4330 ),
4331 detail: "fn()",
4332 relevance: CompletionRelevance {
4333 exact_name_match: false,
4334 type_match: Some(
4335 Exact,
4336 ),
4337 is_local: false,
4338 is_missing: false,
4339 trait_: None,
4340 is_name_already_imported: false,
4341 requires_import: false,
4342 is_private_editable: false,
4343 postfix_match: None,
4344 function: None,
4345 is_skipping_completion: false,
4346 has_local_inherent_impl: false,
4347 is_deprecated: false,
4348 },
4349 },
4350 ]
4351 "#]],
4352 )
4353 }
4354
4355 #[test]
4356 fn qualified_path_ref() {
4357 check_kinds(
4358 r#"
4359struct S;
4360
4361struct T;
4362impl T {
4363 fn foo() -> S {}
4364}
4365
4366fn bar(s: &S) {}
4367
4368fn main() {
4369 bar(T::$0);
4370}
4371"#,
4372 &[CompletionItemKind::SymbolKind(SymbolKind::Function)],
4373 expect![[r#"
4374 [
4375 CompletionItem {
4376 label: "foo()",
4377 detail_left: None,
4378 detail_right: Some(
4379 "fn() -> S",
4380 ),
4381 source_range: 95..95,
4382 delete: 95..95,
4383 insert: "foo()$0",
4384 kind: SymbolKind(
4385 Function,
4386 ),
4387 lookup: "foo",
4388 detail: "fn() -> S",
4389 relevance: CompletionRelevance {
4390 exact_name_match: false,
4391 type_match: None,
4392 is_local: false,
4393 is_missing: false,
4394 trait_: None,
4395 is_name_already_imported: false,
4396 requires_import: false,
4397 is_private_editable: false,
4398 postfix_match: None,
4399 function: Some(
4400 CompletionRelevanceFn {
4401 has_params: false,
4402 has_self_param: false,
4403 return_type: Other,
4404 },
4405 ),
4406 is_skipping_completion: false,
4407 has_local_inherent_impl: false,
4408 is_deprecated: false,
4409 },
4410 ref_match: "&@92",
4411 },
4412 ]
4413 "#]],
4414 );
4415 }
4416
4417 #[test]
4418 fn generic_enum() {
4419 check_relevance(
4420 r#"
4421enum Foo<T> { A(T), B }
4422// bar() should not be an exact type match
4423// because the generic parameters are different
4424fn bar() -> Foo<u8> { Foo::B }
4425// FIXME baz() should be an exact type match
4426// because the types could unify, but it currently
4427// is not. This is due to the T here being
4428// TyKind::Placeholder rather than TyKind::Missing.
4429fn baz<T>() -> Foo<T> { Foo::B }
4430fn foo() {
4431 let foo: Foo<u32> = Foo::B;
4432 let _: Foo<u32> = f$0;
4433}
4434"#,
4435 expect![[r#"
4436 lc foo Foo<u32> [type+local]
4437 ex Foo::B [type]
4438 ex foo [type]
4439 ev Foo::B Foo::B [type_could_unify]
4440 ev Foo::A(…) Foo::A(T) [type_could_unify]
4441 en Foo Foo<T> [type_could_unify]
4442 fn baz() fn() -> Foo<T> [type_could_unify]
4443 fn bar() fn() -> Foo<u8> []
4444 fn foo() fn() []
4445 "#]],
4446 );
4447 }
4448
4449 #[test]
4450 fn postfix_exact_match_is_high_priority() {
4451 cov_mark::check!(postfix_exact_match_is_high_priority);
4452 check_relevance_for_kinds(
4453 r#"
4454mod ops {
4455 pub trait Not {
4456 type Output;
4457 fn not(self) -> Self::Output;
4458 }
4459
4460 impl Not for bool {
4461 type Output = bool;
4462 fn not(self) -> bool { if self { false } else { true }}
4463 }
4464}
4465
4466fn main() {
4467 let _: bool = (9 > 2).not$0;
4468}
4469 "#,
4470 &[CompletionItemKind::Snippet, CompletionItemKind::SymbolKind(SymbolKind::Method)],
4471 expect![[r#"
4472 sn not !expr [snippet]
4473 me not() fn(self) -> <Self as Not>::Output [type_could_unify+requires_import]
4474 sn box Box::new(expr) []
4475 sn call function(expr) []
4476 sn const const {} []
4477 sn dbg dbg!(expr) []
4478 sn dbgr dbg!(&expr) []
4479 sn deref *expr []
4480 sn if if expr {} []
4481 sn match match expr {} []
4482 sn ref &expr []
4483 sn refm &mut expr []
4484 sn return return expr []
4485 sn unsafe unsafe {} []
4486 sn while while expr {} []
4487 "#]],
4488 );
4489 }
4490
4491 #[test]
4492 fn enum_variant_name_exact_match_is_high_priority() {
4493 check_relevance(
4494 r#"
4495struct Other;
4496struct String;
4497enum Foo {
4498 String($0)
4499}
4500 "#,
4501 expect![[r#"
4502 st String String [name]
4503 en Foo Foo []
4504 st Other Other []
4505 sp Self Foo []
4506 "#]],
4507 );
4508
4509 check_relevance(
4510 r#"
4511struct Other;
4512struct String;
4513enum Foo {
4514 String(String, $0)
4515}
4516 "#,
4517 expect![[r#"
4518 en Foo Foo []
4519 st Other Other []
4520 sp Self Foo []
4521 st String String []
4522 "#]],
4523 );
4524
4525 check_relevance(
4526 r#"
4527struct Other;
4528struct Vec<T>(T);
4529enum Foo {
4530 Vec(Vec<$0>)
4531}
4532 "#,
4533 expect![[r#"
4534 en Foo Foo []
4535 st Other Other []
4536 sp Self Foo []
4537 st Vec<…> Vec<T> []
4538 "#]],
4539 );
4540 }
4541
4542 #[test]
4543 fn postfix_inexact_match_is_low_priority() {
4544 cov_mark::check!(postfix_inexact_match_is_low_priority);
4545 check_relevance_for_kinds(
4546 r#"
4547struct S;
4548impl S {
4549 fn f(&self) {}
4550}
4551fn main() {
4552 S.$0
4553}
4554 "#,
4555 &[CompletionItemKind::Snippet, CompletionItemKind::SymbolKind(SymbolKind::Method)],
4556 expect![[r#"
4557 me f() fn(&self) []
4558 sn box Box::new(expr) []
4559 sn call function(expr) []
4560 sn const const {} []
4561 sn dbg dbg!(expr) []
4562 sn dbgr dbg!(&expr) []
4563 sn deref *expr []
4564 sn let let []
4565 sn letm let mut []
4566 sn match match expr {} []
4567 sn ref &expr []
4568 sn refm &mut expr []
4569 sn return return expr []
4570 sn unsafe unsafe {} []
4571 "#]],
4572 );
4573 }
4574
4575 #[test]
4576 fn flyimport_reduced_relevance() {
4577 check_relevance(
4578 r#"
4579mod std {
4580 pub mod io {
4581 pub trait BufRead {}
4582 pub struct BufReader;
4583 pub struct BufWriter;
4584 }
4585}
4586struct Buffer;
4587
4588fn f() {
4589 Buf$0
4590}
4591"#,
4592 expect![[r#"
4593 st Buffer Buffer []
4594 fn f() fn() []
4595 md std:: []
4596 tt BufRead [requires_import]
4597 st BufReader BufReader [requires_import]
4598 st BufWriter BufWriter [requires_import]
4599 "#]],
4600 );
4601 }
4602
4603 #[test]
4604 fn float_consts_relevance() {
4606 check_relevance(
4607 r#"
4608//- minicore: float_consts
4609fn main() {
4610 let x = f32::INF$0
4611}
4612"#,
4613 expect![[r#"
4614 ct INFINITY pub const INFINITY: f32 []
4615 ct NEG_INFINITY pub const NEG_INFINITY: f32 []
4616 ct INFINITY f32 [requires_import+deprecated]
4617 ct NEG_INFINITY f32 [requires_import+deprecated]
4618 "#]],
4619 );
4620 check_relevance(
4621 r#"
4622//- minicore: float_consts
4623fn main() {
4624 let x: f32 = f32::INF$0
4625}
4626"#,
4627 expect![[r#"
4628 ct INFINITY pub const INFINITY: f32 [type]
4629 ct NEG_INFINITY pub const NEG_INFINITY: f32 [type]
4630 ct INFINITY f32 [type+requires_import+deprecated]
4631 ct NEG_INFINITY f32 [type+requires_import+deprecated]
4632 "#]],
4633 );
4634 }
4635
4636 #[test]
4637 fn completes_struct_with_raw_identifier() {
4638 check_edit(
4639 "type",
4640 r#"
4641mod m { pub struct r#type {} }
4642fn main() {
4643 let r#type = m::t$0;
4644}
4645"#,
4646 r#"
4647mod m { pub struct r#type {} }
4648fn main() {
4649 let r#type = m::r#type;
4650}
4651"#,
4652 )
4653 }
4654
4655 #[test]
4656 fn completes_fn_with_raw_identifier() {
4657 check_edit(
4658 "type",
4659 r#"
4660mod m { pub fn r#type {} }
4661fn main() {
4662 m::t$0
4663}
4664"#,
4665 r#"
4666mod m { pub fn r#type {} }
4667fn main() {
4668 m::r#type();$0
4669}
4670"#,
4671 )
4672 }
4673
4674 #[test]
4675 fn completes_macro_with_raw_identifier() {
4676 check_edit(
4677 "let!",
4678 r#"
4679macro_rules! r#let { () => {} }
4680fn main() {
4681 $0
4682}
4683"#,
4684 r#"
4685macro_rules! r#let { () => {} }
4686fn main() {
4687 r#let!($0)
4688}
4689"#,
4690 )
4691 }
4692
4693 #[test]
4694 fn completes_variant_with_raw_identifier() {
4695 check_edit(
4696 "type",
4697 r#"
4698enum A { r#type }
4699fn main() {
4700 let a = A::t$0
4701}
4702"#,
4703 r#"
4704enum A { r#type }
4705fn main() {
4706 let a = A::r#type$0
4707}
4708"#,
4709 )
4710 }
4711
4712 #[test]
4713 fn completes_field_with_raw_identifier() {
4714 check_edit(
4715 "fn",
4716 r#"
4717mod r#type {
4718 pub struct r#struct {
4719 pub r#fn: u32
4720 }
4721}
4722
4723fn main() {
4724 let a = r#type::r#struct {};
4725 a.$0
4726}
4727"#,
4728 r#"
4729mod r#type {
4730 pub struct r#struct {
4731 pub r#fn: u32
4732 }
4733}
4734
4735fn main() {
4736 let a = r#type::r#struct {};
4737 a.r#fn
4738}
4739"#,
4740 )
4741 }
4742
4743 #[test]
4744 fn completes_const_with_raw_identifier() {
4745 check_edit(
4746 "type",
4747 r#"
4748struct r#struct {}
4749impl r#struct { pub const r#type: u8 = 1; }
4750fn main() {
4751 r#struct::t$0
4752}
4753"#,
4754 r#"
4755struct r#struct {}
4756impl r#struct { pub const r#type: u8 = 1; }
4757fn main() {
4758 r#struct::r#type
4759}
4760"#,
4761 )
4762 }
4763
4764 #[test]
4765 fn completes_type_alias_with_raw_identifier() {
4766 check_edit(
4767 "type type",
4768 r#"
4769struct r#struct {}
4770trait r#trait { type r#type; }
4771impl r#trait for r#struct { type t$0 }
4772"#,
4773 r#"
4774struct r#struct {}
4775trait r#trait { type r#type; }
4776impl r#trait for r#struct { type r#type = $0; }
4777"#,
4778 )
4779 }
4780
4781 #[test]
4782 fn field_access_includes_self() {
4783 check_edit(
4784 "length",
4785 r#"
4786struct S {
4787 length: i32
4788}
4789
4790impl S {
4791 fn some_fn(&self) {
4792 let l = len$0
4793 }
4794}
4795"#,
4796 r#"
4797struct S {
4798 length: i32
4799}
4800
4801impl S {
4802 fn some_fn(&self) {
4803 let l = self.length
4804 }
4805}
4806"#,
4807 )
4808 }
4809
4810 #[test]
4811 fn field_access_includes_closure_this_param() {
4812 check_edit(
4813 "length",
4814 r#"
4815//- minicore: fn
4816struct S {
4817 length: i32
4818}
4819
4820impl S {
4821 fn pack(&mut self, f: impl FnOnce(&mut Self, i32)) {
4822 self.length += 1;
4823 f(self, 3);
4824 self.length -= 1;
4825 }
4826
4827 fn some_fn(&mut self) {
4828 self.pack(|this, n| len$0);
4829 }
4830}
4831"#,
4832 r#"
4833struct S {
4834 length: i32
4835}
4836
4837impl S {
4838 fn pack(&mut self, f: impl FnOnce(&mut Self, i32)) {
4839 self.length += 1;
4840 f(self, 3);
4841 self.length -= 1;
4842 }
4843
4844 fn some_fn(&mut self) {
4845 self.pack(|this, n| this.length);
4846 }
4847}
4848"#,
4849 )
4850 }
4851
4852 #[test]
4853 fn notable_traits_method_relevance() {
4854 check_kinds(
4855 r#"
4856#[doc(notable_trait)]
4857trait Write {
4858 fn write(&self);
4859 fn flush(&self);
4860}
4861
4862struct Writer;
4863
4864impl Write for Writer {
4865 fn write(&self) {}
4866 fn flush(&self) {}
4867}
4868
4869fn main() {
4870 Writer.$0
4871}
4872"#,
4873 &[
4874 CompletionItemKind::SymbolKind(SymbolKind::Method),
4875 CompletionItemKind::SymbolKind(SymbolKind::Field),
4876 CompletionItemKind::SymbolKind(SymbolKind::Function),
4877 ],
4878 expect![[r#"
4879 [
4880 CompletionItem {
4881 label: "flush()",
4882 detail_left: Some(
4883 "(as Write)",
4884 ),
4885 detail_right: Some(
4886 "fn(&self)",
4887 ),
4888 source_range: 193..193,
4889 delete: 193..193,
4890 insert: "flush();$0",
4891 kind: SymbolKind(
4892 Method,
4893 ),
4894 lookup: "flush",
4895 detail: "fn(&self)",
4896 relevance: CompletionRelevance {
4897 exact_name_match: false,
4898 type_match: None,
4899 is_local: false,
4900 is_missing: false,
4901 trait_: Some(
4902 CompletionRelevanceTraitInfo {
4903 notable_trait: true,
4904 is_op_method: false,
4905 },
4906 ),
4907 is_name_already_imported: false,
4908 requires_import: false,
4909 is_private_editable: false,
4910 postfix_match: None,
4911 function: None,
4912 is_skipping_completion: false,
4913 has_local_inherent_impl: false,
4914 is_deprecated: false,
4915 },
4916 },
4917 CompletionItem {
4918 label: "write()",
4919 detail_left: Some(
4920 "(as Write)",
4921 ),
4922 detail_right: Some(
4923 "fn(&self)",
4924 ),
4925 source_range: 193..193,
4926 delete: 193..193,
4927 insert: "write();$0",
4928 kind: SymbolKind(
4929 Method,
4930 ),
4931 lookup: "write",
4932 detail: "fn(&self)",
4933 relevance: CompletionRelevance {
4934 exact_name_match: false,
4935 type_match: None,
4936 is_local: false,
4937 is_missing: false,
4938 trait_: Some(
4939 CompletionRelevanceTraitInfo {
4940 notable_trait: true,
4941 is_op_method: false,
4942 },
4943 ),
4944 is_name_already_imported: false,
4945 requires_import: false,
4946 is_private_editable: false,
4947 postfix_match: None,
4948 function: None,
4949 is_skipping_completion: false,
4950 has_local_inherent_impl: false,
4951 is_deprecated: false,
4952 },
4953 },
4954 ]
4955 "#]],
4956 );
4957 }
4958}