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