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