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