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) -> &'a RootDatabase {
75 self.completion.db
76 }
77
78 fn source_range(&self) -> TextRange {
79 self.completion.source_range()
80 }
81
82 fn completion_relevance(&self) -> CompletionRelevance {
83 CompletionRelevance {
84 is_private_editable: self.is_private_editable,
85 requires_import: self.import_to_add.is_some(),
86 ..Default::default()
87 }
88 }
89
90 fn is_immediately_after_macro_bang(&self) -> bool {
91 self.completion.token.kind() == SyntaxKind::BANG
92 && self.completion.token.parent().is_some_and(|it| it.kind() == SyntaxKind::MACRO_CALL)
93 }
94
95 fn is_deprecated(&self, def: impl HasAttrs, 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_ast_node(receiver.clone())
185 {
186 builder.insert(receiver.syntax().text_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_ast_node(receiver.clone())
202 && let Some(ref_mode) = compute_ref_match(ctx.completion, ty)
203 {
204 item.ref_match(ref_mode, original.syntax().text_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(
257 ctx: RenderContext<'_, '_>,
258 path_ctx: &PathCompletionCtx<'_>,
259 local_name: hir::Name,
260 resolution: ScopeDef,
261) -> Builder {
262 render_resolution_path(ctx, path_ctx, local_name, None, resolution)
263}
264
265pub(crate) fn render_pattern_resolution(
266 ctx: RenderContext<'_, '_>,
267 pattern_ctx: &PatternContext,
268 local_name: hir::Name,
269 resolution: ScopeDef,
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(
298 ctx: &CompletionContext<'_, '_>,
299 expr: &hir::term_search::Expr<'_>,
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, &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(
360 resolution: ScopeDef,
361 ctx: &RenderContext<'_, '_>,
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(
378 resolution: ScopeDef,
379 ctx: &RenderContext<'_, '_>,
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(
391 ctx: RenderContext<'_, '_>,
392 pattern_ctx: &PatternContext,
393 local_name: hir::Name,
394 import_to_add: Option<LocatedImport>,
395 resolution: ScopeDef,
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(
409 ctx: RenderContext<'_, '_>,
410 path_ctx: &PathCompletionCtx<'_>,
411 local_name: hir::Name,
412 import_to_add: Option<LocatedImport>,
413 resolution: ScopeDef,
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) || !config.add_colons_to_module;
475 if !allow_module_path && matches!(resolution, ScopeDef::ModuleDef(Module(_))) {
476 insert_text = format_smolstr!("{insert_text}::");
477 item.lookup_by(name.clone()).label(insert_text.clone());
478 }
479 adds_ret_type_arrow(completion, path_ctx, &mut item, insert_text.into());
480
481 let mut set_item_relevance = |ty: Type<'_>| {
482 if !ty.is_unknown() {
483 item.detail(ty.display(db, krate).to_string());
484 }
485
486 item.set_relevance(CompletionRelevance {
487 type_match: compute_type_match(completion, &ty),
488 exact_name_match: compute_exact_name_match(completion, &name),
489 is_local: matches!(resolution, ScopeDef::Local(_)),
490 requires_import,
491 has_local_inherent_impl: compute_has_local_inherent_impl(db, path_ctx, &ty, module),
492 ..CompletionRelevance::default()
493 });
494
495 path_ref_match(completion, path_ctx, &ty, &mut item);
496 };
497
498 match resolution {
499 ScopeDef::Local(local) => set_item_relevance(local.ty(db)),
500 ScopeDef::ModuleDef(ModuleDef::Adt(adt)) | ScopeDef::AdtSelfType(adt) => {
501 set_item_relevance(adt.ty(db))
502 }
503 ScopeDef::ModuleDef(
505 ModuleDef::Function(_) | ModuleDef::EnumVariant(_) | ModuleDef::Macro(_),
506 ) => (),
507 ScopeDef::ModuleDef(ModuleDef::Const(konst)) => set_item_relevance(konst.ty(db)),
508 ScopeDef::ModuleDef(ModuleDef::Static(stat)) => set_item_relevance(stat.ty(db)),
509 ScopeDef::ModuleDef(ModuleDef::BuiltinType(bt)) => set_item_relevance(bt.ty(db)),
510 ScopeDef::ImplSelfType(imp) => set_item_relevance(imp.self_ty(db)),
511 ScopeDef::GenericParam(_)
512 | ScopeDef::Label(_)
513 | ScopeDef::Unknown
514 | ScopeDef::ModuleDef(
515 ModuleDef::Trait(_) | ModuleDef::Module(_) | ModuleDef::TypeAlias(_),
516 ) => (),
517 };
518
519 item
520}
521
522fn render_resolution_simple_(
523 ctx: RenderContext<'_, '_>,
524 local_name: &hir::Name,
525 import_to_add: Option<LocatedImport>,
526 resolution: ScopeDef,
527) -> Builder {
528 let _p = tracing::info_span!("render_resolution_simple_").entered();
529
530 let db = ctx.db();
531 let ctx = ctx.import_to_add(import_to_add);
532 let kind = res_to_kind(resolution);
533
534 let mut item = CompletionItem::new(
535 kind,
536 ctx.source_range(),
537 local_name.as_str().to_smolstr(),
538 ctx.completion.edition,
539 );
540 item.set_relevance(ctx.completion_relevance())
541 .set_documentation(scope_def_docs(db, resolution))
542 .set_deprecated(scope_def_is_deprecated(&ctx, resolution));
543
544 if let Some(import_to_add) = ctx.import_to_add {
545 item.add_import(import_to_add);
546 }
547
548 item.doc_aliases(ctx.doc_aliases);
549 item
550}
551
552fn res_to_kind(resolution: ScopeDef) -> CompletionItemKind {
553 use hir::ModuleDef::*;
554 match resolution {
555 ScopeDef::Unknown => CompletionItemKind::UnresolvedReference,
556 ScopeDef::ModuleDef(Function(_)) => CompletionItemKind::SymbolKind(SymbolKind::Function),
557 ScopeDef::ModuleDef(EnumVariant(_)) => CompletionItemKind::SymbolKind(SymbolKind::Variant),
558 ScopeDef::ModuleDef(Macro(_)) => CompletionItemKind::SymbolKind(SymbolKind::Macro),
559 ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::SymbolKind(SymbolKind::Module),
560 ScopeDef::ModuleDef(Adt(adt)) => CompletionItemKind::SymbolKind(match adt {
561 hir::Adt::Struct(_) => SymbolKind::Struct,
562 hir::Adt::Union(_) => SymbolKind::Union,
563 hir::Adt::Enum(_) => SymbolKind::Enum,
564 }),
565 ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::SymbolKind(SymbolKind::Const),
566 ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::SymbolKind(SymbolKind::Static),
567 ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::SymbolKind(SymbolKind::Trait),
568 ScopeDef::ModuleDef(TypeAlias(..)) => CompletionItemKind::SymbolKind(SymbolKind::TypeAlias),
569 ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType,
570 ScopeDef::GenericParam(param) => CompletionItemKind::SymbolKind(match param {
571 hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam,
572 hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam,
573 hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam,
574 }),
575 ScopeDef::Local(..) => CompletionItemKind::SymbolKind(SymbolKind::Local),
576 ScopeDef::Label(..) => CompletionItemKind::SymbolKind(SymbolKind::Label),
577 ScopeDef::AdtSelfType(..) | ScopeDef::ImplSelfType(..) => {
578 CompletionItemKind::SymbolKind(SymbolKind::SelfParam)
579 }
580 }
581}
582
583fn scope_def_docs(db: &RootDatabase, resolution: ScopeDef) -> Option<Documentation<'_>> {
584 use hir::ModuleDef::*;
585 match resolution {
586 ScopeDef::ModuleDef(Module(it)) => it.docs(db),
587 ScopeDef::ModuleDef(Adt(it)) => it.docs(db),
588 ScopeDef::ModuleDef(EnumVariant(it)) => it.docs(db),
589 ScopeDef::ModuleDef(Const(it)) => it.docs(db),
590 ScopeDef::ModuleDef(Static(it)) => it.docs(db),
591 ScopeDef::ModuleDef(Trait(it)) => it.docs(db),
592 ScopeDef::ModuleDef(TypeAlias(it)) => it.docs(db),
593 _ => None,
594 }
595}
596
597fn scope_def_is_deprecated(ctx: &RenderContext<'_, '_>, resolution: ScopeDef) -> bool {
598 let db = ctx.db();
599 match resolution {
600 ScopeDef::ModuleDef(hir::ModuleDef::EnumVariant(it)) => ctx.is_variant_deprecated(it),
601 ScopeDef::ModuleDef(it) => ctx.is_deprecated(it, it.as_assoc_item(db)),
602 ScopeDef::GenericParam(it) => {
603 ctx.is_deprecated(it, None )
604 }
605 ScopeDef::AdtSelfType(it) => {
606 ctx.is_deprecated(it, None )
607 }
608 _ => false,
609 }
610}
611
612pub(crate) fn render_type_keyword_snippet(
613 ctx: &CompletionContext<'_, '_>,
614 path_ctx: &PathCompletionCtx<'_>,
615 label: &str,
616 snippet: &str,
617) -> Builder {
618 let source_range = ctx.source_range();
619 let mut item =
620 CompletionItem::new(CompletionItemKind::Keyword, source_range, label, ctx.edition);
621
622 let insert_text = if !snippet.contains('$') {
623 item.insert_text(snippet);
624 snippet
625 } else if let Some(cap) = ctx.config.snippet_cap {
626 item.insert_snippet(cap, snippet);
627 snippet
628 } else {
629 label
630 };
631
632 adds_ret_type_arrow(ctx, path_ctx, &mut item, insert_text.to_owned());
633 item
634}
635
636fn adds_ret_type_arrow(
637 ctx: &CompletionContext<'_, '_>,
638 path_ctx: &PathCompletionCtx<'_>,
639 item: &mut Builder,
640 insert_text: String,
641) {
642 if let Some((arrow, at)) = path_ctx.required_thin_arrow() {
643 let mut edit = TextEdit::builder();
644
645 edit.insert(at, arrow.to_owned());
646 edit.replace(ctx.source_range(), insert_text);
647
648 item.text_edit(edit.finish()).adds_text(SmolStr::new_static(arrow));
649 } else {
650 item.insert_text(insert_text);
651 }
652}
653
654fn match_types(
656 ctx: &CompletionContext<'_, '_>,
657 ty1: &hir::Type<'_>,
658 ty2: &hir::Type<'_>,
659) -> Option<CompletionRelevanceTypeMatch> {
660 if ty1 == ty2 {
661 Some(CompletionRelevanceTypeMatch::Exact)
662 } else if ty1.could_unify_with(ctx.db, ty2) {
663 Some(CompletionRelevanceTypeMatch::CouldUnify)
664 } else {
665 None
666 }
667}
668
669fn compute_type_match(
670 ctx: &CompletionContext<'_, '_>,
671 completion_ty: &hir::Type<'_>,
672) -> Option<CompletionRelevanceTypeMatch> {
673 let expected_type = ctx.expected_type.as_ref()?;
674
675 if expected_type.is_unit() {
678 return None;
679 }
680
681 if completion_ty.is_mutable_reference()
683 && let Some(expected_type) = expected_type.remove_ref()
684 && let Some(completion_ty) = completion_ty.remove_ref()
685 {
686 return match_types(ctx, &expected_type, &completion_ty);
687 }
688
689 match_types(ctx, expected_type, completion_ty)
690}
691
692fn compute_has_local_inherent_impl(
693 db: &RootDatabase,
694 path_ctx: &PathCompletionCtx<'_>,
695 completion_ty: &hir::Type<'_>,
696 curr_module: hir::Module,
697) -> bool {
698 matches!(path_ctx.kind, PathKind::Type { location: TypeLocation::ImplTarget })
699 && Impl::all_for_type(db, completion_ty.clone())
700 .iter()
701 .any(|imp| imp.trait_(db).is_none() && imp.module(db) == curr_module)
702}
703
704fn compute_exact_name_match(ctx: &CompletionContext<'_, '_>, completion_name: &str) -> bool {
705 ctx.expected_name.as_ref().is_some_and(|name| name.text() == completion_name)
706}
707
708fn compute_ref_match(
709 ctx: &CompletionContext<'_, '_>,
710 completion_ty: &hir::Type<'_>,
711) -> Option<CompletionItemRefMode> {
712 let expected_type = ctx.expected_type.as_ref()?;
713 let expected_without_ref = expected_type.remove_ref();
714 let completion_without_ref = completion_ty.remove_ref();
715 if expected_type.could_unify_with(ctx.db, completion_ty) {
716 return None;
717 }
718 if let Some(expected_without_ref) = &expected_without_ref
719 && (completion_without_ref.is_none()
720 || completion_ty.could_unify_with(ctx.db, expected_without_ref))
721 && completion_ty
722 .autoderef(ctx.db)
723 .any(|ty| ty.could_unify_with(ctx.db, expected_without_ref))
724 {
725 cov_mark::hit!(suggest_ref);
726 let mutability = if expected_type.is_mutable_reference() {
727 hir::Mutability::Mut
728 } else {
729 hir::Mutability::Shared
730 };
731 return Some(CompletionItemRefMode::Reference(mutability));
732 }
733
734 if let Some(completion_without_ref) = completion_without_ref
735 && completion_without_ref == *expected_type
736 && completion_without_ref.is_copy(ctx.db)
737 {
738 cov_mark::hit!(suggest_deref);
739 return Some(CompletionItemRefMode::Dereference);
740 }
741
742 None
743}
744
745fn path_ref_match(
746 completion: &CompletionContext<'_, '_>,
747 path_ctx: &PathCompletionCtx<'_>,
748 ty: &hir::Type<'_>,
749 item: &mut Builder,
750) {
751 if let Some(original_path) = &path_ctx.original_path {
752 if let Some(original_path) = completion.sema.original_ast_node(original_path.clone())
754 && let Some(ref_mode) = compute_ref_match(completion, ty)
755 {
756 item.ref_match(ref_mode, original_path.syntax().text_range().start());
757 }
758 } else {
759 if let Some(ref_mode) = compute_ref_match(completion, ty) {
763 item.ref_match(ref_mode, completion.source_range().start());
764 }
765 }
766}
767
768#[cfg(test)]
769mod tests {
770 use std::cmp;
771
772 use expect_test::{Expect, expect};
773 use ide_db::SymbolKind;
774 use itertools::Itertools;
775
776 use crate::{
777 CompletionItem, CompletionItemKind, CompletionRelevance, CompletionRelevancePostfixMatch,
778 item::CompletionRelevanceTypeMatch,
779 tests::{TEST_CONFIG, check_edit, do_completion, get_all_items},
780 };
781
782 #[track_caller]
783 fn check(
784 #[rust_analyzer::rust_fixture] ra_fixture: &str,
785 kind: impl Into<CompletionItemKind>,
786 expect: Expect,
787 ) {
788 let actual = do_completion(ra_fixture, kind.into());
789 expect.assert_debug_eq(&actual);
790 }
791
792 #[track_caller]
793 fn check_kinds(
794 #[rust_analyzer::rust_fixture] ra_fixture: &str,
795 kinds: &[CompletionItemKind],
796 expect: Expect,
797 ) {
798 let actual: Vec<_> =
799 kinds.iter().flat_map(|&kind| do_completion(ra_fixture, kind)).collect();
800 expect.assert_debug_eq(&actual);
801 }
802
803 #[track_caller]
804 fn check_function_relevance(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
805 let actual: Vec<_> =
806 do_completion(ra_fixture, CompletionItemKind::SymbolKind(SymbolKind::Method))
807 .into_iter()
808 .map(|item| (item.detail.unwrap_or_default(), item.relevance.function))
809 .collect();
810
811 expect.assert_debug_eq(&actual);
812 }
813
814 #[track_caller]
815 fn check_relevance_for_kinds(
816 #[rust_analyzer::rust_fixture] ra_fixture: &str,
817 kinds: &[CompletionItemKind],
818 expect: Expect,
819 ) {
820 let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
821 actual.retain(|it| kinds.contains(&it.kind));
822 actual.sort_by_key(|it| (cmp::Reverse(it.relevance.score()), it.label.primary.clone()));
823 check_relevance_(actual, expect);
824 }
825
826 #[track_caller]
827 fn check_relevance(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
828 let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
829 actual.retain(|it| it.kind != CompletionItemKind::Snippet);
830 actual.retain(|it| it.kind != CompletionItemKind::Keyword);
831 actual.retain(|it| it.kind != CompletionItemKind::BuiltinType);
832 actual.sort_by_key(|it| (cmp::Reverse(it.relevance.score()), it.label.primary.clone()));
833 check_relevance_(actual, expect);
834 }
835
836 #[track_caller]
837 fn check_relevance_(actual: Vec<CompletionItem>, expect: Expect) {
838 let actual = actual
839 .into_iter()
840 .flat_map(|it| {
841 let mut items = vec![];
842
843 let tag = it.kind.tag();
844 let relevance = display_relevance(it.relevance);
845 items.push(format!(
846 "{tag} {} {} {relevance}\n",
847 it.label.primary,
848 it.label.detail_right.as_deref().unwrap_or_default(),
849 ));
850
851 if let Some((label, _indel, relevance)) = it.ref_match() {
852 let relevance = display_relevance(relevance);
853
854 items.push(format!("{tag} {label} {relevance}\n"));
855 }
856
857 items
858 })
859 .collect::<String>();
860
861 expect.assert_eq(&actual);
862
863 fn display_relevance(relevance: CompletionRelevance) -> String {
864 let CompletionRelevance {
865 exact_name_match,
866 type_match,
867 is_local,
868 trait_,
869 is_name_already_imported: _,
870 requires_import,
871 is_private_editable: _,
872 postfix_match,
873 function: _,
874 is_skipping_completion: _,
875 has_local_inherent_impl,
876 is_deprecated,
877 } = relevance;
878 let relevance_factors = [
879 (type_match == Some(CompletionRelevanceTypeMatch::Exact), "type"),
880 (type_match == Some(CompletionRelevanceTypeMatch::CouldUnify), "type_could_unify"),
881 (exact_name_match, "name"),
882 (is_local, "local"),
883 (postfix_match == Some(CompletionRelevancePostfixMatch::Exact), "snippet"),
884 (trait_.is_some_and(|it| it.is_op_method), "op_method"),
885 (requires_import, "requires_import"),
886 (has_local_inherent_impl, "has_local_inherent_impl"),
887 (is_deprecated, "deprecated"),
888 ]
889 .into_iter()
890 .filter_map(|(cond, desc)| cond.then_some(desc))
891 .join("+");
892
893 format!("[{relevance_factors}]")
894 }
895 }
896
897 #[test]
898 fn trait_imported_as_underscore_should_not_appear_auto_import_again() {
899 check_relevance(
902 r#"
903//- /dep.rs crate:dep
904pub trait MyTrait {
905 fn my_method(&self);
906}
907
908//- /main.rs crate:main deps:dep
909use dep::MyTrait as _;
910struct MyStruct;
911impl dep::MyTrait for MyStruct {
912 fn my_method(&self) {}
913}
914fn main() {
915 MyStruct::my_method$0
916}
917"#,
918 expect![[r#"
919 me my_method(…) fn(&self) []
920 "#]],
921 );
922 }
923
924 #[test]
925 fn set_struct_type_completion_info() {
926 check_relevance(
927 r#"
928//- /lib.rs crate:dep
929
930pub mod test_mod_b {
931 pub struct Struct {}
932}
933
934pub mod test_mod_a {
935 pub struct Struct {}
936}
937
938//- /main.rs crate:main deps:dep
939
940fn test(input: dep::test_mod_b::Struct) { }
941
942fn main() {
943 test(Struct$0);
944}
945"#,
946 expect![[r#"
947 st dep::test_mod_b::Struct {…} dep::test_mod_b::Struct { } [type_could_unify]
948 ex dep::test_mod_b::Struct { } [type_could_unify]
949 st Struct Struct [type_could_unify+requires_import]
950 md dep:: []
951 fn main() fn() []
952 fn test(…) fn(Struct) []
953 st Struct Struct [requires_import]
954 "#]],
955 );
956 }
957
958 #[test]
959 fn set_union_type_completion_info() {
960 check_relevance(
961 r#"
962//- /lib.rs crate:dep
963
964pub mod test_mod_b {
965 pub union Union {
966 a: i32,
967 b: i32
968 }
969}
970
971pub mod test_mod_a {
972 pub enum Union {
973 a: i32,
974 b: i32
975 }
976}
977
978//- /main.rs crate:main deps:dep
979
980fn test(input: dep::test_mod_b::Union) { }
981
982fn main() {
983 test(Union$0);
984}
985"#,
986 expect![[r#"
987 un Union Union [type_could_unify+requires_import]
988 md dep:: []
989 fn main() fn() []
990 fn test(…) fn(Union) []
991 en Union Union [requires_import]
992 "#]],
993 );
994 }
995
996 #[test]
997 fn set_enum_type_completion_info() {
998 check_relevance(
999 r#"
1000//- /lib.rs crate:dep
1001
1002pub mod test_mod_b {
1003 pub enum Enum {
1004 variant
1005 }
1006}
1007
1008pub mod test_mod_a {
1009 pub enum Enum {
1010 variant
1011 }
1012}
1013
1014//- /main.rs crate:main deps:dep
1015
1016fn test(input: dep::test_mod_b::Enum) { }
1017
1018fn main() {
1019 test(Enum$0);
1020}
1021"#,
1022 expect![[r#"
1023 ev dep::test_mod_b::Enum::variant dep::test_mod_b::Enum::variant [type_could_unify]
1024 ex dep::test_mod_b::Enum::variant [type_could_unify]
1025 en Enum Enum [type_could_unify+requires_import]
1026 md dep:: []
1027 fn main() fn() []
1028 fn test(…) fn(Enum) []
1029 en Enum Enum [requires_import]
1030 "#]],
1031 );
1032 }
1033
1034 #[test]
1035 fn set_enum_variant_type_completion_info() {
1036 check_relevance(
1037 r#"
1038//- /lib.rs crate:dep
1039
1040pub mod test_mod_b {
1041 pub enum Enum {
1042 Variant
1043 }
1044}
1045
1046pub mod test_mod_a {
1047 pub enum Enum {
1048 Variant
1049 }
1050}
1051
1052//- /main.rs crate:main deps:dep
1053
1054fn test(input: dep::test_mod_b::Enum) { }
1055
1056fn main() {
1057 test(Variant$0);
1058}
1059"#,
1060 expect![[r#"
1061 ev dep::test_mod_b::Enum::Variant dep::test_mod_b::Enum::Variant [type_could_unify]
1062 ex dep::test_mod_b::Enum::Variant [type_could_unify]
1063 md dep:: []
1064 fn main() fn() []
1065 fn test(…) fn(Enum) []
1066 "#]],
1067 );
1068 }
1069
1070 #[test]
1071 fn set_fn_type_completion_info() {
1072 check_relevance(
1073 r#"
1074//- /lib.rs crate:dep
1075
1076pub mod test_mod_b {
1077 pub fn function(j: isize) -> i32 {}
1078}
1079
1080pub mod test_mod_a {
1081 pub fn function(i: usize) -> i32 {}
1082}
1083
1084//- /main.rs crate:main deps:dep
1085
1086fn test(input: fn(usize) -> i32) { }
1087
1088fn main() {
1089 test(function$0);
1090}
1091"#,
1092 expect![[r#"
1093 md dep:: []
1094 fn main() fn() []
1095 fn test(…) fn(fn(usize) -> i32) []
1096 fn function fn(usize) -> i32 [requires_import]
1097 fn function(…) fn(isize) -> i32 [requires_import]
1098 "#]],
1099 );
1100 }
1101
1102 #[test]
1103 fn set_const_type_completion_info() {
1104 check_relevance(
1105 r#"
1106//- /lib.rs crate:dep
1107
1108pub mod test_mod_b {
1109 pub const CONST: i32 = 1;
1110}
1111
1112pub mod test_mod_a {
1113 pub const CONST: i64 = 2;
1114}
1115
1116//- /main.rs crate:main deps:dep
1117
1118fn test(input: i32) { }
1119
1120fn main() {
1121 test(CONST$0);
1122}
1123"#,
1124 expect![[r#"
1125 ct CONST i32 [type_could_unify+requires_import]
1126 md dep:: []
1127 fn main() fn() []
1128 fn test(…) fn(i32) []
1129 ct CONST i64 [requires_import]
1130 "#]],
1131 );
1132 }
1133
1134 #[test]
1135 fn set_static_type_completion_info() {
1136 check_relevance(
1137 r#"
1138//- /lib.rs crate:dep
1139
1140pub mod test_mod_b {
1141 pub static STATIC: i32 = 5;
1142}
1143
1144pub mod test_mod_a {
1145 pub static STATIC: i64 = 5;
1146}
1147
1148//- /main.rs crate:main deps:dep
1149
1150fn test(input: i32) { }
1151
1152fn main() {
1153 test(STATIC$0);
1154}
1155"#,
1156 expect![[r#"
1157 sc STATIC i32 [type_could_unify+requires_import]
1158 md dep:: []
1159 fn main() fn() []
1160 fn test(…) fn(i32) []
1161 sc STATIC i64 [requires_import]
1162 "#]],
1163 );
1164 }
1165
1166 #[test]
1167 fn set_self_type_completion_info_with_params() {
1168 check_relevance(
1169 r#"
1170//- /lib.rs crate:dep
1171pub struct Struct;
1172
1173impl Struct {
1174 pub fn Function(&self, input: i32) -> bool {
1175 false
1176 }
1177}
1178
1179
1180//- /main.rs crate:main deps:dep
1181
1182use dep::Struct;
1183
1184
1185fn test(input: fn(&dep::Struct, i32) -> bool) { }
1186
1187fn main() {
1188 test(Struct::Function$0);
1189}
1190
1191"#,
1192 expect![[r#"
1193 me Function fn(&self, i32) -> bool []
1194 "#]],
1195 );
1196 }
1197
1198 #[test]
1199 fn set_self_type_completion_info() {
1200 check_relevance(
1201 r#"
1202//- /main.rs crate:main
1203
1204struct Struct;
1205
1206impl Struct {
1207fn test(&self) {
1208 func(Self$0);
1209 }
1210}
1211
1212fn func(input: Struct) { }
1213
1214"#,
1215 expect![[r#"
1216 st Self Self [type]
1217 st Struct Struct [type]
1218 sp Self Struct [type]
1219 st Struct Struct [type]
1220 ex Struct [type]
1221 lc self &Struct [local]
1222 fn func(…) fn(Struct) []
1223 me self.test() fn(&self) []
1224 "#]],
1225 );
1226 }
1227
1228 #[test]
1229 fn set_builtin_type_completion_info() {
1230 check_relevance(
1231 r#"
1232//- /main.rs crate:main
1233
1234fn test(input: bool) { }
1235 pub Input: bool = false;
1236
1237fn main() {
1238 let input = false;
1239 let inputbad = 3;
1240 test(inp$0);
1241}
1242"#,
1243 expect![[r#"
1244 lc input bool [type+name+local]
1245 ex false [type]
1246 ex input [type]
1247 ex true [type]
1248 lc inputbad i32 [local]
1249 fn main() fn() []
1250 fn test(…) fn(bool) []
1251 "#]],
1252 );
1253 }
1254
1255 #[test]
1256 fn enum_detail_includes_record_fields() {
1257 check(
1258 r#"
1259enum Foo { Foo { x: i32, y: i32 } }
1260
1261fn main() { Foo::Fo$0 }
1262"#,
1263 SymbolKind::Variant,
1264 expect![[r#"
1265 [
1266 CompletionItem {
1267 label: "Foo {…}",
1268 detail_left: None,
1269 detail_right: Some(
1270 "Foo { x: i32, y: i32 }",
1271 ),
1272 source_range: 54..56,
1273 delete: 54..56,
1274 insert: "Foo { x: ${1:()}, y: ${2:()} }$0",
1275 kind: SymbolKind(
1276 Variant,
1277 ),
1278 lookup: "Foo{}",
1279 detail: "Foo { x: i32, y: i32 }",
1280 relevance: CompletionRelevance {
1281 exact_name_match: false,
1282 type_match: None,
1283 is_local: false,
1284 trait_: None,
1285 is_name_already_imported: false,
1286 requires_import: false,
1287 is_private_editable: false,
1288 postfix_match: None,
1289 function: Some(
1290 CompletionRelevanceFn {
1291 has_params: true,
1292 has_self_param: false,
1293 return_type: DirectConstructor,
1294 },
1295 ),
1296 is_skipping_completion: false,
1297 has_local_inherent_impl: false,
1298 is_deprecated: false,
1299 },
1300 trigger_call_info: true,
1301 },
1302 ]
1303 "#]],
1304 );
1305 }
1306
1307 #[test]
1308 fn enum_detail_includes_tuple_fields() {
1309 check(
1310 r#"
1311enum Foo { Foo (i32, i32) }
1312
1313fn main() { Foo::Fo$0 }
1314"#,
1315 SymbolKind::Variant,
1316 expect![[r#"
1317 [
1318 CompletionItem {
1319 label: "Foo(…)",
1320 detail_left: None,
1321 detail_right: Some(
1322 "Foo(i32, i32)",
1323 ),
1324 source_range: 46..48,
1325 delete: 46..48,
1326 insert: "Foo(${1:()}, ${2:()})$0",
1327 kind: SymbolKind(
1328 Variant,
1329 ),
1330 lookup: "Foo()",
1331 detail: "Foo(i32, i32)",
1332 relevance: CompletionRelevance {
1333 exact_name_match: false,
1334 type_match: None,
1335 is_local: false,
1336 trait_: None,
1337 is_name_already_imported: false,
1338 requires_import: false,
1339 is_private_editable: false,
1340 postfix_match: None,
1341 function: Some(
1342 CompletionRelevanceFn {
1343 has_params: true,
1344 has_self_param: false,
1345 return_type: DirectConstructor,
1346 },
1347 ),
1348 is_skipping_completion: false,
1349 has_local_inherent_impl: false,
1350 is_deprecated: false,
1351 },
1352 trigger_call_info: true,
1353 },
1354 ]
1355 "#]],
1356 );
1357 }
1358
1359 #[test]
1360 fn fn_detail_includes_args_and_return_type() {
1361 check(
1362 r#"
1363fn foo<T>(a: u32, b: u32, t: T) -> (u32, T) { (a, t) }
1364
1365fn main() { fo$0 }
1366"#,
1367 SymbolKind::Function,
1368 expect![[r#"
1369 [
1370 CompletionItem {
1371 label: "foo(…)",
1372 detail_left: None,
1373 detail_right: Some(
1374 "fn(u32, u32, T) -> (u32, T)",
1375 ),
1376 source_range: 68..70,
1377 delete: 68..70,
1378 insert: "foo(${1:a}, ${2:b}, ${3:t})$0",
1379 kind: SymbolKind(
1380 Function,
1381 ),
1382 lookup: "foo",
1383 detail: "fn(u32, u32, T) -> (u32, T)",
1384 trigger_call_info: true,
1385 },
1386 CompletionItem {
1387 label: "main()",
1388 detail_left: None,
1389 detail_right: Some(
1390 "fn()",
1391 ),
1392 source_range: 68..70,
1393 delete: 68..70,
1394 insert: "main();$0",
1395 kind: SymbolKind(
1396 Function,
1397 ),
1398 lookup: "main",
1399 detail: "fn()",
1400 },
1401 ]
1402 "#]],
1403 );
1404 }
1405
1406 #[test]
1407 fn fn_detail_includes_variadics() {
1408 check(
1409 r#"
1410unsafe extern "C" fn foo(a: u32, b: u32, ...) {}
1411
1412fn main() { fo$0 }
1413"#,
1414 SymbolKind::Function,
1415 expect![[r#"
1416 [
1417 CompletionItem {
1418 label: "foo(…)",
1419 detail_left: None,
1420 detail_right: Some(
1421 "unsafe fn(u32, u32, ...)",
1422 ),
1423 source_range: 62..64,
1424 delete: 62..64,
1425 insert: "foo(${1:a}, ${2:b});$0",
1426 kind: SymbolKind(
1427 Function,
1428 ),
1429 lookup: "foo",
1430 detail: "unsafe fn(u32, u32, ...)",
1431 trigger_call_info: true,
1432 },
1433 CompletionItem {
1434 label: "main()",
1435 detail_left: None,
1436 detail_right: Some(
1437 "fn()",
1438 ),
1439 source_range: 62..64,
1440 delete: 62..64,
1441 insert: "main();$0",
1442 kind: SymbolKind(
1443 Function,
1444 ),
1445 lookup: "main",
1446 detail: "fn()",
1447 },
1448 ]
1449 "#]],
1450 );
1451 }
1452
1453 #[test]
1454 fn enum_detail_just_name_for_unit() {
1455 check(
1456 r#"
1457enum Foo { Foo }
1458
1459fn main() { Foo::Fo$0 }
1460"#,
1461 SymbolKind::Variant,
1462 expect![[r#"
1463 [
1464 CompletionItem {
1465 label: "Foo",
1466 detail_left: None,
1467 detail_right: Some(
1468 "Foo",
1469 ),
1470 source_range: 35..37,
1471 delete: 35..37,
1472 insert: "Foo$0",
1473 kind: SymbolKind(
1474 Variant,
1475 ),
1476 detail: "Foo",
1477 relevance: CompletionRelevance {
1478 exact_name_match: false,
1479 type_match: None,
1480 is_local: false,
1481 trait_: None,
1482 is_name_already_imported: false,
1483 requires_import: false,
1484 is_private_editable: false,
1485 postfix_match: None,
1486 function: Some(
1487 CompletionRelevanceFn {
1488 has_params: false,
1489 has_self_param: false,
1490 return_type: DirectConstructor,
1491 },
1492 ),
1493 is_skipping_completion: false,
1494 has_local_inherent_impl: false,
1495 is_deprecated: false,
1496 },
1497 trigger_call_info: true,
1498 },
1499 ]
1500 "#]],
1501 );
1502 }
1503
1504 #[test]
1505 fn lookup_enums_by_two_qualifiers() {
1506 check_kinds(
1507 r#"
1508mod m {
1509 pub enum Spam { Foo, Bar(i32) }
1510}
1511fn main() { let _: m::Spam = S$0 }
1512"#,
1513 &[
1514 CompletionItemKind::SymbolKind(SymbolKind::Function),
1515 CompletionItemKind::SymbolKind(SymbolKind::Module),
1516 CompletionItemKind::SymbolKind(SymbolKind::Variant),
1517 ],
1518 expect![[r#"
1519 [
1520 CompletionItem {
1521 label: "main()",
1522 detail_left: None,
1523 detail_right: Some(
1524 "fn()",
1525 ),
1526 source_range: 75..76,
1527 delete: 75..76,
1528 insert: "main();$0",
1529 kind: SymbolKind(
1530 Function,
1531 ),
1532 lookup: "main",
1533 detail: "fn()",
1534 },
1535 CompletionItem {
1536 label: "m::",
1537 detail_left: None,
1538 detail_right: None,
1539 source_range: 75..76,
1540 delete: 75..76,
1541 insert: "m::",
1542 kind: SymbolKind(
1543 Module,
1544 ),
1545 lookup: "m",
1546 },
1547 CompletionItem {
1548 label: "m::Spam::Bar(…)",
1549 detail_left: None,
1550 detail_right: Some(
1551 "m::Spam::Bar(i32)",
1552 ),
1553 source_range: 75..76,
1554 delete: 75..76,
1555 insert: "m::Spam::Bar(${1:()})$0",
1556 kind: SymbolKind(
1557 Variant,
1558 ),
1559 lookup: "Spam::Bar()",
1560 detail: "m::Spam::Bar(i32)",
1561 relevance: CompletionRelevance {
1562 exact_name_match: false,
1563 type_match: Some(
1564 Exact,
1565 ),
1566 is_local: false,
1567 trait_: None,
1568 is_name_already_imported: false,
1569 requires_import: false,
1570 is_private_editable: false,
1571 postfix_match: None,
1572 function: Some(
1573 CompletionRelevanceFn {
1574 has_params: true,
1575 has_self_param: false,
1576 return_type: DirectConstructor,
1577 },
1578 ),
1579 is_skipping_completion: false,
1580 has_local_inherent_impl: false,
1581 is_deprecated: false,
1582 },
1583 trigger_call_info: true,
1584 },
1585 CompletionItem {
1586 label: "m::Spam::Foo",
1587 detail_left: None,
1588 detail_right: Some(
1589 "m::Spam::Foo",
1590 ),
1591 source_range: 75..76,
1592 delete: 75..76,
1593 insert: "m::Spam::Foo$0",
1594 kind: SymbolKind(
1595 Variant,
1596 ),
1597 lookup: "Spam::Foo",
1598 detail: "m::Spam::Foo",
1599 relevance: CompletionRelevance {
1600 exact_name_match: false,
1601 type_match: Some(
1602 Exact,
1603 ),
1604 is_local: false,
1605 trait_: None,
1606 is_name_already_imported: false,
1607 requires_import: false,
1608 is_private_editable: false,
1609 postfix_match: None,
1610 function: Some(
1611 CompletionRelevanceFn {
1612 has_params: false,
1613 has_self_param: false,
1614 return_type: DirectConstructor,
1615 },
1616 ),
1617 is_skipping_completion: false,
1618 has_local_inherent_impl: false,
1619 is_deprecated: false,
1620 },
1621 trigger_call_info: true,
1622 },
1623 ]
1624 "#]],
1625 )
1626 }
1627
1628 #[test]
1629 fn sets_deprecated_flag_in_items() {
1630 check(
1631 r#"
1632#[deprecated]
1633mod something_deprecated {}
1634
1635fn main() { som$0 }
1636"#,
1637 SymbolKind::Module,
1638 expect![[r#"
1639 [
1640 CompletionItem {
1641 label: "something_deprecated::",
1642 detail_left: None,
1643 detail_right: None,
1644 source_range: 55..58,
1645 delete: 55..58,
1646 insert: "something_deprecated::",
1647 kind: SymbolKind(
1648 Module,
1649 ),
1650 lookup: "something_deprecated",
1651 deprecated: true,
1652 relevance: CompletionRelevance {
1653 exact_name_match: false,
1654 type_match: None,
1655 is_local: false,
1656 trait_: None,
1657 is_name_already_imported: false,
1658 requires_import: false,
1659 is_private_editable: false,
1660 postfix_match: None,
1661 function: None,
1662 is_skipping_completion: false,
1663 has_local_inherent_impl: false,
1664 is_deprecated: true,
1665 },
1666 },
1667 ]
1668 "#]],
1669 );
1670
1671 check(
1672 r#"
1673#[deprecated]
1674fn something_deprecated() {}
1675
1676fn main() { som$0 }
1677"#,
1678 SymbolKind::Function,
1679 expect![[r#"
1680 [
1681 CompletionItem {
1682 label: "main()",
1683 detail_left: None,
1684 detail_right: Some(
1685 "fn()",
1686 ),
1687 source_range: 56..59,
1688 delete: 56..59,
1689 insert: "main();$0",
1690 kind: SymbolKind(
1691 Function,
1692 ),
1693 lookup: "main",
1694 detail: "fn()",
1695 },
1696 CompletionItem {
1697 label: "something_deprecated()",
1698 detail_left: None,
1699 detail_right: Some(
1700 "fn()",
1701 ),
1702 source_range: 56..59,
1703 delete: 56..59,
1704 insert: "something_deprecated();$0",
1705 kind: SymbolKind(
1706 Function,
1707 ),
1708 lookup: "something_deprecated",
1709 detail: "fn()",
1710 deprecated: true,
1711 relevance: CompletionRelevance {
1712 exact_name_match: false,
1713 type_match: None,
1714 is_local: false,
1715 trait_: None,
1716 is_name_already_imported: false,
1717 requires_import: false,
1718 is_private_editable: false,
1719 postfix_match: None,
1720 function: None,
1721 is_skipping_completion: false,
1722 has_local_inherent_impl: false,
1723 is_deprecated: true,
1724 },
1725 },
1726 ]
1727 "#]],
1728 );
1729
1730 check(
1731 r#"
1732#[deprecated]
1733struct A;
1734
1735fn main() { A$0 }
1736"#,
1737 SymbolKind::Struct,
1738 expect![[r#"
1739 [
1740 CompletionItem {
1741 label: "A",
1742 detail_left: None,
1743 detail_right: Some(
1744 "A",
1745 ),
1746 source_range: 37..38,
1747 delete: 37..38,
1748 insert: "A",
1749 kind: SymbolKind(
1750 Struct,
1751 ),
1752 detail: "A",
1753 deprecated: true,
1754 relevance: CompletionRelevance {
1755 exact_name_match: false,
1756 type_match: None,
1757 is_local: false,
1758 trait_: None,
1759 is_name_already_imported: false,
1760 requires_import: false,
1761 is_private_editable: false,
1762 postfix_match: None,
1763 function: None,
1764 is_skipping_completion: false,
1765 has_local_inherent_impl: false,
1766 is_deprecated: true,
1767 },
1768 },
1769 ]
1770 "#]],
1771 );
1772
1773 check(
1774 r#"
1775#[deprecated]
1776enum A {}
1777
1778fn main() { A$0 }
1779"#,
1780 SymbolKind::Enum,
1781 expect![[r#"
1782 [
1783 CompletionItem {
1784 label: "A",
1785 detail_left: None,
1786 detail_right: Some(
1787 "A",
1788 ),
1789 source_range: 37..38,
1790 delete: 37..38,
1791 insert: "A",
1792 kind: SymbolKind(
1793 Enum,
1794 ),
1795 detail: "A",
1796 deprecated: true,
1797 relevance: CompletionRelevance {
1798 exact_name_match: false,
1799 type_match: None,
1800 is_local: false,
1801 trait_: None,
1802 is_name_already_imported: false,
1803 requires_import: false,
1804 is_private_editable: false,
1805 postfix_match: None,
1806 function: None,
1807 is_skipping_completion: false,
1808 has_local_inherent_impl: false,
1809 is_deprecated: true,
1810 },
1811 },
1812 ]
1813 "#]],
1814 );
1815
1816 check(
1817 r#"
1818enum A {
1819 Okay,
1820 #[deprecated]
1821 Old,
1822}
1823
1824fn main() { A::$0 }
1825"#,
1826 SymbolKind::Variant,
1827 expect![[r#"
1828 [
1829 CompletionItem {
1830 label: "Okay",
1831 detail_left: None,
1832 detail_right: Some(
1833 "Okay",
1834 ),
1835 source_range: 64..64,
1836 delete: 64..64,
1837 insert: "Okay$0",
1838 kind: SymbolKind(
1839 Variant,
1840 ),
1841 detail: "Okay",
1842 relevance: CompletionRelevance {
1843 exact_name_match: false,
1844 type_match: None,
1845 is_local: false,
1846 trait_: None,
1847 is_name_already_imported: false,
1848 requires_import: false,
1849 is_private_editable: false,
1850 postfix_match: None,
1851 function: Some(
1852 CompletionRelevanceFn {
1853 has_params: false,
1854 has_self_param: false,
1855 return_type: DirectConstructor,
1856 },
1857 ),
1858 is_skipping_completion: false,
1859 has_local_inherent_impl: false,
1860 is_deprecated: false,
1861 },
1862 trigger_call_info: true,
1863 },
1864 CompletionItem {
1865 label: "Old",
1866 detail_left: None,
1867 detail_right: Some(
1868 "Old",
1869 ),
1870 source_range: 64..64,
1871 delete: 64..64,
1872 insert: "Old$0",
1873 kind: SymbolKind(
1874 Variant,
1875 ),
1876 detail: "Old",
1877 deprecated: true,
1878 relevance: CompletionRelevance {
1879 exact_name_match: false,
1880 type_match: None,
1881 is_local: false,
1882 trait_: None,
1883 is_name_already_imported: false,
1884 requires_import: false,
1885 is_private_editable: false,
1886 postfix_match: None,
1887 function: Some(
1888 CompletionRelevanceFn {
1889 has_params: false,
1890 has_self_param: false,
1891 return_type: DirectConstructor,
1892 },
1893 ),
1894 is_skipping_completion: false,
1895 has_local_inherent_impl: false,
1896 is_deprecated: true,
1897 },
1898 trigger_call_info: true,
1899 },
1900 ]
1901 "#]],
1902 );
1903
1904 check(
1905 r#"
1906#[deprecated]
1907const A: i32 = 0;
1908
1909fn main() { A$0 }
1910"#,
1911 SymbolKind::Const,
1912 expect![[r#"
1913 [
1914 CompletionItem {
1915 label: "A",
1916 detail_left: None,
1917 detail_right: Some(
1918 "i32",
1919 ),
1920 source_range: 45..46,
1921 delete: 45..46,
1922 insert: "A",
1923 kind: SymbolKind(
1924 Const,
1925 ),
1926 detail: "i32",
1927 deprecated: true,
1928 relevance: CompletionRelevance {
1929 exact_name_match: false,
1930 type_match: None,
1931 is_local: false,
1932 trait_: None,
1933 is_name_already_imported: false,
1934 requires_import: false,
1935 is_private_editable: false,
1936 postfix_match: None,
1937 function: None,
1938 is_skipping_completion: false,
1939 has_local_inherent_impl: false,
1940 is_deprecated: true,
1941 },
1942 },
1943 ]
1944 "#]],
1945 );
1946
1947 check(
1948 r#"
1949#[deprecated]
1950static A: i32 = 0;
1951
1952fn main() { A$0 }
1953"#,
1954 SymbolKind::Static,
1955 expect![[r#"
1956 [
1957 CompletionItem {
1958 label: "A",
1959 detail_left: None,
1960 detail_right: Some(
1961 "i32",
1962 ),
1963 source_range: 46..47,
1964 delete: 46..47,
1965 insert: "A",
1966 kind: SymbolKind(
1967 Static,
1968 ),
1969 detail: "i32",
1970 deprecated: true,
1971 relevance: CompletionRelevance {
1972 exact_name_match: false,
1973 type_match: None,
1974 is_local: false,
1975 trait_: None,
1976 is_name_already_imported: false,
1977 requires_import: false,
1978 is_private_editable: false,
1979 postfix_match: None,
1980 function: None,
1981 is_skipping_completion: false,
1982 has_local_inherent_impl: false,
1983 is_deprecated: true,
1984 },
1985 },
1986 ]
1987 "#]],
1988 );
1989
1990 check(
1991 r#"
1992#[deprecated]
1993trait A {}
1994
1995impl A$0
1996"#,
1997 SymbolKind::Trait,
1998 expect![[r#"
1999 [
2000 CompletionItem {
2001 label: "A",
2002 detail_left: None,
2003 detail_right: None,
2004 source_range: 31..32,
2005 delete: 31..32,
2006 insert: "A",
2007 kind: SymbolKind(
2008 Trait,
2009 ),
2010 deprecated: true,
2011 relevance: CompletionRelevance {
2012 exact_name_match: false,
2013 type_match: None,
2014 is_local: false,
2015 trait_: None,
2016 is_name_already_imported: false,
2017 requires_import: false,
2018 is_private_editable: false,
2019 postfix_match: None,
2020 function: None,
2021 is_skipping_completion: false,
2022 has_local_inherent_impl: false,
2023 is_deprecated: true,
2024 },
2025 },
2026 ]
2027 "#]],
2028 );
2029
2030 check(
2031 r#"
2032#[deprecated]
2033type A = i32;
2034
2035fn main() { A$0 }
2036"#,
2037 SymbolKind::TypeAlias,
2038 expect![[r#"
2039 [
2040 CompletionItem {
2041 label: "A",
2042 detail_left: None,
2043 detail_right: None,
2044 source_range: 41..42,
2045 delete: 41..42,
2046 insert: "A",
2047 kind: SymbolKind(
2048 TypeAlias,
2049 ),
2050 deprecated: true,
2051 relevance: CompletionRelevance {
2052 exact_name_match: false,
2053 type_match: None,
2054 is_local: false,
2055 trait_: None,
2056 is_name_already_imported: false,
2057 requires_import: false,
2058 is_private_editable: false,
2059 postfix_match: None,
2060 function: None,
2061 is_skipping_completion: false,
2062 has_local_inherent_impl: false,
2063 is_deprecated: true,
2064 },
2065 },
2066 ]
2067 "#]],
2068 );
2069
2070 check(
2071 r#"
2072#[deprecated]
2073macro_rules! a { _ => {}}
2074
2075fn main() { a$0 }
2076"#,
2077 SymbolKind::Macro,
2078 expect![[r#"
2079 [
2080 CompletionItem {
2081 label: "a!(…)",
2082 detail_left: None,
2083 detail_right: Some(
2084 "macro_rules! a",
2085 ),
2086 source_range: 53..54,
2087 delete: 53..54,
2088 insert: "a!($0)",
2089 kind: SymbolKind(
2090 Macro,
2091 ),
2092 lookup: "a!",
2093 detail: "macro_rules! a",
2094 deprecated: true,
2095 relevance: CompletionRelevance {
2096 exact_name_match: false,
2097 type_match: None,
2098 is_local: false,
2099 trait_: None,
2100 is_name_already_imported: false,
2101 requires_import: false,
2102 is_private_editable: false,
2103 postfix_match: None,
2104 function: None,
2105 is_skipping_completion: false,
2106 has_local_inherent_impl: false,
2107 is_deprecated: true,
2108 },
2109 },
2110 ]
2111 "#]],
2112 );
2113
2114 check(
2115 r#"
2116struct A { #[deprecated] the_field: u32 }
2117
2118fn main() { A { the$0 } }
2119"#,
2120 SymbolKind::Field,
2121 expect![[r#"
2122 [
2123 CompletionItem {
2124 label: "the_field",
2125 detail_left: None,
2126 detail_right: Some(
2127 "u32",
2128 ),
2129 source_range: 59..62,
2130 delete: 59..62,
2131 insert: "the_field",
2132 kind: SymbolKind(
2133 Field,
2134 ),
2135 detail: "u32",
2136 deprecated: true,
2137 relevance: CompletionRelevance {
2138 exact_name_match: false,
2139 type_match: Some(
2140 CouldUnify,
2141 ),
2142 is_local: false,
2143 trait_: None,
2144 is_name_already_imported: false,
2145 requires_import: false,
2146 is_private_editable: false,
2147 postfix_match: None,
2148 function: None,
2149 is_skipping_completion: false,
2150 has_local_inherent_impl: false,
2151 is_deprecated: true,
2152 },
2153 },
2154 ]
2155 "#]],
2156 );
2157 }
2158
2159 #[test]
2160 fn renders_docs() {
2161 check_kinds(
2162 r#"
2163struct S {
2164 /// Field docs
2165 foo:
2166}
2167impl S {
2168 /// Method docs
2169 fn bar(self) { self.$0 }
2170}"#,
2171 &[
2172 CompletionItemKind::SymbolKind(SymbolKind::Method),
2173 CompletionItemKind::SymbolKind(SymbolKind::Field),
2174 ],
2175 expect![[r#"
2176 [
2177 CompletionItem {
2178 label: "bar()",
2179 detail_left: None,
2180 detail_right: Some(
2181 "fn(self)",
2182 ),
2183 source_range: 94..94,
2184 delete: 94..94,
2185 insert: "bar();$0",
2186 kind: SymbolKind(
2187 Method,
2188 ),
2189 lookup: "bar",
2190 detail: "fn(self)",
2191 documentation: Documentation(
2192 "Method docs",
2193 ),
2194 relevance: CompletionRelevance {
2195 exact_name_match: false,
2196 type_match: None,
2197 is_local: false,
2198 trait_: None,
2199 is_name_already_imported: false,
2200 requires_import: false,
2201 is_private_editable: false,
2202 postfix_match: None,
2203 function: Some(
2204 CompletionRelevanceFn {
2205 has_params: true,
2206 has_self_param: true,
2207 return_type: Other,
2208 },
2209 ),
2210 is_skipping_completion: false,
2211 has_local_inherent_impl: false,
2212 is_deprecated: false,
2213 },
2214 },
2215 CompletionItem {
2216 label: "foo",
2217 detail_left: None,
2218 detail_right: Some(
2219 "{unknown}",
2220 ),
2221 source_range: 94..94,
2222 delete: 94..94,
2223 insert: "foo",
2224 kind: SymbolKind(
2225 Field,
2226 ),
2227 detail: "{unknown}",
2228 documentation: Documentation(
2229 "Field docs",
2230 ),
2231 },
2232 ]
2233 "#]],
2234 );
2235
2236 check_kinds(
2237 r#"
2238use self::my$0;
2239
2240/// mod docs
2241mod my { }
2242
2243/// enum docs
2244enum E {
2245 /// variant docs
2246 V
2247}
2248use self::E::*;
2249"#,
2250 &[
2251 CompletionItemKind::SymbolKind(SymbolKind::Module),
2252 CompletionItemKind::SymbolKind(SymbolKind::Variant),
2253 CompletionItemKind::SymbolKind(SymbolKind::Enum),
2254 ],
2255 expect![[r#"
2256 [
2257 CompletionItem {
2258 label: "my",
2259 detail_left: None,
2260 detail_right: None,
2261 source_range: 10..12,
2262 delete: 10..12,
2263 insert: "my",
2264 kind: SymbolKind(
2265 Module,
2266 ),
2267 documentation: Documentation(
2268 "mod docs",
2269 ),
2270 },
2271 CompletionItem {
2272 label: "V",
2273 detail_left: None,
2274 detail_right: Some(
2275 "V",
2276 ),
2277 source_range: 10..12,
2278 delete: 10..12,
2279 insert: "V$0",
2280 kind: SymbolKind(
2281 Variant,
2282 ),
2283 detail: "V",
2284 documentation: Documentation(
2285 "variant docs",
2286 ),
2287 relevance: CompletionRelevance {
2288 exact_name_match: false,
2289 type_match: None,
2290 is_local: false,
2291 trait_: None,
2292 is_name_already_imported: false,
2293 requires_import: false,
2294 is_private_editable: false,
2295 postfix_match: None,
2296 function: Some(
2297 CompletionRelevanceFn {
2298 has_params: false,
2299 has_self_param: false,
2300 return_type: DirectConstructor,
2301 },
2302 ),
2303 is_skipping_completion: false,
2304 has_local_inherent_impl: false,
2305 is_deprecated: false,
2306 },
2307 trigger_call_info: true,
2308 },
2309 CompletionItem {
2310 label: "E",
2311 detail_left: None,
2312 detail_right: Some(
2313 "E",
2314 ),
2315 source_range: 10..12,
2316 delete: 10..12,
2317 insert: "E",
2318 kind: SymbolKind(
2319 Enum,
2320 ),
2321 detail: "E",
2322 documentation: Documentation(
2323 "enum docs",
2324 ),
2325 },
2326 ]
2327 "#]],
2328 )
2329 }
2330
2331 #[test]
2332 fn dont_render_attrs() {
2333 check(
2334 r#"
2335struct S;
2336impl S {
2337 #[inline]
2338 fn the_method(&self) { }
2339}
2340fn foo(s: S) { s.$0 }
2341"#,
2342 CompletionItemKind::SymbolKind(SymbolKind::Method),
2343 expect![[r#"
2344 [
2345 CompletionItem {
2346 label: "the_method()",
2347 detail_left: None,
2348 detail_right: Some(
2349 "fn(&self)",
2350 ),
2351 source_range: 81..81,
2352 delete: 81..81,
2353 insert: "the_method();$0",
2354 kind: SymbolKind(
2355 Method,
2356 ),
2357 lookup: "the_method",
2358 detail: "fn(&self)",
2359 relevance: CompletionRelevance {
2360 exact_name_match: false,
2361 type_match: None,
2362 is_local: false,
2363 trait_: None,
2364 is_name_already_imported: false,
2365 requires_import: false,
2366 is_private_editable: false,
2367 postfix_match: None,
2368 function: Some(
2369 CompletionRelevanceFn {
2370 has_params: true,
2371 has_self_param: true,
2372 return_type: Other,
2373 },
2374 ),
2375 is_skipping_completion: false,
2376 has_local_inherent_impl: false,
2377 is_deprecated: false,
2378 },
2379 },
2380 ]
2381 "#]],
2382 )
2383 }
2384
2385 #[test]
2386 fn no_call_parens_if_fn_ptr_needed() {
2387 cov_mark::check!(no_call_parens_if_fn_ptr_needed);
2388 check_edit(
2389 "foo",
2390 r#"
2391fn foo(foo: u8, bar: u8) {}
2392struct ManualVtable { f: fn(u8, u8) }
2393
2394fn main() -> ManualVtable {
2395 ManualVtable { f: f$0 }
2396}
2397"#,
2398 r#"
2399fn foo(foo: u8, bar: u8) {}
2400struct ManualVtable { f: fn(u8, u8) }
2401
2402fn main() -> ManualVtable {
2403 ManualVtable { f: foo }
2404}
2405"#,
2406 );
2407 check_edit(
2408 "type",
2409 r#"
2410struct RawIdentTable { r#type: u32 }
2411
2412fn main() -> RawIdentTable {
2413 RawIdentTable { t$0: 42 }
2414}
2415"#,
2416 r#"
2417struct RawIdentTable { r#type: u32 }
2418
2419fn main() -> RawIdentTable {
2420 RawIdentTable { r#type: 42 }
2421}
2422"#,
2423 );
2424 }
2425
2426 #[test]
2427 fn no_parens_in_use_item() {
2428 check_edit(
2429 "foo",
2430 r#"
2431mod m { pub fn foo() {} }
2432use crate::m::f$0;
2433"#,
2434 r#"
2435mod m { pub fn foo() {} }
2436use crate::m::foo;
2437"#,
2438 );
2439 }
2440
2441 #[test]
2442 fn no_parens_in_call() {
2443 check_edit(
2444 "foo",
2445 r#"
2446fn foo(x: i32) {}
2447fn main() { f$0(); }
2448"#,
2449 r#"
2450fn foo(x: i32) {}
2451fn main() { foo(); }
2452"#,
2453 );
2454 check_edit(
2455 "foo",
2456 r#"
2457struct Foo;
2458impl Foo { fn foo(&self){} }
2459fn f(foo: &Foo) { foo.f$0(); }
2460"#,
2461 r#"
2462struct Foo;
2463impl Foo { fn foo(&self){} }
2464fn f(foo: &Foo) { foo.foo(); }
2465"#,
2466 );
2467 }
2468
2469 #[test]
2470 fn inserts_angle_brackets_for_generics() {
2471 cov_mark::check!(inserts_angle_brackets_for_generics);
2472 check_edit(
2473 "Vec",
2474 r#"
2475struct Vec<T> {}
2476fn foo(xs: Ve$0)
2477"#,
2478 r#"
2479struct Vec<T> {}
2480fn foo(xs: Vec<$0>)
2481"#,
2482 );
2483 check_edit(
2484 "Vec",
2485 r#"
2486type Vec<T> = (T,);
2487fn foo(xs: Ve$0)
2488"#,
2489 r#"
2490type Vec<T> = (T,);
2491fn foo(xs: Vec<$0>)
2492"#,
2493 );
2494 check_edit(
2495 "Vec",
2496 r#"
2497struct Vec<T = i128> {}
2498fn foo(xs: Ve$0)
2499"#,
2500 r#"
2501struct Vec<T = i128> {}
2502fn foo(xs: Vec)
2503"#,
2504 );
2505 check_edit(
2506 "Vec",
2507 r#"
2508struct Vec<T> {}
2509fn foo(xs: Ve$0<i128>)
2510"#,
2511 r#"
2512struct Vec<T> {}
2513fn foo(xs: Vec<i128>)
2514"#,
2515 );
2516 }
2517
2518 #[test]
2519 fn active_param_relevance() {
2520 check_relevance(
2521 r#"
2522struct S { foo: i64, bar: u32, baz: u32 }
2523fn test(bar: u32) { }
2524fn foo(s: S) { test(s.$0) }
2525"#,
2526 expect![[r#"
2527 fd bar u32 [type+name]
2528 fd baz u32 [type]
2529 fd foo i64 []
2530 "#]],
2531 );
2532 }
2533
2534 #[test]
2535 fn record_field_relevances() {
2536 check_relevance(
2537 r#"
2538struct A { foo: i64, bar: u32, baz: u32 }
2539struct B { x: (), y: f32, bar: u32 }
2540fn foo(a: A) { B { bar: a.$0 }; }
2541"#,
2542 expect![[r#"
2543 fd bar u32 [type+name]
2544 fd baz u32 [type]
2545 fd foo i64 []
2546 "#]],
2547 )
2548 }
2549
2550 #[test]
2551 fn tuple_field_detail() {
2552 check(
2553 r#"
2554struct S(i32);
2555
2556fn f() -> i32 {
2557 let s = S(0);
2558 s.0$0
2559}
2560"#,
2561 SymbolKind::Field,
2562 expect![[r#"
2563 [
2564 CompletionItem {
2565 label: "0",
2566 detail_left: None,
2567 detail_right: Some(
2568 "i32",
2569 ),
2570 source_range: 56..57,
2571 delete: 56..57,
2572 insert: "0",
2573 kind: SymbolKind(
2574 Field,
2575 ),
2576 detail: "i32",
2577 relevance: CompletionRelevance {
2578 exact_name_match: false,
2579 type_match: Some(
2580 Exact,
2581 ),
2582 is_local: false,
2583 trait_: None,
2584 is_name_already_imported: false,
2585 requires_import: false,
2586 is_private_editable: false,
2587 postfix_match: None,
2588 function: None,
2589 is_skipping_completion: false,
2590 has_local_inherent_impl: false,
2591 is_deprecated: false,
2592 },
2593 },
2594 ]
2595 "#]],
2596 );
2597 }
2598
2599 #[test]
2600 fn record_field_and_call_relevances() {
2601 check_relevance(
2602 r#"
2603struct A { foo: i64, bar: u32, baz: u32 }
2604struct B { x: (), y: f32, bar: u32 }
2605fn f(foo: i64) { }
2606fn foo(a: A) { B { bar: f(a.$0) }; }
2607"#,
2608 expect![[r#"
2609 fd foo i64 [type+name]
2610 fd bar u32 []
2611 fd baz u32 []
2612 "#]],
2613 );
2614 check_relevance(
2615 r#"
2616struct A { foo: i64, bar: u32, baz: u32 }
2617struct B { x: (), y: f32, bar: u32 }
2618fn f(foo: i64) { }
2619fn foo(a: A) { f(B { bar: a.$0 }); }
2620"#,
2621 expect![[r#"
2622 fd bar u32 [type+name]
2623 fd baz u32 [type]
2624 fd foo i64 []
2625 "#]],
2626 );
2627 }
2628
2629 #[test]
2630 fn prioritize_exact_ref_match() {
2631 check_relevance(
2632 r#"
2633struct WorldSnapshot { _f: () };
2634fn go(world: &WorldSnapshot) { go(w$0) }
2635"#,
2636 expect![[r#"
2637 lc world &WorldSnapshot [type+name+local]
2638 ex world [type]
2639 st WorldSnapshot {…} WorldSnapshot { _f: () } []
2640 st &WorldSnapshot {…} [type]
2641 st WorldSnapshot WorldSnapshot []
2642 st &WorldSnapshot [type]
2643 fn go(…) fn(&WorldSnapshot) []
2644 "#]],
2645 );
2646 }
2647
2648 #[test]
2649 fn prioritize_mutable_ref_as_immutable_ref_match() {
2650 check_relevance(
2651 r#"fn foo(r: &mut i32) -> &i32 { $0 }"#,
2652 expect![[r#"
2653 lc r &mut i32 [type+local]
2654 fn foo(…) fn(&mut i32) -> &i32 [type]
2655 "#]],
2656 );
2657 }
2658
2659 #[test]
2660 fn complete_ref_match_after_keyword_prefix() {
2661 check_kinds(
2663 r#"
2664fn foo(data: &i32) {}
2665fn main() {
2666 let indent = 2i32;
2667 foo(in$0)
2668}
2669"#,
2670 &[CompletionItemKind::SymbolKind(SymbolKind::Local)],
2671 expect![[r#"
2672 [
2673 CompletionItem {
2674 label: "indent",
2675 detail_left: None,
2676 detail_right: Some(
2677 "i32",
2678 ),
2679 source_range: 65..67,
2680 delete: 65..67,
2681 insert: "indent",
2682 kind: SymbolKind(
2683 Local,
2684 ),
2685 detail: "i32",
2686 relevance: CompletionRelevance {
2687 exact_name_match: false,
2688 type_match: None,
2689 is_local: true,
2690 trait_: None,
2691 is_name_already_imported: false,
2692 requires_import: false,
2693 is_private_editable: false,
2694 postfix_match: None,
2695 function: None,
2696 is_skipping_completion: false,
2697 has_local_inherent_impl: false,
2698 is_deprecated: false,
2699 },
2700 ref_match: "&@65",
2701 },
2702 ]
2703 "#]],
2704 );
2705 }
2706
2707 #[test]
2708 fn too_many_arguments() {
2709 cov_mark::check!(too_many_arguments);
2710 check_relevance(
2711 r#"
2712struct Foo;
2713fn f(foo: &Foo) { f(foo, w$0) }
2714"#,
2715 expect![[r#"
2716 lc foo &Foo [local]
2717 st Foo Foo []
2718 fn f(…) fn(&Foo) []
2719 "#]],
2720 );
2721 }
2722
2723 #[test]
2724 fn score_fn_type_and_name_match() {
2725 check_relevance(
2726 r#"
2727struct A { bar: u8 }
2728fn baz() -> u8 { 0 }
2729fn bar() -> u8 { 0 }
2730fn f() { A { bar: b$0 }; }
2731"#,
2732 expect![[r#"
2733 fn bar() fn() -> u8 [type+name]
2734 ex bar() [type]
2735 fn baz() fn() -> u8 [type]
2736 ex baz() [type]
2737 st A A []
2738 fn f() fn() []
2739 "#]],
2740 );
2741 }
2742
2743 #[test]
2744 fn score_method_type_and_name_match() {
2745 check_relevance(
2746 r#"
2747fn baz(aaa: u32){}
2748struct Foo;
2749impl Foo {
2750fn aaa(&self) -> u32 { 0 }
2751fn bbb(&self) -> u32 { 0 }
2752fn ccc(&self) -> u64 { 0 }
2753}
2754fn f() {
2755 baz(Foo.$0
2756}
2757"#,
2758 expect![[r#"
2759 me aaa() fn(&self) -> u32 [type+name]
2760 me bbb() fn(&self) -> u32 [type]
2761 me ccc() fn(&self) -> u64 []
2762 "#]],
2763 );
2764 }
2765
2766 #[test]
2767 fn score_method_name_match_only() {
2768 check_relevance(
2769 r#"
2770fn baz(aaa: u32){}
2771struct Foo;
2772impl Foo {
2773fn aaa(&self) -> u64 { 0 }
2774}
2775fn f() {
2776 baz(Foo.$0
2777}
2778"#,
2779 expect![[r#"
2780 me aaa() fn(&self) -> u64 [name]
2781 "#]],
2782 );
2783 }
2784
2785 #[test]
2786 fn score_has_local_inherent_impl() {
2787 check_relevance(
2788 r#"
2789trait Foob {}
2790struct Fooa {}
2791impl Fooa {}
2792
2793impl Foo$0
2794"#,
2795 expect![[r#"
2796 tt Foob []
2797 st Fooa Fooa [has_local_inherent_impl]
2798 "#]],
2799 );
2800
2801 check_relevance(
2803 r#"
2804trait Foob {}
2805struct Fooa {}
2806
2807mod a {
2808 use super::*;
2809 impl Fooa {}
2810}
2811
2812mod b {
2813 use super::*;
2814 impl Foo$0
2815}
2816
2817"#,
2818 expect![[r#"
2819 st Fooa Fooa []
2820 tt Foob []
2821 md a:: []
2822 md b:: []
2823 "#]],
2824 );
2825 }
2826
2827 #[test]
2828 fn test_avoid_redundant_suggestion() {
2829 check_relevance(
2830 r#"
2831struct aa([u8]);
2832
2833impl aa {
2834 fn from_bytes(bytes: &[u8]) -> &Self {
2835 unsafe { &*(bytes as *const [u8] as *const aa) }
2836 }
2837}
2838
2839fn bb()-> &'static aa {
2840 let bytes = b"hello";
2841 aa::$0
2842}
2843"#,
2844 expect![[r#"
2845 fn from_bytes(…) fn(&[u8]) -> &aa [type_could_unify]
2846 "#]],
2847 );
2848 }
2849
2850 #[test]
2851 fn suggest_ref_mut() {
2852 cov_mark::check!(suggest_ref);
2853 check_relevance(
2854 r#"
2855struct S;
2856fn foo(s: &mut S) {}
2857fn main() {
2858 let mut s = S;
2859 foo($0);
2860}
2861 "#,
2862 expect![[r#"
2863 lc s S [name+local]
2864 lc &mut s [type+name+local]
2865 st S S []
2866 st &mut S [type]
2867 st S S []
2868 st &mut S [type]
2869 fn foo(…) fn(&mut S) []
2870 fn main() fn() []
2871 "#]],
2872 );
2873 check_relevance(
2874 r#"
2875struct S;
2876fn foo(s: &mut S) {}
2877fn main() {
2878 let mut s = S;
2879 foo(&mut $0);
2880}
2881 "#,
2882 expect![[r#"
2883 lc s S [type+name+local]
2884 st S S [type]
2885 st S S [type]
2886 ex S [type]
2887 ex s [type]
2888 fn foo(…) fn(&mut S) []
2889 fn main() fn() []
2890 "#]],
2891 );
2892 check_relevance(
2893 r#"
2894struct S;
2895fn foo(s: &mut S) {}
2896fn main() {
2897 let mut ssss = S;
2898 foo(&mut s$0);
2899}
2900 "#,
2901 expect![[r#"
2902 st S S [type]
2903 lc ssss S [type+local]
2904 st S S [type]
2905 ex S [type]
2906 ex ssss [type]
2907 fn foo(…) fn(&mut S) []
2908 fn main() fn() []
2909 "#]],
2910 );
2911 check_relevance(
2912 r#"
2913struct S;
2914fn foo(s: &&S) {}
2915fn main() {
2916 let mut ssss = &S;
2917 foo($0);
2918}
2919 "#,
2920 expect![[r#"
2921 st S S []
2922 lc ssss &S [local]
2923 lc &ssss [type+local]
2924 st S S []
2925 fn foo(…) fn(&&S) []
2926 fn main() fn() []
2927 "#]],
2928 );
2929 check_relevance(
2930 r#"
2931struct S<T>(T);
2932fn foo<T>(s: &mut S<T>) {}
2933fn main() {
2934 let mut ssss = S(2u32);
2935 foo($0);
2936}
2937 "#,
2938 expect![[r#"
2939 st S(…) S(T) []
2940 st &mut S(…) [type]
2941 lc ssss S<u32> [local]
2942 lc &mut ssss [type+local]
2943 st S S<{unknown}> []
2944 st &mut S [type]
2945 fn foo(…) fn(&mut S<T>) []
2946 fn main() fn() []
2947 "#]],
2948 );
2949 }
2950
2951 #[test]
2952 fn suggest_deref_copy() {
2953 cov_mark::check!(suggest_deref);
2954 check_relevance(
2955 r#"
2956//- minicore: copy
2957struct Foo;
2958
2959impl Copy for Foo {}
2960impl Clone for Foo {
2961 fn clone(&self) -> Self { *self }
2962}
2963
2964fn bar(x: Foo) {}
2965
2966fn main() {
2967 let foo = &Foo;
2968 bar($0);
2969}
2970"#,
2971 expect![[r#"
2972 st Foo Foo [type]
2973 st Foo Foo [type]
2974 ex Foo [type]
2975 lc foo &Foo [local]
2976 lc *foo [type+local]
2977 tt Clone []
2978 tt Copy []
2979 fn bar(…) fn(Foo) []
2980 md core:: []
2981 fn main() fn() []
2982 "#]],
2983 );
2984 }
2985
2986 #[test]
2987 fn suggest_deref_trait() {
2988 check_relevance(
2989 r#"
2990//- minicore: deref
2991struct S;
2992struct T(S);
2993
2994impl core::ops::Deref for T {
2995 type Target = S;
2996
2997 fn deref(&self) -> &Self::Target {
2998 &self.0
2999 }
3000}
3001
3002fn foo(s: &S) {}
3003
3004fn main() {
3005 let t = T(S);
3006 let m = 123;
3007
3008 foo($0);
3009}
3010 "#,
3011 expect![[r#"
3012 st S S []
3013 st &S [type]
3014 ex core::ops::Deref::deref(&t) [type_could_unify]
3015 lc m i32 [local]
3016 lc t T [local]
3017 lc &t [type+local]
3018 st S S []
3019 st &S [type]
3020 st T T []
3021 st &T [type]
3022 md core:: []
3023 fn foo(…) fn(&S) []
3024 fn main() fn() []
3025 "#]],
3026 )
3027 }
3028
3029 #[test]
3030 fn suggest_deref_mut() {
3031 check_relevance(
3032 r#"
3033//- minicore: deref_mut
3034struct S;
3035struct T(S);
3036
3037impl core::ops::Deref for T {
3038 type Target = S;
3039
3040 fn deref(&self) -> &Self::Target {
3041 &self.0
3042 }
3043}
3044
3045impl core::ops::DerefMut for T {
3046 fn deref_mut(&mut self) -> &mut Self::Target {
3047 &mut self.0
3048 }
3049}
3050
3051fn foo(s: &mut S) {}
3052
3053fn main() {
3054 let t = T(S);
3055 let m = 123;
3056
3057 foo($0);
3058}
3059 "#,
3060 expect![[r#"
3061 st S S []
3062 st &mut S [type]
3063 ex core::ops::DerefMut::deref_mut(&mut t) [type_could_unify]
3064 lc m i32 [local]
3065 lc t T [local]
3066 lc &mut t [type+local]
3067 st S S []
3068 st &mut S [type]
3069 st T T []
3070 st &mut T [type]
3071 md core:: []
3072 fn foo(…) fn(&mut S) []
3073 fn main() fn() []
3074 "#]],
3075 )
3076 }
3077
3078 #[test]
3079 fn locals() {
3080 check_relevance(
3081 r#"
3082fn foo(bar: u32) {
3083 let baz = 0;
3084
3085 f$0
3086}
3087"#,
3088 expect![[r#"
3089 lc bar u32 [local]
3090 lc baz i32 [local]
3091 fn foo(…) fn(u32) []
3092 "#]],
3093 );
3094 }
3095
3096 #[test]
3097 fn enum_owned() {
3098 check_relevance(
3099 r#"
3100enum Foo { A, B }
3101fn foo() {
3102 bar($0);
3103}
3104fn bar(t: Foo) {}
3105"#,
3106 expect![[r#"
3107 ev Foo::A Foo::A [type]
3108 ev Foo::B Foo::B [type]
3109 en Foo Foo [type]
3110 ex Foo::A [type]
3111 ex Foo::B [type]
3112 fn bar(…) fn(Foo) []
3113 fn foo() fn() []
3114 "#]],
3115 );
3116 }
3117
3118 #[test]
3119 fn enum_ref() {
3120 check_relevance(
3121 r#"
3122enum Foo { A, B }
3123fn foo() {
3124 bar($0);
3125}
3126fn bar(t: &Foo) {}
3127"#,
3128 expect![[r#"
3129 ev Foo::A Foo::A []
3130 ev &Foo::A [type]
3131 ev Foo::B Foo::B []
3132 ev &Foo::B [type]
3133 en Foo Foo []
3134 en &Foo [type]
3135 fn bar(…) fn(&Foo) []
3136 fn foo() fn() []
3137 "#]],
3138 );
3139 }
3140
3141 #[test]
3142 fn suggest_deref_fn_ret() {
3143 check_relevance(
3144 r#"
3145//- minicore: deref
3146struct S;
3147struct T(S);
3148
3149impl core::ops::Deref for T {
3150 type Target = S;
3151
3152 fn deref(&self) -> &Self::Target {
3153 &self.0
3154 }
3155}
3156
3157fn foo(s: &S) {}
3158fn bar() -> T {}
3159
3160fn main() {
3161 foo($0);
3162}
3163"#,
3164 expect![[r#"
3165 st S S []
3166 st &S [type]
3167 ex core::ops::Deref::deref(&bar()) [type_could_unify]
3168 st S S []
3169 st &S [type]
3170 st T T []
3171 st &T [type]
3172 fn bar() fn() -> T []
3173 fn &bar() [type]
3174 md core:: []
3175 fn foo(…) fn(&S) []
3176 fn main() fn() []
3177 "#]],
3178 )
3179 }
3180
3181 #[test]
3182 fn op_function_relevances() {
3183 check_relevance(
3184 r#"
3185#[lang = "sub"]
3186trait Sub {
3187 fn sub(self, other: Self) -> Self { self }
3188}
3189impl Sub for u32 {}
3190fn foo(a: u32) { a.$0 }
3191"#,
3192 expect![[r#"
3193 me sub(…) fn(self, Self) -> Self [op_method]
3194 "#]],
3195 );
3196 check_relevance(
3197 r#"
3198struct Foo;
3199impl Foo {
3200 fn new() -> Self {}
3201}
3202#[lang = "eq"]
3203pub trait PartialEq<Rhs: ?Sized = Self> {
3204 fn eq(&self, other: &Rhs) -> bool;
3205 fn ne(&self, other: &Rhs) -> bool;
3206}
3207
3208impl PartialEq for Foo {}
3209fn main() {
3210 Foo::$0
3211}
3212"#,
3213 expect![[r#"
3214 fn new() fn() -> Foo []
3215 me eq(…) fn(&self, &Rhs) -> bool [op_method]
3216 me ne(…) fn(&self, &Rhs) -> bool [op_method]
3217 "#]],
3218 );
3219 }
3220
3221 #[test]
3222 fn constructor_order_simple() {
3223 check_relevance(
3224 r#"
3225struct Foo;
3226struct Other;
3227struct Option<T>(T);
3228
3229impl Foo {
3230 fn fn_ctr() -> Foo { unimplemented!() }
3231 fn fn_another(n: u32) -> Other { unimplemented!() }
3232 fn fn_ctr_self() -> Option<Self> { unimplemented!() }
3233}
3234
3235fn test() {
3236 let a = Foo::$0;
3237}
3238"#,
3239 expect![[r#"
3240 fn fn_ctr() fn() -> Foo [type_could_unify]
3241 fn fn_ctr_self() fn() -> Option<Foo> [type_could_unify]
3242 fn fn_another(…) fn(u32) -> Other [type_could_unify]
3243 "#]],
3244 );
3245 }
3246
3247 #[test]
3248 fn constructor_order_kind() {
3249 check_function_relevance(
3250 r#"
3251struct Foo;
3252struct Bar;
3253struct Option<T>(T);
3254enum Result<T, E> { Ok(T), Err(E) };
3255
3256impl Foo {
3257 fn fn_ctr(&self) -> Foo { unimplemented!() }
3258 fn fn_ctr_with_args(&self, n: u32) -> Foo { unimplemented!() }
3259 fn fn_another(&self, n: u32) -> Bar { unimplemented!() }
3260 fn fn_ctr_wrapped(&self, ) -> Option<Self> { unimplemented!() }
3261 fn fn_ctr_wrapped_2(&self, ) -> Result<Self, Bar> { unimplemented!() }
3262 fn fn_ctr_wrapped_3(&self, ) -> Result<Bar, Self> { unimplemented!() } // Self is not the first type
3263 fn fn_ctr_wrapped_with_args(&self, m: u32) -> Option<Self> { unimplemented!() }
3264 fn fn_another_unit(&self) { unimplemented!() }
3265}
3266
3267fn test() {
3268 let a = self::Foo::$0;
3269}
3270"#,
3271 expect![[r#"
3272 [
3273 (
3274 "fn(&self, u32) -> Bar",
3275 Some(
3276 CompletionRelevanceFn {
3277 has_params: true,
3278 has_self_param: true,
3279 return_type: Other,
3280 },
3281 ),
3282 ),
3283 (
3284 "fn(&self)",
3285 Some(
3286 CompletionRelevanceFn {
3287 has_params: true,
3288 has_self_param: true,
3289 return_type: Other,
3290 },
3291 ),
3292 ),
3293 (
3294 "fn(&self) -> Foo",
3295 Some(
3296 CompletionRelevanceFn {
3297 has_params: true,
3298 has_self_param: true,
3299 return_type: DirectConstructor,
3300 },
3301 ),
3302 ),
3303 (
3304 "fn(&self, u32) -> Foo",
3305 Some(
3306 CompletionRelevanceFn {
3307 has_params: true,
3308 has_self_param: true,
3309 return_type: DirectConstructor,
3310 },
3311 ),
3312 ),
3313 (
3314 "fn(&self) -> Option<Foo>",
3315 Some(
3316 CompletionRelevanceFn {
3317 has_params: true,
3318 has_self_param: true,
3319 return_type: Constructor,
3320 },
3321 ),
3322 ),
3323 (
3324 "fn(&self) -> Result<Foo, Bar>",
3325 Some(
3326 CompletionRelevanceFn {
3327 has_params: true,
3328 has_self_param: true,
3329 return_type: Constructor,
3330 },
3331 ),
3332 ),
3333 (
3334 "fn(&self) -> Result<Bar, Foo>",
3335 Some(
3336 CompletionRelevanceFn {
3337 has_params: true,
3338 has_self_param: true,
3339 return_type: Constructor,
3340 },
3341 ),
3342 ),
3343 (
3344 "fn(&self, u32) -> Option<Foo>",
3345 Some(
3346 CompletionRelevanceFn {
3347 has_params: true,
3348 has_self_param: true,
3349 return_type: Constructor,
3350 },
3351 ),
3352 ),
3353 ]
3354 "#]],
3355 );
3356 }
3357
3358 #[test]
3359 fn constructor_order_relevance() {
3360 check_relevance(
3361 r#"
3362struct Foo;
3363struct FooBuilder;
3364struct Result<T>(T);
3365
3366impl Foo {
3367 fn fn_no_ret(&self) {}
3368 fn fn_ctr_with_args(input: u32) -> Foo { unimplemented!() }
3369 fn fn_direct_ctr() -> Self { unimplemented!() }
3370 fn fn_ctr() -> Result<Self> { unimplemented!() }
3371 fn fn_other() -> Result<u32> { unimplemented!() }
3372 fn fn_builder() -> FooBuilder { unimplemented!() }
3373}
3374
3375fn test() {
3376 let a = self::Foo::$0;
3377}
3378"#,
3379 expect![[r#"
3386 fn fn_direct_ctr() fn() -> Foo [type_could_unify]
3387 fn fn_ctr_with_args(…) fn(u32) -> Foo [type_could_unify]
3388 fn fn_builder() fn() -> FooBuilder [type_could_unify]
3389 fn fn_ctr() fn() -> Result<Foo> [type_could_unify]
3390 me fn_no_ret(…) fn(&self) [type_could_unify]
3391 fn fn_other() fn() -> Result<u32> [type_could_unify]
3392 "#]],
3393 );
3394
3395 }
3397
3398 #[test]
3399 fn function_relevance_generic_1() {
3400 check_relevance(
3401 r#"
3402struct Foo<T: Default>(T);
3403struct FooBuilder;
3404struct Option<T>(T);
3405enum Result<T, E>{Ok(T), Err(E)};
3406
3407impl<T: Default> Foo<T> {
3408 fn fn_returns_unit(&self) {}
3409 fn fn_ctr_with_args(input: T) -> Foo<T> { unimplemented!() }
3410 fn fn_direct_ctr() -> Self { unimplemented!() }
3411 fn fn_ctr_wrapped() -> Option<Self> { unimplemented!() }
3412 fn fn_ctr_wrapped_2() -> Result<Self, u32> { unimplemented!() }
3413 fn fn_other() -> Option<u32> { unimplemented!() }
3414 fn fn_builder() -> FooBuilder { unimplemented!() }
3415}
3416
3417fn test() {
3418 let a = self::Foo::<u32>::$0;
3419}
3420 "#,
3421 expect![[r#"
3422 fn fn_direct_ctr() fn() -> Foo<T> [type_could_unify]
3423 fn fn_ctr_with_args(…) fn(T) -> Foo<T> [type_could_unify]
3424 fn fn_builder() fn() -> FooBuilder [type_could_unify]
3425 fn fn_ctr_wrapped() fn() -> Option<Foo<T>> [type_could_unify]
3426 fn fn_ctr_wrapped_2() fn() -> Result<Foo<T>, u32> [type_could_unify]
3427 fn fn_other() fn() -> Option<u32> [type_could_unify]
3428 me fn_returns_unit(…) fn(&self) [type_could_unify]
3429 "#]],
3430 );
3431 }
3432
3433 #[test]
3434 fn function_relevance_generic_2() {
3435 check_relevance(
3437 r#"
3438struct Foo<T: Default>(T);
3439struct FooBuilder;
3440struct Option<T>(T);
3441enum Result<T, E>{Ok(T), Err(E)};
3442
3443impl<T: Default> Foo<T> {
3444 fn fn_no_ret(&self) {}
3445 fn fn_ctr_with_args(input: T) -> Foo<T> { unimplemented!() }
3446 fn fn_direct_ctr() -> Self { unimplemented!() }
3447 fn fn_ctr() -> Option<Self> { unimplemented!() }
3448 fn fn_ctr2() -> Result<Self, u32> { unimplemented!() }
3449 fn fn_other() -> Option<u32> { unimplemented!() }
3450 fn fn_builder() -> FooBuilder { unimplemented!() }
3451}
3452
3453fn test() {
3454 let a : Res<Foo<u32>> = Foo::$0;
3455}
3456 "#,
3457 expect![[r#"
3458 fn fn_direct_ctr() fn() -> Foo<T> [type_could_unify]
3459 fn fn_ctr_with_args(…) fn(T) -> Foo<T> [type_could_unify]
3460 fn fn_builder() fn() -> FooBuilder [type_could_unify]
3461 fn fn_ctr() fn() -> Option<Foo<T>> [type_could_unify]
3462 fn fn_ctr2() fn() -> Result<Foo<T>, u32> [type_could_unify]
3463 me fn_no_ret(…) fn(&self) [type_could_unify]
3464 fn fn_other() fn() -> Option<u32> [type_could_unify]
3465 "#]],
3466 );
3467 }
3468
3469 #[test]
3470 fn struct_field_method_ref() {
3471 check_kinds(
3472 r#"
3473struct Foo { bar: u32, qux: fn() }
3474impl Foo { fn baz(&self) -> u32 { 0 } }
3475
3476fn foo(f: Foo) { let _: &u32 = f.b$0 }
3477"#,
3478 &[
3479 CompletionItemKind::SymbolKind(SymbolKind::Method),
3480 CompletionItemKind::SymbolKind(SymbolKind::Field),
3481 ],
3482 expect![[r#"
3483 [
3484 CompletionItem {
3485 label: "baz()",
3486 detail_left: None,
3487 detail_right: Some(
3488 "fn(&self) -> u32",
3489 ),
3490 source_range: 109..110,
3491 delete: 109..110,
3492 insert: "baz()$0",
3493 kind: SymbolKind(
3494 Method,
3495 ),
3496 lookup: "baz",
3497 detail: "fn(&self) -> u32",
3498 relevance: CompletionRelevance {
3499 exact_name_match: false,
3500 type_match: None,
3501 is_local: false,
3502 trait_: None,
3503 is_name_already_imported: false,
3504 requires_import: false,
3505 is_private_editable: false,
3506 postfix_match: None,
3507 function: Some(
3508 CompletionRelevanceFn {
3509 has_params: true,
3510 has_self_param: true,
3511 return_type: Other,
3512 },
3513 ),
3514 is_skipping_completion: false,
3515 has_local_inherent_impl: false,
3516 is_deprecated: false,
3517 },
3518 ref_match: "&@107",
3519 },
3520 CompletionItem {
3521 label: "bar",
3522 detail_left: None,
3523 detail_right: Some(
3524 "u32",
3525 ),
3526 source_range: 109..110,
3527 delete: 109..110,
3528 insert: "bar",
3529 kind: SymbolKind(
3530 Field,
3531 ),
3532 detail: "u32",
3533 ref_match: "&@107",
3534 },
3535 CompletionItem {
3536 label: "qux",
3537 detail_left: None,
3538 detail_right: Some(
3539 "fn()",
3540 ),
3541 source_range: 109..110,
3542 text_edit: TextEdit {
3543 indels: [
3544 Indel {
3545 insert: "(",
3546 delete: 107..107,
3547 },
3548 Indel {
3549 insert: "qux)()",
3550 delete: 109..110,
3551 },
3552 ],
3553 annotation: None,
3554 },
3555 kind: SymbolKind(
3556 Field,
3557 ),
3558 detail: "fn()",
3559 },
3560 ]
3561 "#]],
3562 );
3563 }
3564
3565 #[test]
3566 fn expected_fn_type_ref() {
3567 check_kinds(
3568 r#"
3569struct S { field: fn() }
3570
3571fn foo() {
3572 let foo: fn() = S { fields: || {}}.fi$0;
3573}
3574"#,
3575 &[CompletionItemKind::SymbolKind(SymbolKind::Field)],
3576 expect![[r#"
3577 [
3578 CompletionItem {
3579 label: "field",
3580 detail_left: None,
3581 detail_right: Some(
3582 "fn()",
3583 ),
3584 source_range: 76..78,
3585 delete: 76..78,
3586 insert: "field",
3587 kind: SymbolKind(
3588 Field,
3589 ),
3590 detail: "fn()",
3591 relevance: CompletionRelevance {
3592 exact_name_match: false,
3593 type_match: Some(
3594 Exact,
3595 ),
3596 is_local: false,
3597 trait_: None,
3598 is_name_already_imported: false,
3599 requires_import: false,
3600 is_private_editable: false,
3601 postfix_match: None,
3602 function: None,
3603 is_skipping_completion: false,
3604 has_local_inherent_impl: false,
3605 is_deprecated: false,
3606 },
3607 },
3608 ]
3609 "#]],
3610 )
3611 }
3612
3613 #[test]
3614 fn qualified_path_ref() {
3615 check_kinds(
3616 r#"
3617struct S;
3618
3619struct T;
3620impl T {
3621 fn foo() -> S {}
3622}
3623
3624fn bar(s: &S) {}
3625
3626fn main() {
3627 bar(T::$0);
3628}
3629"#,
3630 &[CompletionItemKind::SymbolKind(SymbolKind::Function)],
3631 expect![[r#"
3632 [
3633 CompletionItem {
3634 label: "foo()",
3635 detail_left: None,
3636 detail_right: Some(
3637 "fn() -> S",
3638 ),
3639 source_range: 95..95,
3640 delete: 95..95,
3641 insert: "foo()$0",
3642 kind: SymbolKind(
3643 Function,
3644 ),
3645 lookup: "foo",
3646 detail: "fn() -> S",
3647 relevance: CompletionRelevance {
3648 exact_name_match: false,
3649 type_match: None,
3650 is_local: false,
3651 trait_: None,
3652 is_name_already_imported: false,
3653 requires_import: false,
3654 is_private_editable: false,
3655 postfix_match: None,
3656 function: Some(
3657 CompletionRelevanceFn {
3658 has_params: false,
3659 has_self_param: false,
3660 return_type: Other,
3661 },
3662 ),
3663 is_skipping_completion: false,
3664 has_local_inherent_impl: false,
3665 is_deprecated: false,
3666 },
3667 ref_match: "&@92",
3668 },
3669 ]
3670 "#]],
3671 );
3672 }
3673
3674 #[test]
3675 fn generic_enum() {
3676 check_relevance(
3677 r#"
3678enum Foo<T> { A(T), B }
3679// bar() should not be an exact type match
3680// because the generic parameters are different
3681fn bar() -> Foo<u8> { Foo::B }
3682// FIXME baz() should be an exact type match
3683// because the types could unify, but it currently
3684// is not. This is due to the T here being
3685// TyKind::Placeholder rather than TyKind::Missing.
3686fn baz<T>() -> Foo<T> { Foo::B }
3687fn foo() {
3688 let foo: Foo<u32> = Foo::B;
3689 let _: Foo<u32> = f$0;
3690}
3691"#,
3692 expect![[r#"
3693 ev Foo::B Foo::B [type_could_unify]
3694 ev Foo::A(…) Foo::A(T) [type_could_unify]
3695 lc foo Foo<u32> [type+local]
3696 ex Foo::B [type]
3697 ex foo [type]
3698 en Foo Foo<{unknown}> [type_could_unify]
3699 fn bar() fn() -> Foo<u8> []
3700 fn baz() fn() -> Foo<T> []
3701 fn foo() fn() []
3702 "#]],
3703 );
3704 }
3705
3706 #[test]
3707 fn postfix_exact_match_is_high_priority() {
3708 cov_mark::check!(postfix_exact_match_is_high_priority);
3709 check_relevance_for_kinds(
3710 r#"
3711mod ops {
3712 pub trait Not {
3713 type Output;
3714 fn not(self) -> Self::Output;
3715 }
3716
3717 impl Not for bool {
3718 type Output = bool;
3719 fn not(self) -> bool { if self { false } else { true }}
3720 }
3721}
3722
3723fn main() {
3724 let _: bool = (9 > 2).not$0;
3725}
3726 "#,
3727 &[CompletionItemKind::Snippet, CompletionItemKind::SymbolKind(SymbolKind::Method)],
3728 expect![[r#"
3729 sn not !expr [snippet]
3730 sn box Box::new(expr) []
3731 sn call function(expr) []
3732 sn const const {} []
3733 sn dbg dbg!(expr) []
3734 sn dbgr dbg!(&expr) []
3735 sn deref *expr []
3736 sn if if expr {} []
3737 sn match match expr {} []
3738 sn ref &expr []
3739 sn refm &mut expr []
3740 sn return return expr []
3741 sn unsafe unsafe {} []
3742 sn while while expr {} []
3743 me not() fn(self) -> <Self as Not>::Output [requires_import]
3744 "#]],
3745 );
3746 }
3747
3748 #[test]
3749 fn enum_variant_name_exact_match_is_high_priority() {
3750 check_relevance(
3751 r#"
3752struct Other;
3753struct String;
3754enum Foo {
3755 String($0)
3756}
3757 "#,
3758 expect![[r#"
3759 st String String [name]
3760 en Foo Foo []
3761 st Other Other []
3762 sp Self Foo []
3763 "#]],
3764 );
3765
3766 check_relevance(
3767 r#"
3768struct Other;
3769struct String;
3770enum Foo {
3771 String(String, $0)
3772}
3773 "#,
3774 expect![[r#"
3775 en Foo Foo []
3776 st Other Other []
3777 sp Self Foo []
3778 st String String []
3779 "#]],
3780 );
3781
3782 check_relevance(
3783 r#"
3784struct Other;
3785struct Vec<T>(T);
3786enum Foo {
3787 Vec(Vec<$0>)
3788}
3789 "#,
3790 expect![[r#"
3791 en Foo Foo []
3792 st Other Other []
3793 sp Self Foo []
3794 st Vec<…> Vec<{unknown}> []
3795 "#]],
3796 );
3797 }
3798
3799 #[test]
3800 fn postfix_inexact_match_is_low_priority() {
3801 cov_mark::check!(postfix_inexact_match_is_low_priority);
3802 check_relevance_for_kinds(
3803 r#"
3804struct S;
3805impl S {
3806 fn f(&self) {}
3807}
3808fn main() {
3809 S.$0
3810}
3811 "#,
3812 &[CompletionItemKind::Snippet, CompletionItemKind::SymbolKind(SymbolKind::Method)],
3813 expect![[r#"
3814 me f() fn(&self) []
3815 sn box Box::new(expr) []
3816 sn call function(expr) []
3817 sn const const {} []
3818 sn dbg dbg!(expr) []
3819 sn dbgr dbg!(&expr) []
3820 sn deref *expr []
3821 sn let let []
3822 sn letm let mut []
3823 sn match match expr {} []
3824 sn ref &expr []
3825 sn refm &mut expr []
3826 sn return return expr []
3827 sn unsafe unsafe {} []
3828 "#]],
3829 );
3830 }
3831
3832 #[test]
3833 fn flyimport_reduced_relevance() {
3834 check_relevance(
3835 r#"
3836mod std {
3837 pub mod io {
3838 pub trait BufRead {}
3839 pub struct BufReader;
3840 pub struct BufWriter;
3841 }
3842}
3843struct Buffer;
3844
3845fn f() {
3846 Buf$0
3847}
3848"#,
3849 expect![[r#"
3850 st Buffer Buffer []
3851 fn f() fn() []
3852 md std:: []
3853 tt BufRead [requires_import]
3854 st BufReader BufReader [requires_import]
3855 st BufWriter BufWriter [requires_import]
3856 "#]],
3857 );
3858 }
3859
3860 #[test]
3861 fn float_consts_relevance() {
3863 check_relevance(
3864 r#"
3865//- minicore: float_consts
3866fn main() {
3867 let x = f32::INF$0
3868}
3869"#,
3870 expect![[r#"
3871 ct INFINITY pub const INFINITY: f32 []
3872 ct NEG_INFINITY pub const NEG_INFINITY: f32 []
3873 ct INFINITY f32 [type_could_unify+requires_import+deprecated]
3874 ct NEG_INFINITY f32 [type_could_unify+requires_import+deprecated]
3875 "#]],
3876 );
3877 }
3878
3879 #[test]
3880 fn completes_struct_with_raw_identifier() {
3881 check_edit(
3882 "type",
3883 r#"
3884mod m { pub struct r#type {} }
3885fn main() {
3886 let r#type = m::t$0;
3887}
3888"#,
3889 r#"
3890mod m { pub struct r#type {} }
3891fn main() {
3892 let r#type = m::r#type;
3893}
3894"#,
3895 )
3896 }
3897
3898 #[test]
3899 fn completes_fn_with_raw_identifier() {
3900 check_edit(
3901 "type",
3902 r#"
3903mod m { pub fn r#type {} }
3904fn main() {
3905 m::t$0
3906}
3907"#,
3908 r#"
3909mod m { pub fn r#type {} }
3910fn main() {
3911 m::r#type();$0
3912}
3913"#,
3914 )
3915 }
3916
3917 #[test]
3918 fn completes_macro_with_raw_identifier() {
3919 check_edit(
3920 "let!",
3921 r#"
3922macro_rules! r#let { () => {} }
3923fn main() {
3924 $0
3925}
3926"#,
3927 r#"
3928macro_rules! r#let { () => {} }
3929fn main() {
3930 r#let!($0)
3931}
3932"#,
3933 )
3934 }
3935
3936 #[test]
3937 fn completes_variant_with_raw_identifier() {
3938 check_edit(
3939 "type",
3940 r#"
3941enum A { r#type }
3942fn main() {
3943 let a = A::t$0
3944}
3945"#,
3946 r#"
3947enum A { r#type }
3948fn main() {
3949 let a = A::r#type$0
3950}
3951"#,
3952 )
3953 }
3954
3955 #[test]
3956 fn completes_field_with_raw_identifier() {
3957 check_edit(
3958 "fn",
3959 r#"
3960mod r#type {
3961 pub struct r#struct {
3962 pub r#fn: u32
3963 }
3964}
3965
3966fn main() {
3967 let a = r#type::r#struct {};
3968 a.$0
3969}
3970"#,
3971 r#"
3972mod r#type {
3973 pub struct r#struct {
3974 pub r#fn: u32
3975 }
3976}
3977
3978fn main() {
3979 let a = r#type::r#struct {};
3980 a.r#fn
3981}
3982"#,
3983 )
3984 }
3985
3986 #[test]
3987 fn completes_const_with_raw_identifier() {
3988 check_edit(
3989 "type",
3990 r#"
3991struct r#struct {}
3992impl r#struct { pub const r#type: u8 = 1; }
3993fn main() {
3994 r#struct::t$0
3995}
3996"#,
3997 r#"
3998struct r#struct {}
3999impl r#struct { pub const r#type: u8 = 1; }
4000fn main() {
4001 r#struct::r#type
4002}
4003"#,
4004 )
4005 }
4006
4007 #[test]
4008 fn completes_type_alias_with_raw_identifier() {
4009 check_edit(
4010 "type type",
4011 r#"
4012struct r#struct {}
4013trait r#trait { type r#type; }
4014impl r#trait for r#struct { type t$0 }
4015"#,
4016 r#"
4017struct r#struct {}
4018trait r#trait { type r#type; }
4019impl r#trait for r#struct { type r#type = $0; }
4020"#,
4021 )
4022 }
4023
4024 #[test]
4025 fn field_access_includes_self() {
4026 check_edit(
4027 "length",
4028 r#"
4029struct S {
4030 length: i32
4031}
4032
4033impl S {
4034 fn some_fn(&self) {
4035 let l = len$0
4036 }
4037}
4038"#,
4039 r#"
4040struct S {
4041 length: i32
4042}
4043
4044impl S {
4045 fn some_fn(&self) {
4046 let l = self.length
4047 }
4048}
4049"#,
4050 )
4051 }
4052
4053 #[test]
4054 fn field_access_includes_closure_this_param() {
4055 check_edit(
4056 "length",
4057 r#"
4058//- minicore: fn
4059struct S {
4060 length: i32
4061}
4062
4063impl S {
4064 fn pack(&mut self, f: impl FnOnce(&mut Self, i32)) {
4065 self.length += 1;
4066 f(self, 3);
4067 self.length -= 1;
4068 }
4069
4070 fn some_fn(&mut self) {
4071 self.pack(|this, n| len$0);
4072 }
4073}
4074"#,
4075 r#"
4076struct S {
4077 length: i32
4078}
4079
4080impl S {
4081 fn pack(&mut self, f: impl FnOnce(&mut Self, i32)) {
4082 self.length += 1;
4083 f(self, 3);
4084 self.length -= 1;
4085 }
4086
4087 fn some_fn(&mut self) {
4088 self.pack(|this, n| this.length);
4089 }
4090}
4091"#,
4092 )
4093 }
4094
4095 #[test]
4096 fn notable_traits_method_relevance() {
4097 check_kinds(
4098 r#"
4099#[doc(notable_trait)]
4100trait Write {
4101 fn write(&self);
4102 fn flush(&self);
4103}
4104
4105struct Writer;
4106
4107impl Write for Writer {
4108 fn write(&self) {}
4109 fn flush(&self) {}
4110}
4111
4112fn main() {
4113 Writer.$0
4114}
4115"#,
4116 &[
4117 CompletionItemKind::SymbolKind(SymbolKind::Method),
4118 CompletionItemKind::SymbolKind(SymbolKind::Field),
4119 CompletionItemKind::SymbolKind(SymbolKind::Function),
4120 ],
4121 expect![[r#"
4122 [
4123 CompletionItem {
4124 label: "flush()",
4125 detail_left: Some(
4126 "(as Write)",
4127 ),
4128 detail_right: Some(
4129 "fn(&self)",
4130 ),
4131 source_range: 193..193,
4132 delete: 193..193,
4133 insert: "flush();$0",
4134 kind: SymbolKind(
4135 Method,
4136 ),
4137 lookup: "flush",
4138 detail: "fn(&self)",
4139 relevance: CompletionRelevance {
4140 exact_name_match: false,
4141 type_match: None,
4142 is_local: false,
4143 trait_: Some(
4144 CompletionRelevanceTraitInfo {
4145 notable_trait: true,
4146 is_op_method: false,
4147 },
4148 ),
4149 is_name_already_imported: false,
4150 requires_import: false,
4151 is_private_editable: false,
4152 postfix_match: None,
4153 function: None,
4154 is_skipping_completion: false,
4155 has_local_inherent_impl: false,
4156 is_deprecated: false,
4157 },
4158 },
4159 CompletionItem {
4160 label: "write()",
4161 detail_left: Some(
4162 "(as Write)",
4163 ),
4164 detail_right: Some(
4165 "fn(&self)",
4166 ),
4167 source_range: 193..193,
4168 delete: 193..193,
4169 insert: "write();$0",
4170 kind: SymbolKind(
4171 Method,
4172 ),
4173 lookup: "write",
4174 detail: "fn(&self)",
4175 relevance: CompletionRelevance {
4176 exact_name_match: false,
4177 type_match: None,
4178 is_local: false,
4179 trait_: Some(
4180 CompletionRelevanceTraitInfo {
4181 notable_trait: true,
4182 is_op_method: false,
4183 },
4184 ),
4185 is_name_already_imported: false,
4186 requires_import: false,
4187 is_private_editable: false,
4188 postfix_match: None,
4189 function: None,
4190 is_skipping_completion: false,
4191 has_local_inherent_impl: false,
4192 is_deprecated: false,
4193 },
4194 },
4195 ]
4196 "#]],
4197 );
4198 }
4199}