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, 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::{DotAccess, DotAccessKind, PathCompletionCtx, PathKind, PatternContext},
27 item::{Builder, CompletionRelevanceTypeMatch},
28 render::{
29 function::render_fn,
30 literal::render_variant_lit,
31 macro_::{render_macro, render_macro_pat},
32 },
33};
34#[derive(Debug, Clone)]
36pub(crate) struct RenderContext<'a> {
37 completion: &'a CompletionContext<'a>,
38 is_private_editable: bool,
39 import_to_add: Option<LocatedImport>,
40 doc_aliases: Vec<SmolStr>,
41}
42
43impl<'a> RenderContext<'a> {
44 pub(crate) fn new(completion: &'a CompletionContext<'a>) -> RenderContext<'a> {
45 RenderContext {
46 completion,
47 is_private_editable: false,
48 import_to_add: None,
49 doc_aliases: vec![],
50 }
51 }
52
53 pub(crate) fn private_editable(mut self, private_editable: bool) -> Self {
54 self.is_private_editable = private_editable;
55 self
56 }
57
58 pub(crate) fn import_to_add(mut self, import_to_add: Option<LocatedImport>) -> Self {
59 self.import_to_add = import_to_add;
60 self
61 }
62
63 pub(crate) fn doc_aliases(mut self, doc_aliases: Vec<SmolStr>) -> Self {
64 self.doc_aliases = doc_aliases;
65 self
66 }
67
68 fn snippet_cap(&self) -> Option<SnippetCap> {
69 self.completion.config.snippet_cap
70 }
71
72 fn db(&self) -> &'a RootDatabase {
73 self.completion.db
74 }
75
76 fn source_range(&self) -> TextRange {
77 self.completion.source_range()
78 }
79
80 fn completion_relevance(&self) -> CompletionRelevance {
81 CompletionRelevance {
82 is_private_editable: self.is_private_editable,
83 requires_import: self.import_to_add.is_some(),
84 ..Default::default()
85 }
86 }
87
88 fn is_immediately_after_macro_bang(&self) -> bool {
89 self.completion.token.kind() == SyntaxKind::BANG
90 && self.completion.token.parent().is_some_and(|it| it.kind() == SyntaxKind::MACRO_CALL)
91 }
92
93 fn is_deprecated(&self, def: impl HasAttrs) -> bool {
94 def.attrs(self.db()).is_deprecated()
95 }
96
97 fn is_deprecated_assoc_item(&self, as_assoc_item: impl AsAssocItem) -> bool {
98 let db = self.db();
99 let assoc = match as_assoc_item.as_assoc_item(db) {
100 Some(assoc) => assoc,
101 None => return false,
102 };
103
104 let is_assoc_deprecated = match assoc {
105 hir::AssocItem::Function(it) => self.is_deprecated(it),
106 hir::AssocItem::Const(it) => self.is_deprecated(it),
107 hir::AssocItem::TypeAlias(it) => self.is_deprecated(it),
108 };
109 is_assoc_deprecated
110 || assoc
111 .container_or_implemented_trait(db)
112 .map(|trait_| self.is_deprecated(trait_))
113 .unwrap_or(false)
114 }
115
116 fn docs(&self, def: impl HasDocs) -> Option<Documentation<'a>> {
118 def.docs(self.db())
119 }
120}
121
122pub(crate) fn render_field(
123 ctx: RenderContext<'_>,
124 dot_access: &DotAccess<'_>,
125 receiver: Option<SmolStr>,
126 field: hir::Field,
127 ty: &hir::Type<'_>,
128) -> CompletionItem {
129 let db = ctx.db();
130 let is_deprecated = ctx.is_deprecated(field);
131 let name = field.name(db);
132 let (name, escaped_name) =
133 (name.as_str().to_smolstr(), name.display_no_db(ctx.completion.edition).to_smolstr());
134 let mut item = CompletionItem::new(
135 SymbolKind::Field,
136 ctx.source_range(),
137 field_with_receiver(receiver.as_deref(), &name),
138 ctx.completion.edition,
139 );
140 item.set_relevance(CompletionRelevance {
141 type_match: compute_type_match(ctx.completion, ty),
142 exact_name_match: compute_exact_name_match(ctx.completion, &name),
143 is_skipping_completion: receiver.is_some(),
144 ..CompletionRelevance::default()
145 });
146 item.detail(ty.display(db, ctx.completion.display_target).to_string())
147 .set_documentation(field.docs(db))
148 .set_deprecated(is_deprecated)
149 .lookup_by(name);
150
151 let is_field_access = matches!(dot_access.kind, DotAccessKind::Field { .. });
152 if !is_field_access || ty.is_fn() || ty.is_closure() {
153 let mut builder = TextEdit::builder();
154 builder.replace(
159 ctx.source_range(),
160 field_with_receiver(receiver.as_deref(), &escaped_name).into(),
161 );
162
163 let expected_fn_type =
164 ctx.completion.expected_type.as_ref().is_some_and(|ty| ty.is_fn() || ty.is_closure());
165
166 if !expected_fn_type
167 && let Some(receiver) = &dot_access.receiver
168 && let Some(receiver) = ctx.completion.sema.original_ast_node(receiver.clone())
169 {
170 builder.insert(receiver.syntax().text_range().start(), "(".to_owned());
171 builder.insert(ctx.source_range().end(), ")".to_owned());
172
173 let is_parens_needed = !matches!(dot_access.kind, DotAccessKind::Method);
174
175 if is_parens_needed {
176 builder.insert(ctx.source_range().end(), "()".to_owned());
177 }
178 }
179
180 item.text_edit(builder.finish());
181 } else {
182 item.insert_text(field_with_receiver(receiver.as_deref(), &escaped_name));
183 }
184 if let Some(receiver) = &dot_access.receiver
185 && let Some(original) = ctx.completion.sema.original_ast_node(receiver.clone())
186 && let Some(ref_mode) = compute_ref_match(ctx.completion, ty)
187 {
188 item.ref_match(ref_mode, original.syntax().text_range().start());
189 }
190 item.doc_aliases(ctx.doc_aliases);
191 item.build(db)
192}
193
194fn field_with_receiver(receiver: Option<&str>, field_name: &str) -> SmolStr {
195 receiver
196 .map_or_else(|| field_name.into(), |receiver| format_smolstr!("{}.{field_name}", receiver))
197}
198
199pub(crate) fn render_tuple_field(
200 ctx: RenderContext<'_>,
201 receiver: Option<SmolStr>,
202 field: usize,
203 ty: &hir::Type<'_>,
204) -> CompletionItem {
205 let mut item = CompletionItem::new(
206 SymbolKind::Field,
207 ctx.source_range(),
208 field_with_receiver(receiver.as_deref(), &field.to_string()),
209 ctx.completion.edition,
210 );
211 item.detail(ty.display(ctx.db(), ctx.completion.display_target).to_string())
212 .lookup_by(field.to_string());
213 item.set_relevance(CompletionRelevance {
214 is_skipping_completion: receiver.is_some(),
215 ..ctx.completion_relevance()
216 });
217 item.build(ctx.db())
218}
219
220pub(crate) fn render_type_inference(
221 ty_string: String,
222 ctx: &CompletionContext<'_>,
223) -> CompletionItem {
224 let mut builder = CompletionItem::new(
225 CompletionItemKind::InferredType,
226 ctx.source_range(),
227 ty_string,
228 ctx.edition,
229 );
230 builder.set_relevance(CompletionRelevance {
231 type_match: Some(CompletionRelevanceTypeMatch::Exact),
232 exact_name_match: true,
233 ..Default::default()
234 });
235 builder.build(ctx.db)
236}
237
238pub(crate) fn render_path_resolution(
239 ctx: RenderContext<'_>,
240 path_ctx: &PathCompletionCtx<'_>,
241 local_name: hir::Name,
242 resolution: ScopeDef,
243) -> Builder {
244 render_resolution_path(ctx, path_ctx, local_name, None, resolution)
245}
246
247pub(crate) fn render_pattern_resolution(
248 ctx: RenderContext<'_>,
249 pattern_ctx: &PatternContext,
250 local_name: hir::Name,
251 resolution: ScopeDef,
252) -> Builder {
253 render_resolution_pat(ctx, pattern_ctx, local_name, None, resolution)
254}
255
256pub(crate) fn render_resolution_with_import(
257 ctx: RenderContext<'_>,
258 path_ctx: &PathCompletionCtx<'_>,
259 import_edit: LocatedImport,
260) -> Option<Builder> {
261 let resolution = ScopeDef::from(import_edit.original_item);
262 let local_name = get_import_name(resolution, &ctx, &import_edit)?;
263 let doc_aliases = ctx.completion.doc_aliases_in_scope(resolution);
265 let ctx = ctx.doc_aliases(doc_aliases);
266 Some(render_resolution_path(ctx, path_ctx, local_name, Some(import_edit), resolution))
267}
268
269pub(crate) fn render_resolution_with_import_pat(
270 ctx: RenderContext<'_>,
271 pattern_ctx: &PatternContext,
272 import_edit: LocatedImport,
273) -> Option<Builder> {
274 let resolution = ScopeDef::from(import_edit.original_item);
275 let local_name = get_import_name(resolution, &ctx, &import_edit)?;
276 Some(render_resolution_pat(ctx, pattern_ctx, local_name, Some(import_edit), resolution))
277}
278
279pub(crate) fn render_expr(
280 ctx: &CompletionContext<'_>,
281 expr: &hir::term_search::Expr<'_>,
282) -> Option<Builder> {
283 let mut i = 1;
284 let mut snippet_formatter = |ty: &hir::Type<'_>| {
285 let arg_name = ty
286 .as_adt()
287 .map(|adt| stdx::to_lower_snake_case(adt.name(ctx.db).as_str()))
288 .unwrap_or_else(|| String::from("_"));
289 let res = format!("${{{i}:{arg_name}}}");
290 i += 1;
291 res
292 };
293
294 let mut label_formatter = |ty: &hir::Type<'_>| {
295 ty.as_adt()
296 .map(|adt| stdx::to_lower_snake_case(adt.name(ctx.db).as_str()))
297 .unwrap_or_else(|| String::from("..."))
298 };
299
300 let cfg = ctx.config.find_path_config(ctx.is_nightly);
301
302 let label =
303 expr.gen_source_code(&ctx.scope, &mut label_formatter, cfg, ctx.display_target).ok()?;
304
305 let source_range = match ctx.original_token.parent() {
306 Some(node) => match node.ancestors().find_map(ast::Path::cast) {
307 Some(path) => path.syntax().text_range(),
308 None => node.text_range(),
309 },
310 None => ctx.source_range(),
311 };
312
313 let mut item =
314 CompletionItem::new(CompletionItemKind::Expression, source_range, label, ctx.edition);
315
316 let snippet = format!(
317 "{}$0",
318 expr.gen_source_code(&ctx.scope, &mut snippet_formatter, cfg, ctx.display_target).ok()?
319 );
320 let edit = TextEdit::replace(source_range, snippet);
321 item.snippet_edit(ctx.config.snippet_cap?, edit);
322 item.documentation(Documentation::new_owned(String::from(
323 "Autogenerated expression by term search",
324 )));
325 item.set_relevance(crate::CompletionRelevance {
326 type_match: compute_type_match(ctx, &expr.ty(ctx.db)),
327 ..Default::default()
328 });
329 for trait_ in expr.traits_used(ctx.db) {
330 let trait_item = hir::ItemInNs::from(hir::ModuleDef::from(trait_));
331 let Some(path) = ctx.module.find_path(ctx.db, trait_item, cfg) else {
332 continue;
333 };
334
335 item.add_import(LocatedImport::new_no_completion(path, trait_item, trait_item));
336 }
337
338 Some(item)
339}
340
341fn get_import_name(
342 resolution: ScopeDef,
343 ctx: &RenderContext<'_>,
344 import_edit: &LocatedImport,
345) -> Option<hir::Name> {
346 if import_edit.item_to_import == import_edit.original_item {
353 import_edit.import_path.segments().last().cloned()
354 } else {
355 scope_def_to_name(resolution, ctx, import_edit)
356 }
357}
358
359fn scope_def_to_name(
360 resolution: ScopeDef,
361 ctx: &RenderContext<'_>,
362 import_edit: &LocatedImport,
363) -> Option<hir::Name> {
364 Some(match resolution {
365 ScopeDef::ModuleDef(hir::ModuleDef::Function(f)) => f.name(ctx.completion.db),
366 ScopeDef::ModuleDef(hir::ModuleDef::Const(c)) => c.name(ctx.completion.db)?,
367 ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(t)) => t.name(ctx.completion.db),
368 _ => item_name(ctx.db(), import_edit.original_item)?,
369 })
370}
371
372fn render_resolution_pat(
373 ctx: RenderContext<'_>,
374 pattern_ctx: &PatternContext,
375 local_name: hir::Name,
376 import_to_add: Option<LocatedImport>,
377 resolution: ScopeDef,
378) -> Builder {
379 let _p = tracing::info_span!("render_resolution_pat").entered();
380 use hir::ModuleDef::*;
381
382 if let ScopeDef::ModuleDef(Macro(mac)) = resolution {
383 let ctx = ctx.import_to_add(import_to_add);
384 render_macro_pat(ctx, pattern_ctx, local_name, mac)
385 } else {
386 render_resolution_simple_(ctx, &local_name, import_to_add, resolution)
387 }
388}
389
390fn render_resolution_path(
391 ctx: RenderContext<'_>,
392 path_ctx: &PathCompletionCtx<'_>,
393 local_name: hir::Name,
394 import_to_add: Option<LocatedImport>,
395 resolution: ScopeDef,
396) -> Builder {
397 let _p = tracing::info_span!("render_resolution_path").entered();
398 use hir::ModuleDef::*;
399
400 let krate = ctx.completion.display_target;
401
402 match resolution {
403 ScopeDef::ModuleDef(Macro(mac)) => {
404 let ctx = ctx.import_to_add(import_to_add);
405 return render_macro(ctx, path_ctx, local_name, mac);
406 }
407 ScopeDef::ModuleDef(Function(func)) => {
408 let ctx = ctx.import_to_add(import_to_add);
409 return render_fn(ctx, path_ctx, Some(local_name), func);
410 }
411 ScopeDef::ModuleDef(Variant(var)) => {
412 let ctx = ctx.clone().import_to_add(import_to_add.clone());
413 if let Some(item) =
414 render_variant_lit(ctx, path_ctx, Some(local_name.clone()), var, None)
415 {
416 return item;
417 }
418 }
419 _ => (),
420 }
421
422 let completion = ctx.completion;
423 let cap = ctx.snippet_cap();
424 let db = completion.db;
425 let config = completion.config;
426 let requires_import = import_to_add.is_some();
427
428 let name = local_name.display_no_db(ctx.completion.edition).to_smolstr();
429 let mut item = render_resolution_simple_(ctx, &local_name, import_to_add, resolution);
430 if local_name.needs_escape(completion.edition) {
431 item.insert_text(local_name.display_no_db(completion.edition).to_smolstr());
432 }
433 let type_path_no_ty_args = matches!(
435 path_ctx,
436 PathCompletionCtx { kind: PathKind::Type { .. }, has_type_args: false, .. }
437 ) && config.callable.is_some();
438 if type_path_no_ty_args && let Some(cap) = cap {
439 let has_non_default_type_params = match resolution {
440 ScopeDef::ModuleDef(hir::ModuleDef::Adt(it)) => it.has_non_default_type_params(db),
441 ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(it)) => {
442 it.has_non_default_type_params(db)
443 }
444 _ => false,
445 };
446
447 if has_non_default_type_params {
448 cov_mark::hit!(inserts_angle_brackets_for_generics);
449 item.lookup_by(name.clone())
450 .label(SmolStr::from_iter([&name, "<…>"]))
451 .trigger_call_info()
452 .insert_snippet(cap, format!("{}<$0>", local_name.display(db, completion.edition)));
453 }
454 }
455
456 let mut set_item_relevance = |ty: Type<'_>| {
457 if !ty.is_unknown() {
458 item.detail(ty.display(db, krate).to_string());
459 }
460
461 item.set_relevance(CompletionRelevance {
462 type_match: compute_type_match(completion, &ty),
463 exact_name_match: compute_exact_name_match(completion, &name),
464 is_local: matches!(resolution, ScopeDef::Local(_)),
465 requires_import,
466 ..CompletionRelevance::default()
467 });
468
469 path_ref_match(completion, path_ctx, &ty, &mut item);
470 };
471
472 match resolution {
473 ScopeDef::Local(local) => set_item_relevance(local.ty(db)),
474 ScopeDef::ModuleDef(ModuleDef::Adt(adt)) | ScopeDef::AdtSelfType(adt) => {
475 set_item_relevance(adt.ty(db))
476 }
477 ScopeDef::ModuleDef(
479 ModuleDef::Function(_) | ModuleDef::Variant(_) | ModuleDef::Macro(_),
480 ) => (),
481 ScopeDef::ModuleDef(ModuleDef::Const(konst)) => set_item_relevance(konst.ty(db)),
482 ScopeDef::ModuleDef(ModuleDef::Static(stat)) => set_item_relevance(stat.ty(db)),
483 ScopeDef::ModuleDef(ModuleDef::BuiltinType(bt)) => set_item_relevance(bt.ty(db)),
484 ScopeDef::ImplSelfType(imp) => set_item_relevance(imp.self_ty(db)),
485 ScopeDef::GenericParam(_)
486 | ScopeDef::Label(_)
487 | ScopeDef::Unknown
488 | ScopeDef::ModuleDef(
489 ModuleDef::Trait(_) | ModuleDef::Module(_) | ModuleDef::TypeAlias(_),
490 ) => (),
491 };
492
493 item
494}
495
496fn render_resolution_simple_(
497 ctx: RenderContext<'_>,
498 local_name: &hir::Name,
499 import_to_add: Option<LocatedImport>,
500 resolution: ScopeDef,
501) -> Builder {
502 let _p = tracing::info_span!("render_resolution_simple_").entered();
503
504 let db = ctx.db();
505 let ctx = ctx.import_to_add(import_to_add);
506 let kind = res_to_kind(resolution);
507
508 let mut item = CompletionItem::new(
509 kind,
510 ctx.source_range(),
511 local_name.as_str().to_smolstr(),
512 ctx.completion.edition,
513 );
514 item.set_relevance(ctx.completion_relevance())
515 .set_documentation(scope_def_docs(db, resolution))
516 .set_deprecated(scope_def_is_deprecated(&ctx, resolution));
517
518 if let Some(import_to_add) = ctx.import_to_add {
519 item.add_import(import_to_add);
520 }
521
522 item.doc_aliases(ctx.doc_aliases);
523 item
524}
525
526fn res_to_kind(resolution: ScopeDef) -> CompletionItemKind {
527 use hir::ModuleDef::*;
528 match resolution {
529 ScopeDef::Unknown => CompletionItemKind::UnresolvedReference,
530 ScopeDef::ModuleDef(Function(_)) => CompletionItemKind::SymbolKind(SymbolKind::Function),
531 ScopeDef::ModuleDef(Variant(_)) => CompletionItemKind::SymbolKind(SymbolKind::Variant),
532 ScopeDef::ModuleDef(Macro(_)) => CompletionItemKind::SymbolKind(SymbolKind::Macro),
533 ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::SymbolKind(SymbolKind::Module),
534 ScopeDef::ModuleDef(Adt(adt)) => CompletionItemKind::SymbolKind(match adt {
535 hir::Adt::Struct(_) => SymbolKind::Struct,
536 hir::Adt::Union(_) => SymbolKind::Union,
537 hir::Adt::Enum(_) => SymbolKind::Enum,
538 }),
539 ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::SymbolKind(SymbolKind::Const),
540 ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::SymbolKind(SymbolKind::Static),
541 ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::SymbolKind(SymbolKind::Trait),
542 ScopeDef::ModuleDef(TypeAlias(..)) => CompletionItemKind::SymbolKind(SymbolKind::TypeAlias),
543 ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType,
544 ScopeDef::GenericParam(param) => CompletionItemKind::SymbolKind(match param {
545 hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam,
546 hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam,
547 hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam,
548 }),
549 ScopeDef::Local(..) => CompletionItemKind::SymbolKind(SymbolKind::Local),
550 ScopeDef::Label(..) => CompletionItemKind::SymbolKind(SymbolKind::Label),
551 ScopeDef::AdtSelfType(..) | ScopeDef::ImplSelfType(..) => {
552 CompletionItemKind::SymbolKind(SymbolKind::SelfParam)
553 }
554 }
555}
556
557fn scope_def_docs(db: &RootDatabase, resolution: ScopeDef) -> Option<Documentation<'_>> {
558 use hir::ModuleDef::*;
559 match resolution {
560 ScopeDef::ModuleDef(Module(it)) => it.docs(db),
561 ScopeDef::ModuleDef(Adt(it)) => it.docs(db),
562 ScopeDef::ModuleDef(Variant(it)) => it.docs(db),
563 ScopeDef::ModuleDef(Const(it)) => it.docs(db),
564 ScopeDef::ModuleDef(Static(it)) => it.docs(db),
565 ScopeDef::ModuleDef(Trait(it)) => it.docs(db),
566 ScopeDef::ModuleDef(TypeAlias(it)) => it.docs(db),
567 _ => None,
568 }
569}
570
571fn scope_def_is_deprecated(ctx: &RenderContext<'_>, resolution: ScopeDef) -> bool {
572 match resolution {
573 ScopeDef::ModuleDef(it) => ctx.is_deprecated_assoc_item(it),
574 ScopeDef::GenericParam(it) => ctx.is_deprecated(it),
575 ScopeDef::AdtSelfType(it) => ctx.is_deprecated(it),
576 _ => false,
577 }
578}
579
580fn match_types(
582 ctx: &CompletionContext<'_>,
583 ty1: &hir::Type<'_>,
584 ty2: &hir::Type<'_>,
585) -> Option<CompletionRelevanceTypeMatch> {
586 if ty1 == ty2 {
587 Some(CompletionRelevanceTypeMatch::Exact)
588 } else if ty1.could_unify_with(ctx.db, ty2) {
589 Some(CompletionRelevanceTypeMatch::CouldUnify)
590 } else {
591 None
592 }
593}
594
595fn compute_type_match(
596 ctx: &CompletionContext<'_>,
597 completion_ty: &hir::Type<'_>,
598) -> Option<CompletionRelevanceTypeMatch> {
599 let expected_type = ctx.expected_type.as_ref()?;
600
601 if expected_type.is_unit() {
604 return None;
605 }
606
607 if completion_ty.is_mutable_reference()
609 && let Some(expected_type) = expected_type.remove_ref()
610 && let Some(completion_ty) = completion_ty.remove_ref()
611 {
612 return match_types(ctx, &expected_type, &completion_ty);
613 }
614
615 match_types(ctx, expected_type, completion_ty)
616}
617
618fn compute_exact_name_match(ctx: &CompletionContext<'_>, completion_name: &str) -> bool {
619 ctx.expected_name.as_ref().is_some_and(|name| name.text() == completion_name)
620}
621
622fn compute_ref_match(
623 ctx: &CompletionContext<'_>,
624 completion_ty: &hir::Type<'_>,
625) -> Option<CompletionItemRefMode> {
626 let expected_type = ctx.expected_type.as_ref()?;
627 let expected_without_ref = expected_type.remove_ref();
628 let completion_without_ref = completion_ty.remove_ref();
629 if expected_type.could_unify_with(ctx.db, completion_ty) {
630 return None;
631 }
632 if let Some(expected_without_ref) = &expected_without_ref
633 && (completion_without_ref.is_none()
634 || completion_ty.could_unify_with(ctx.db, expected_without_ref))
635 && completion_ty.autoderef(ctx.db).any(|ty| ty == *expected_without_ref)
636 {
637 cov_mark::hit!(suggest_ref);
638 let mutability = if expected_type.is_mutable_reference() {
639 hir::Mutability::Mut
640 } else {
641 hir::Mutability::Shared
642 };
643 return Some(CompletionItemRefMode::Reference(mutability));
644 }
645
646 if let Some(completion_without_ref) = completion_without_ref
647 && completion_without_ref == *expected_type
648 && completion_without_ref.is_copy(ctx.db)
649 {
650 cov_mark::hit!(suggest_deref);
651 return Some(CompletionItemRefMode::Dereference);
652 }
653
654 None
655}
656
657fn path_ref_match(
658 completion: &CompletionContext<'_>,
659 path_ctx: &PathCompletionCtx<'_>,
660 ty: &hir::Type<'_>,
661 item: &mut Builder,
662) {
663 if let Some(original_path) = &path_ctx.original_path {
664 if let Some(original_path) = completion.sema.original_ast_node(original_path.clone())
666 && let Some(ref_mode) = compute_ref_match(completion, ty)
667 {
668 item.ref_match(ref_mode, original_path.syntax().text_range().start());
669 }
670 } else {
671 if let Some(ref_mode) = compute_ref_match(completion, ty) {
675 item.ref_match(ref_mode, completion.position.offset);
676 }
677 }
678}
679
680#[cfg(test)]
681mod tests {
682 use std::cmp;
683
684 use expect_test::{Expect, expect};
685 use ide_db::SymbolKind;
686 use itertools::Itertools;
687
688 use crate::{
689 CompletionItem, CompletionItemKind, CompletionRelevance, CompletionRelevancePostfixMatch,
690 item::CompletionRelevanceTypeMatch,
691 tests::{TEST_CONFIG, check_edit, do_completion, get_all_items},
692 };
693
694 #[track_caller]
695 fn check(
696 #[rust_analyzer::rust_fixture] ra_fixture: &str,
697 kind: impl Into<CompletionItemKind>,
698 expect: Expect,
699 ) {
700 let actual = do_completion(ra_fixture, kind.into());
701 expect.assert_debug_eq(&actual);
702 }
703
704 #[track_caller]
705 fn check_kinds(
706 #[rust_analyzer::rust_fixture] ra_fixture: &str,
707 kinds: &[CompletionItemKind],
708 expect: Expect,
709 ) {
710 let actual: Vec<_> =
711 kinds.iter().flat_map(|&kind| do_completion(ra_fixture, kind)).collect();
712 expect.assert_debug_eq(&actual);
713 }
714
715 #[track_caller]
716 fn check_function_relevance(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
717 let actual: Vec<_> =
718 do_completion(ra_fixture, CompletionItemKind::SymbolKind(SymbolKind::Method))
719 .into_iter()
720 .map(|item| (item.detail.unwrap_or_default(), item.relevance.function))
721 .collect();
722
723 expect.assert_debug_eq(&actual);
724 }
725
726 #[track_caller]
727 fn check_relevance_for_kinds(
728 #[rust_analyzer::rust_fixture] ra_fixture: &str,
729 kinds: &[CompletionItemKind],
730 expect: Expect,
731 ) {
732 let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
733 actual.retain(|it| kinds.contains(&it.kind));
734 actual.sort_by_key(|it| (cmp::Reverse(it.relevance.score()), it.label.primary.clone()));
735 check_relevance_(actual, expect);
736 }
737
738 #[track_caller]
739 fn check_relevance(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
740 let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
741 actual.retain(|it| it.kind != CompletionItemKind::Snippet);
742 actual.retain(|it| it.kind != CompletionItemKind::Keyword);
743 actual.retain(|it| it.kind != CompletionItemKind::BuiltinType);
744 actual.sort_by_key(|it| (cmp::Reverse(it.relevance.score()), it.label.primary.clone()));
745 check_relevance_(actual, expect);
746 }
747
748 #[track_caller]
749 fn check_relevance_(actual: Vec<CompletionItem>, expect: Expect) {
750 let actual = actual
751 .into_iter()
752 .flat_map(|it| {
753 let mut items = vec![];
754
755 let tag = it.kind.tag();
756 let relevance = display_relevance(it.relevance);
757 items.push(format!(
758 "{tag} {} {} {relevance}\n",
759 it.label.primary,
760 it.label.detail_right.clone().unwrap_or_default(),
761 ));
762
763 if let Some((label, _indel, relevance)) = it.ref_match() {
764 let relevance = display_relevance(relevance);
765
766 items.push(format!("{tag} {label} {relevance}\n"));
767 }
768
769 items
770 })
771 .collect::<String>();
772
773 expect.assert_eq(&actual);
774
775 fn display_relevance(relevance: CompletionRelevance) -> String {
776 let relevance_factors = vec![
777 (relevance.type_match == Some(CompletionRelevanceTypeMatch::Exact), "type"),
778 (
779 relevance.type_match == Some(CompletionRelevanceTypeMatch::CouldUnify),
780 "type_could_unify",
781 ),
782 (relevance.exact_name_match, "name"),
783 (relevance.is_local, "local"),
784 (
785 relevance.postfix_match == Some(CompletionRelevancePostfixMatch::Exact),
786 "snippet",
787 ),
788 (relevance.trait_.is_some_and(|it| it.is_op_method), "op_method"),
789 (relevance.requires_import, "requires_import"),
790 ]
791 .into_iter()
792 .filter_map(|(cond, desc)| if cond { Some(desc) } else { None })
793 .join("+");
794
795 format!("[{relevance_factors}]")
796 }
797 }
798
799 #[test]
800 fn set_struct_type_completion_info() {
801 check_relevance(
802 r#"
803//- /lib.rs crate:dep
804
805pub mod test_mod_b {
806 pub struct Struct {}
807}
808
809pub mod test_mod_a {
810 pub struct Struct {}
811}
812
813//- /main.rs crate:main deps:dep
814
815fn test(input: dep::test_mod_b::Struct) { }
816
817fn main() {
818 test(Struct$0);
819}
820"#,
821 expect![[r#"
822 st dep::test_mod_b::Struct {…} dep::test_mod_b::Struct { } [type_could_unify]
823 ex dep::test_mod_b::Struct { } [type_could_unify]
824 st Struct Struct [type_could_unify+requires_import]
825 md dep []
826 fn main() fn() []
827 fn test(…) fn(Struct) []
828 st Struct Struct [requires_import]
829 "#]],
830 );
831 }
832
833 #[test]
834 fn set_union_type_completion_info() {
835 check_relevance(
836 r#"
837//- /lib.rs crate:dep
838
839pub mod test_mod_b {
840 pub union Union {
841 a: i32,
842 b: i32
843 }
844}
845
846pub mod test_mod_a {
847 pub enum Union {
848 a: i32,
849 b: i32
850 }
851}
852
853//- /main.rs crate:main deps:dep
854
855fn test(input: dep::test_mod_b::Union) { }
856
857fn main() {
858 test(Union$0);
859}
860"#,
861 expect![[r#"
862 un Union Union [type_could_unify+requires_import]
863 md dep []
864 fn main() fn() []
865 fn test(…) fn(Union) []
866 en Union Union [requires_import]
867 "#]],
868 );
869 }
870
871 #[test]
872 fn set_enum_type_completion_info() {
873 check_relevance(
874 r#"
875//- /lib.rs crate:dep
876
877pub mod test_mod_b {
878 pub enum Enum {
879 variant
880 }
881}
882
883pub mod test_mod_a {
884 pub enum Enum {
885 variant
886 }
887}
888
889//- /main.rs crate:main deps:dep
890
891fn test(input: dep::test_mod_b::Enum) { }
892
893fn main() {
894 test(Enum$0);
895}
896"#,
897 expect![[r#"
898 ev dep::test_mod_b::Enum::variant dep::test_mod_b::Enum::variant [type_could_unify]
899 ex dep::test_mod_b::Enum::variant [type_could_unify]
900 en Enum Enum [type_could_unify+requires_import]
901 md dep []
902 fn main() fn() []
903 fn test(…) fn(Enum) []
904 en Enum Enum [requires_import]
905 "#]],
906 );
907 }
908
909 #[test]
910 fn set_enum_variant_type_completion_info() {
911 check_relevance(
912 r#"
913//- /lib.rs crate:dep
914
915pub mod test_mod_b {
916 pub enum Enum {
917 Variant
918 }
919}
920
921pub mod test_mod_a {
922 pub enum Enum {
923 Variant
924 }
925}
926
927//- /main.rs crate:main deps:dep
928
929fn test(input: dep::test_mod_b::Enum) { }
930
931fn main() {
932 test(Variant$0);
933}
934"#,
935 expect![[r#"
936 ev dep::test_mod_b::Enum::Variant dep::test_mod_b::Enum::Variant [type_could_unify]
937 ex dep::test_mod_b::Enum::Variant [type_could_unify]
938 md dep []
939 fn main() fn() []
940 fn test(…) fn(Enum) []
941 "#]],
942 );
943 }
944
945 #[test]
946 fn set_fn_type_completion_info() {
947 check_relevance(
948 r#"
949//- /lib.rs crate:dep
950
951pub mod test_mod_b {
952 pub fn function(j: isize) -> i32 {}
953}
954
955pub mod test_mod_a {
956 pub fn function(i: usize) -> i32 {}
957}
958
959//- /main.rs crate:main deps:dep
960
961fn test(input: fn(usize) -> i32) { }
962
963fn main() {
964 test(function$0);
965}
966"#,
967 expect![[r#"
968 md dep []
969 fn main() fn() []
970 fn test(…) fn(fn(usize) -> i32) []
971 fn function fn(usize) -> i32 [requires_import]
972 fn function(…) fn(isize) -> i32 [requires_import]
973 "#]],
974 );
975 }
976
977 #[test]
978 fn set_const_type_completion_info() {
979 check_relevance(
980 r#"
981//- /lib.rs crate:dep
982
983pub mod test_mod_b {
984 pub const CONST: i32 = 1;
985}
986
987pub mod test_mod_a {
988 pub const CONST: i64 = 2;
989}
990
991//- /main.rs crate:main deps:dep
992
993fn test(input: i32) { }
994
995fn main() {
996 test(CONST$0);
997}
998"#,
999 expect![[r#"
1000 ct CONST i32 [type_could_unify+requires_import]
1001 md dep []
1002 fn main() fn() []
1003 fn test(…) fn(i32) []
1004 ct CONST i64 [requires_import]
1005 "#]],
1006 );
1007 }
1008
1009 #[test]
1010 fn set_static_type_completion_info() {
1011 check_relevance(
1012 r#"
1013//- /lib.rs crate:dep
1014
1015pub mod test_mod_b {
1016 pub static STATIC: i32 = 5;
1017}
1018
1019pub mod test_mod_a {
1020 pub static STATIC: i64 = 5;
1021}
1022
1023//- /main.rs crate:main deps:dep
1024
1025fn test(input: i32) { }
1026
1027fn main() {
1028 test(STATIC$0);
1029}
1030"#,
1031 expect![[r#"
1032 sc STATIC i32 [type_could_unify+requires_import]
1033 md dep []
1034 fn main() fn() []
1035 fn test(…) fn(i32) []
1036 sc STATIC i64 [requires_import]
1037 "#]],
1038 );
1039 }
1040
1041 #[test]
1042 fn set_self_type_completion_info_with_params() {
1043 check_relevance(
1044 r#"
1045//- /lib.rs crate:dep
1046pub struct Struct;
1047
1048impl Struct {
1049 pub fn Function(&self, input: i32) -> bool {
1050 false
1051 }
1052}
1053
1054
1055//- /main.rs crate:main deps:dep
1056
1057use dep::Struct;
1058
1059
1060fn test(input: fn(&dep::Struct, i32) -> bool) { }
1061
1062fn main() {
1063 test(Struct::Function$0);
1064}
1065
1066"#,
1067 expect![[r#"
1068 me Function fn(&self, i32) -> bool []
1069 "#]],
1070 );
1071 }
1072
1073 #[test]
1074 fn set_self_type_completion_info() {
1075 check_relevance(
1076 r#"
1077//- /main.rs crate:main
1078
1079struct Struct;
1080
1081impl Struct {
1082fn test(&self) {
1083 func(Self$0);
1084 }
1085}
1086
1087fn func(input: Struct) { }
1088
1089"#,
1090 expect![[r#"
1091 st Self Self [type]
1092 st Struct Struct [type]
1093 sp Self Struct [type]
1094 st Struct Struct [type]
1095 ex Struct [type]
1096 lc self &Struct [local]
1097 fn func(…) fn(Struct) []
1098 me self.test() fn(&self) []
1099 "#]],
1100 );
1101 }
1102
1103 #[test]
1104 fn set_builtin_type_completion_info() {
1105 check_relevance(
1106 r#"
1107//- /main.rs crate:main
1108
1109fn test(input: bool) { }
1110 pub Input: bool = false;
1111
1112fn main() {
1113 let input = false;
1114 let inputbad = 3;
1115 test(inp$0);
1116}
1117"#,
1118 expect![[r#"
1119 lc input bool [type+name+local]
1120 ex false [type]
1121 ex input [type]
1122 ex true [type]
1123 lc inputbad i32 [local]
1124 fn main() fn() []
1125 fn test(…) fn(bool) []
1126 "#]],
1127 );
1128 }
1129
1130 #[test]
1131 fn enum_detail_includes_record_fields() {
1132 check(
1133 r#"
1134enum Foo { Foo { x: i32, y: i32 } }
1135
1136fn main() { Foo::Fo$0 }
1137"#,
1138 SymbolKind::Variant,
1139 expect![[r#"
1140 [
1141 CompletionItem {
1142 label: "Foo {…}",
1143 detail_left: None,
1144 detail_right: Some(
1145 "Foo { x: i32, y: i32 }",
1146 ),
1147 source_range: 54..56,
1148 delete: 54..56,
1149 insert: "Foo { x: ${1:()}, y: ${2:()} }$0",
1150 kind: SymbolKind(
1151 Variant,
1152 ),
1153 lookup: "Foo{}",
1154 detail: "Foo { x: i32, y: i32 }",
1155 relevance: CompletionRelevance {
1156 exact_name_match: false,
1157 type_match: None,
1158 is_local: false,
1159 trait_: None,
1160 is_name_already_imported: false,
1161 requires_import: false,
1162 is_private_editable: false,
1163 postfix_match: None,
1164 function: Some(
1165 CompletionRelevanceFn {
1166 has_params: true,
1167 has_self_param: false,
1168 return_type: DirectConstructor,
1169 },
1170 ),
1171 is_skipping_completion: false,
1172 },
1173 trigger_call_info: true,
1174 },
1175 ]
1176 "#]],
1177 );
1178 }
1179
1180 #[test]
1181 fn enum_detail_includes_tuple_fields() {
1182 check(
1183 r#"
1184enum Foo { Foo (i32, i32) }
1185
1186fn main() { Foo::Fo$0 }
1187"#,
1188 SymbolKind::Variant,
1189 expect![[r#"
1190 [
1191 CompletionItem {
1192 label: "Foo(…)",
1193 detail_left: None,
1194 detail_right: Some(
1195 "Foo(i32, i32)",
1196 ),
1197 source_range: 46..48,
1198 delete: 46..48,
1199 insert: "Foo(${1:()}, ${2:()})$0",
1200 kind: SymbolKind(
1201 Variant,
1202 ),
1203 lookup: "Foo()",
1204 detail: "Foo(i32, i32)",
1205 relevance: CompletionRelevance {
1206 exact_name_match: false,
1207 type_match: None,
1208 is_local: false,
1209 trait_: None,
1210 is_name_already_imported: false,
1211 requires_import: false,
1212 is_private_editable: false,
1213 postfix_match: None,
1214 function: Some(
1215 CompletionRelevanceFn {
1216 has_params: true,
1217 has_self_param: false,
1218 return_type: DirectConstructor,
1219 },
1220 ),
1221 is_skipping_completion: false,
1222 },
1223 trigger_call_info: true,
1224 },
1225 ]
1226 "#]],
1227 );
1228 }
1229
1230 #[test]
1231 fn fn_detail_includes_args_and_return_type() {
1232 check(
1233 r#"
1234fn foo<T>(a: u32, b: u32, t: T) -> (u32, T) { (a, t) }
1235
1236fn main() { fo$0 }
1237"#,
1238 SymbolKind::Function,
1239 expect![[r#"
1240 [
1241 CompletionItem {
1242 label: "foo(…)",
1243 detail_left: None,
1244 detail_right: Some(
1245 "fn(u32, u32, T) -> (u32, T)",
1246 ),
1247 source_range: 68..70,
1248 delete: 68..70,
1249 insert: "foo(${1:a}, ${2:b}, ${3:t})$0",
1250 kind: SymbolKind(
1251 Function,
1252 ),
1253 lookup: "foo",
1254 detail: "fn(u32, u32, T) -> (u32, T)",
1255 trigger_call_info: true,
1256 },
1257 CompletionItem {
1258 label: "main()",
1259 detail_left: None,
1260 detail_right: Some(
1261 "fn()",
1262 ),
1263 source_range: 68..70,
1264 delete: 68..70,
1265 insert: "main();$0",
1266 kind: SymbolKind(
1267 Function,
1268 ),
1269 lookup: "main",
1270 detail: "fn()",
1271 },
1272 ]
1273 "#]],
1274 );
1275 }
1276
1277 #[test]
1278 fn fn_detail_includes_variadics() {
1279 check(
1280 r#"
1281unsafe extern "C" fn foo(a: u32, b: u32, ...) {}
1282
1283fn main() { fo$0 }
1284"#,
1285 SymbolKind::Function,
1286 expect![[r#"
1287 [
1288 CompletionItem {
1289 label: "foo(…)",
1290 detail_left: None,
1291 detail_right: Some(
1292 "unsafe fn(u32, u32, ...)",
1293 ),
1294 source_range: 62..64,
1295 delete: 62..64,
1296 insert: "foo(${1:a}, ${2:b});$0",
1297 kind: SymbolKind(
1298 Function,
1299 ),
1300 lookup: "foo",
1301 detail: "unsafe fn(u32, u32, ...)",
1302 trigger_call_info: true,
1303 },
1304 CompletionItem {
1305 label: "main()",
1306 detail_left: None,
1307 detail_right: Some(
1308 "fn()",
1309 ),
1310 source_range: 62..64,
1311 delete: 62..64,
1312 insert: "main();$0",
1313 kind: SymbolKind(
1314 Function,
1315 ),
1316 lookup: "main",
1317 detail: "fn()",
1318 },
1319 ]
1320 "#]],
1321 );
1322 }
1323
1324 #[test]
1325 fn enum_detail_just_name_for_unit() {
1326 check(
1327 r#"
1328enum Foo { Foo }
1329
1330fn main() { Foo::Fo$0 }
1331"#,
1332 SymbolKind::Variant,
1333 expect![[r#"
1334 [
1335 CompletionItem {
1336 label: "Foo",
1337 detail_left: None,
1338 detail_right: Some(
1339 "Foo",
1340 ),
1341 source_range: 35..37,
1342 delete: 35..37,
1343 insert: "Foo$0",
1344 kind: SymbolKind(
1345 Variant,
1346 ),
1347 detail: "Foo",
1348 relevance: CompletionRelevance {
1349 exact_name_match: false,
1350 type_match: None,
1351 is_local: false,
1352 trait_: None,
1353 is_name_already_imported: false,
1354 requires_import: false,
1355 is_private_editable: false,
1356 postfix_match: None,
1357 function: Some(
1358 CompletionRelevanceFn {
1359 has_params: false,
1360 has_self_param: false,
1361 return_type: DirectConstructor,
1362 },
1363 ),
1364 is_skipping_completion: false,
1365 },
1366 trigger_call_info: true,
1367 },
1368 ]
1369 "#]],
1370 );
1371 }
1372
1373 #[test]
1374 fn lookup_enums_by_two_qualifiers() {
1375 check_kinds(
1376 r#"
1377mod m {
1378 pub enum Spam { Foo, Bar(i32) }
1379}
1380fn main() { let _: m::Spam = S$0 }
1381"#,
1382 &[
1383 CompletionItemKind::SymbolKind(SymbolKind::Function),
1384 CompletionItemKind::SymbolKind(SymbolKind::Module),
1385 CompletionItemKind::SymbolKind(SymbolKind::Variant),
1386 ],
1387 expect![[r#"
1388 [
1389 CompletionItem {
1390 label: "main()",
1391 detail_left: None,
1392 detail_right: Some(
1393 "fn()",
1394 ),
1395 source_range: 75..76,
1396 delete: 75..76,
1397 insert: "main();$0",
1398 kind: SymbolKind(
1399 Function,
1400 ),
1401 lookup: "main",
1402 detail: "fn()",
1403 },
1404 CompletionItem {
1405 label: "m",
1406 detail_left: None,
1407 detail_right: None,
1408 source_range: 75..76,
1409 delete: 75..76,
1410 insert: "m",
1411 kind: SymbolKind(
1412 Module,
1413 ),
1414 },
1415 CompletionItem {
1416 label: "m::Spam::Bar(…)",
1417 detail_left: None,
1418 detail_right: Some(
1419 "m::Spam::Bar(i32)",
1420 ),
1421 source_range: 75..76,
1422 delete: 75..76,
1423 insert: "m::Spam::Bar(${1:()})$0",
1424 kind: SymbolKind(
1425 Variant,
1426 ),
1427 lookup: "Spam::Bar()",
1428 detail: "m::Spam::Bar(i32)",
1429 relevance: CompletionRelevance {
1430 exact_name_match: false,
1431 type_match: Some(
1432 Exact,
1433 ),
1434 is_local: false,
1435 trait_: None,
1436 is_name_already_imported: false,
1437 requires_import: false,
1438 is_private_editable: false,
1439 postfix_match: None,
1440 function: Some(
1441 CompletionRelevanceFn {
1442 has_params: true,
1443 has_self_param: false,
1444 return_type: DirectConstructor,
1445 },
1446 ),
1447 is_skipping_completion: false,
1448 },
1449 trigger_call_info: true,
1450 },
1451 CompletionItem {
1452 label: "m::Spam::Foo",
1453 detail_left: None,
1454 detail_right: Some(
1455 "m::Spam::Foo",
1456 ),
1457 source_range: 75..76,
1458 delete: 75..76,
1459 insert: "m::Spam::Foo$0",
1460 kind: SymbolKind(
1461 Variant,
1462 ),
1463 lookup: "Spam::Foo",
1464 detail: "m::Spam::Foo",
1465 relevance: CompletionRelevance {
1466 exact_name_match: false,
1467 type_match: Some(
1468 Exact,
1469 ),
1470 is_local: false,
1471 trait_: None,
1472 is_name_already_imported: false,
1473 requires_import: false,
1474 is_private_editable: false,
1475 postfix_match: None,
1476 function: Some(
1477 CompletionRelevanceFn {
1478 has_params: false,
1479 has_self_param: false,
1480 return_type: DirectConstructor,
1481 },
1482 ),
1483 is_skipping_completion: false,
1484 },
1485 trigger_call_info: true,
1486 },
1487 ]
1488 "#]],
1489 )
1490 }
1491
1492 #[test]
1493 fn sets_deprecated_flag_in_items() {
1494 check(
1495 r#"
1496#[deprecated]
1497fn something_deprecated() {}
1498
1499fn main() { som$0 }
1500"#,
1501 SymbolKind::Function,
1502 expect![[r#"
1503 [
1504 CompletionItem {
1505 label: "main()",
1506 detail_left: None,
1507 detail_right: Some(
1508 "fn()",
1509 ),
1510 source_range: 56..59,
1511 delete: 56..59,
1512 insert: "main();$0",
1513 kind: SymbolKind(
1514 Function,
1515 ),
1516 lookup: "main",
1517 detail: "fn()",
1518 },
1519 CompletionItem {
1520 label: "something_deprecated()",
1521 detail_left: None,
1522 detail_right: Some(
1523 "fn()",
1524 ),
1525 source_range: 56..59,
1526 delete: 56..59,
1527 insert: "something_deprecated();$0",
1528 kind: SymbolKind(
1529 Function,
1530 ),
1531 lookup: "something_deprecated",
1532 detail: "fn()",
1533 deprecated: true,
1534 },
1535 ]
1536 "#]],
1537 );
1538
1539 check(
1540 r#"
1541struct A { #[deprecated] the_field: u32 }
1542fn foo() { A { the$0 } }
1543"#,
1544 SymbolKind::Field,
1545 expect![[r#"
1546 [
1547 CompletionItem {
1548 label: "the_field",
1549 detail_left: None,
1550 detail_right: Some(
1551 "u32",
1552 ),
1553 source_range: 57..60,
1554 delete: 57..60,
1555 insert: "the_field",
1556 kind: SymbolKind(
1557 Field,
1558 ),
1559 detail: "u32",
1560 deprecated: true,
1561 relevance: CompletionRelevance {
1562 exact_name_match: false,
1563 type_match: Some(
1564 CouldUnify,
1565 ),
1566 is_local: false,
1567 trait_: None,
1568 is_name_already_imported: false,
1569 requires_import: false,
1570 is_private_editable: false,
1571 postfix_match: None,
1572 function: None,
1573 is_skipping_completion: false,
1574 },
1575 },
1576 ]
1577 "#]],
1578 );
1579 }
1580
1581 #[test]
1582 fn renders_docs() {
1583 check_kinds(
1584 r#"
1585struct S {
1586 /// Field docs
1587 foo:
1588}
1589impl S {
1590 /// Method docs
1591 fn bar(self) { self.$0 }
1592}"#,
1593 &[
1594 CompletionItemKind::SymbolKind(SymbolKind::Method),
1595 CompletionItemKind::SymbolKind(SymbolKind::Field),
1596 ],
1597 expect![[r#"
1598 [
1599 CompletionItem {
1600 label: "bar()",
1601 detail_left: None,
1602 detail_right: Some(
1603 "fn(self)",
1604 ),
1605 source_range: 94..94,
1606 delete: 94..94,
1607 insert: "bar();$0",
1608 kind: SymbolKind(
1609 Method,
1610 ),
1611 lookup: "bar",
1612 detail: "fn(self)",
1613 documentation: Documentation(
1614 "Method docs",
1615 ),
1616 relevance: CompletionRelevance {
1617 exact_name_match: false,
1618 type_match: None,
1619 is_local: false,
1620 trait_: None,
1621 is_name_already_imported: false,
1622 requires_import: false,
1623 is_private_editable: false,
1624 postfix_match: None,
1625 function: Some(
1626 CompletionRelevanceFn {
1627 has_params: true,
1628 has_self_param: true,
1629 return_type: Other,
1630 },
1631 ),
1632 is_skipping_completion: false,
1633 },
1634 },
1635 CompletionItem {
1636 label: "foo",
1637 detail_left: None,
1638 detail_right: Some(
1639 "{unknown}",
1640 ),
1641 source_range: 94..94,
1642 delete: 94..94,
1643 insert: "foo",
1644 kind: SymbolKind(
1645 Field,
1646 ),
1647 detail: "{unknown}",
1648 documentation: Documentation(
1649 "Field docs",
1650 ),
1651 },
1652 ]
1653 "#]],
1654 );
1655
1656 check_kinds(
1657 r#"
1658use self::my$0;
1659
1660/// mod docs
1661mod my { }
1662
1663/// enum docs
1664enum E {
1665 /// variant docs
1666 V
1667}
1668use self::E::*;
1669"#,
1670 &[
1671 CompletionItemKind::SymbolKind(SymbolKind::Module),
1672 CompletionItemKind::SymbolKind(SymbolKind::Variant),
1673 CompletionItemKind::SymbolKind(SymbolKind::Enum),
1674 ],
1675 expect![[r#"
1676 [
1677 CompletionItem {
1678 label: "my",
1679 detail_left: None,
1680 detail_right: None,
1681 source_range: 10..12,
1682 delete: 10..12,
1683 insert: "my",
1684 kind: SymbolKind(
1685 Module,
1686 ),
1687 documentation: Documentation(
1688 "mod docs",
1689 ),
1690 },
1691 CompletionItem {
1692 label: "V",
1693 detail_left: None,
1694 detail_right: Some(
1695 "V",
1696 ),
1697 source_range: 10..12,
1698 delete: 10..12,
1699 insert: "V$0",
1700 kind: SymbolKind(
1701 Variant,
1702 ),
1703 detail: "V",
1704 documentation: Documentation(
1705 "variant docs",
1706 ),
1707 relevance: CompletionRelevance {
1708 exact_name_match: false,
1709 type_match: None,
1710 is_local: false,
1711 trait_: None,
1712 is_name_already_imported: false,
1713 requires_import: false,
1714 is_private_editable: false,
1715 postfix_match: None,
1716 function: Some(
1717 CompletionRelevanceFn {
1718 has_params: false,
1719 has_self_param: false,
1720 return_type: DirectConstructor,
1721 },
1722 ),
1723 is_skipping_completion: false,
1724 },
1725 trigger_call_info: true,
1726 },
1727 CompletionItem {
1728 label: "E",
1729 detail_left: None,
1730 detail_right: Some(
1731 "E",
1732 ),
1733 source_range: 10..12,
1734 delete: 10..12,
1735 insert: "E",
1736 kind: SymbolKind(
1737 Enum,
1738 ),
1739 detail: "E",
1740 documentation: Documentation(
1741 "enum docs",
1742 ),
1743 },
1744 ]
1745 "#]],
1746 )
1747 }
1748
1749 #[test]
1750 fn dont_render_attrs() {
1751 check(
1752 r#"
1753struct S;
1754impl S {
1755 #[inline]
1756 fn the_method(&self) { }
1757}
1758fn foo(s: S) { s.$0 }
1759"#,
1760 CompletionItemKind::SymbolKind(SymbolKind::Method),
1761 expect![[r#"
1762 [
1763 CompletionItem {
1764 label: "the_method()",
1765 detail_left: None,
1766 detail_right: Some(
1767 "fn(&self)",
1768 ),
1769 source_range: 81..81,
1770 delete: 81..81,
1771 insert: "the_method();$0",
1772 kind: SymbolKind(
1773 Method,
1774 ),
1775 lookup: "the_method",
1776 detail: "fn(&self)",
1777 relevance: CompletionRelevance {
1778 exact_name_match: false,
1779 type_match: None,
1780 is_local: false,
1781 trait_: None,
1782 is_name_already_imported: false,
1783 requires_import: false,
1784 is_private_editable: false,
1785 postfix_match: None,
1786 function: Some(
1787 CompletionRelevanceFn {
1788 has_params: true,
1789 has_self_param: true,
1790 return_type: Other,
1791 },
1792 ),
1793 is_skipping_completion: false,
1794 },
1795 },
1796 ]
1797 "#]],
1798 )
1799 }
1800
1801 #[test]
1802 fn no_call_parens_if_fn_ptr_needed() {
1803 cov_mark::check!(no_call_parens_if_fn_ptr_needed);
1804 check_edit(
1805 "foo",
1806 r#"
1807fn foo(foo: u8, bar: u8) {}
1808struct ManualVtable { f: fn(u8, u8) }
1809
1810fn main() -> ManualVtable {
1811 ManualVtable { f: f$0 }
1812}
1813"#,
1814 r#"
1815fn foo(foo: u8, bar: u8) {}
1816struct ManualVtable { f: fn(u8, u8) }
1817
1818fn main() -> ManualVtable {
1819 ManualVtable { f: foo }
1820}
1821"#,
1822 );
1823 check_edit(
1824 "type",
1825 r#"
1826struct RawIdentTable { r#type: u32 }
1827
1828fn main() -> RawIdentTable {
1829 RawIdentTable { t$0: 42 }
1830}
1831"#,
1832 r#"
1833struct RawIdentTable { r#type: u32 }
1834
1835fn main() -> RawIdentTable {
1836 RawIdentTable { r#type: 42 }
1837}
1838"#,
1839 );
1840 }
1841
1842 #[test]
1843 fn no_parens_in_use_item() {
1844 check_edit(
1845 "foo",
1846 r#"
1847mod m { pub fn foo() {} }
1848use crate::m::f$0;
1849"#,
1850 r#"
1851mod m { pub fn foo() {} }
1852use crate::m::foo;
1853"#,
1854 );
1855 }
1856
1857 #[test]
1858 fn no_parens_in_call() {
1859 check_edit(
1860 "foo",
1861 r#"
1862fn foo(x: i32) {}
1863fn main() { f$0(); }
1864"#,
1865 r#"
1866fn foo(x: i32) {}
1867fn main() { foo(); }
1868"#,
1869 );
1870 check_edit(
1871 "foo",
1872 r#"
1873struct Foo;
1874impl Foo { fn foo(&self){} }
1875fn f(foo: &Foo) { foo.f$0(); }
1876"#,
1877 r#"
1878struct Foo;
1879impl Foo { fn foo(&self){} }
1880fn f(foo: &Foo) { foo.foo(); }
1881"#,
1882 );
1883 }
1884
1885 #[test]
1886 fn inserts_angle_brackets_for_generics() {
1887 cov_mark::check!(inserts_angle_brackets_for_generics);
1888 check_edit(
1889 "Vec",
1890 r#"
1891struct Vec<T> {}
1892fn foo(xs: Ve$0)
1893"#,
1894 r#"
1895struct Vec<T> {}
1896fn foo(xs: Vec<$0>)
1897"#,
1898 );
1899 check_edit(
1900 "Vec",
1901 r#"
1902type Vec<T> = (T,);
1903fn foo(xs: Ve$0)
1904"#,
1905 r#"
1906type Vec<T> = (T,);
1907fn foo(xs: Vec<$0>)
1908"#,
1909 );
1910 check_edit(
1911 "Vec",
1912 r#"
1913struct Vec<T = i128> {}
1914fn foo(xs: Ve$0)
1915"#,
1916 r#"
1917struct Vec<T = i128> {}
1918fn foo(xs: Vec)
1919"#,
1920 );
1921 check_edit(
1922 "Vec",
1923 r#"
1924struct Vec<T> {}
1925fn foo(xs: Ve$0<i128>)
1926"#,
1927 r#"
1928struct Vec<T> {}
1929fn foo(xs: Vec<i128>)
1930"#,
1931 );
1932 }
1933
1934 #[test]
1935 fn active_param_relevance() {
1936 check_relevance(
1937 r#"
1938struct S { foo: i64, bar: u32, baz: u32 }
1939fn test(bar: u32) { }
1940fn foo(s: S) { test(s.$0) }
1941"#,
1942 expect![[r#"
1943 fd bar u32 [type+name]
1944 fd baz u32 [type]
1945 fd foo i64 []
1946 "#]],
1947 );
1948 }
1949
1950 #[test]
1951 fn record_field_relevances() {
1952 check_relevance(
1953 r#"
1954struct A { foo: i64, bar: u32, baz: u32 }
1955struct B { x: (), y: f32, bar: u32 }
1956fn foo(a: A) { B { bar: a.$0 }; }
1957"#,
1958 expect![[r#"
1959 fd bar u32 [type+name]
1960 fd baz u32 [type]
1961 fd foo i64 []
1962 "#]],
1963 )
1964 }
1965
1966 #[test]
1967 fn tuple_field_detail() {
1968 check(
1969 r#"
1970struct S(i32);
1971
1972fn f() -> i32 {
1973 let s = S(0);
1974 s.0$0
1975}
1976"#,
1977 SymbolKind::Field,
1978 expect![[r#"
1979 [
1980 CompletionItem {
1981 label: "0",
1982 detail_left: None,
1983 detail_right: Some(
1984 "i32",
1985 ),
1986 source_range: 56..57,
1987 delete: 56..57,
1988 insert: "0",
1989 kind: SymbolKind(
1990 Field,
1991 ),
1992 detail: "i32",
1993 relevance: CompletionRelevance {
1994 exact_name_match: false,
1995 type_match: Some(
1996 Exact,
1997 ),
1998 is_local: false,
1999 trait_: None,
2000 is_name_already_imported: false,
2001 requires_import: false,
2002 is_private_editable: false,
2003 postfix_match: None,
2004 function: None,
2005 is_skipping_completion: false,
2006 },
2007 },
2008 ]
2009 "#]],
2010 );
2011 }
2012
2013 #[test]
2014 fn record_field_and_call_relevances() {
2015 check_relevance(
2016 r#"
2017struct A { foo: i64, bar: u32, baz: u32 }
2018struct B { x: (), y: f32, bar: u32 }
2019fn f(foo: i64) { }
2020fn foo(a: A) { B { bar: f(a.$0) }; }
2021"#,
2022 expect![[r#"
2023 fd foo i64 [type+name]
2024 fd bar u32 []
2025 fd baz u32 []
2026 "#]],
2027 );
2028 check_relevance(
2029 r#"
2030struct A { foo: i64, bar: u32, baz: u32 }
2031struct B { x: (), y: f32, bar: u32 }
2032fn f(foo: i64) { }
2033fn foo(a: A) { f(B { bar: a.$0 }); }
2034"#,
2035 expect![[r#"
2036 fd bar u32 [type+name]
2037 fd baz u32 [type]
2038 fd foo i64 []
2039 "#]],
2040 );
2041 }
2042
2043 #[test]
2044 fn prioritize_exact_ref_match() {
2045 check_relevance(
2046 r#"
2047struct WorldSnapshot { _f: () };
2048fn go(world: &WorldSnapshot) { go(w$0) }
2049"#,
2050 expect![[r#"
2051 lc world &WorldSnapshot [type+name+local]
2052 ex world [type]
2053 st WorldSnapshot {…} WorldSnapshot { _f: () } []
2054 st &WorldSnapshot {…} [type]
2055 st WorldSnapshot WorldSnapshot []
2056 st &WorldSnapshot [type]
2057 fn go(…) fn(&WorldSnapshot) []
2058 "#]],
2059 );
2060 }
2061
2062 #[test]
2063 fn prioritize_mutable_ref_as_immutable_ref_match() {
2064 check_relevance(
2065 r#"fn foo(r: &mut i32) -> &i32 { $0 }"#,
2066 expect![[r#"
2067 lc r &mut i32 [type+local]
2068 fn foo(…) fn(&mut i32) -> &i32 [type]
2069 "#]],
2070 );
2071 }
2072
2073 #[test]
2074 fn too_many_arguments() {
2075 cov_mark::check!(too_many_arguments);
2076 check_relevance(
2077 r#"
2078struct Foo;
2079fn f(foo: &Foo) { f(foo, w$0) }
2080"#,
2081 expect![[r#"
2082 lc foo &Foo [local]
2083 st Foo Foo []
2084 fn f(…) fn(&Foo) []
2085 "#]],
2086 );
2087 }
2088
2089 #[test]
2090 fn score_fn_type_and_name_match() {
2091 check_relevance(
2092 r#"
2093struct A { bar: u8 }
2094fn baz() -> u8 { 0 }
2095fn bar() -> u8 { 0 }
2096fn f() { A { bar: b$0 }; }
2097"#,
2098 expect![[r#"
2099 fn bar() fn() -> u8 [type+name]
2100 ex bar() [type]
2101 fn baz() fn() -> u8 [type]
2102 ex baz() [type]
2103 st A A []
2104 fn f() fn() []
2105 "#]],
2106 );
2107 }
2108
2109 #[test]
2110 fn score_method_type_and_name_match() {
2111 check_relevance(
2112 r#"
2113fn baz(aaa: u32){}
2114struct Foo;
2115impl Foo {
2116fn aaa(&self) -> u32 { 0 }
2117fn bbb(&self) -> u32 { 0 }
2118fn ccc(&self) -> u64 { 0 }
2119}
2120fn f() {
2121 baz(Foo.$0
2122}
2123"#,
2124 expect![[r#"
2125 me aaa() fn(&self) -> u32 [type+name]
2126 me bbb() fn(&self) -> u32 [type]
2127 me ccc() fn(&self) -> u64 []
2128 "#]],
2129 );
2130 }
2131
2132 #[test]
2133 fn score_method_name_match_only() {
2134 check_relevance(
2135 r#"
2136fn baz(aaa: u32){}
2137struct Foo;
2138impl Foo {
2139fn aaa(&self) -> u64 { 0 }
2140}
2141fn f() {
2142 baz(Foo.$0
2143}
2144"#,
2145 expect![[r#"
2146 me aaa() fn(&self) -> u64 [name]
2147 "#]],
2148 );
2149 }
2150
2151 #[test]
2152 fn test_avoid_redundant_suggestion() {
2153 check_relevance(
2154 r#"
2155struct aa([u8]);
2156
2157impl aa {
2158 fn from_bytes(bytes: &[u8]) -> &Self {
2159 unsafe { &*(bytes as *const [u8] as *const aa) }
2160 }
2161}
2162
2163fn bb()-> &'static aa {
2164 let bytes = b"hello";
2165 aa::$0
2166}
2167"#,
2168 expect![[r#"
2169 ex bb() [type]
2170 fn from_bytes(…) fn(&[u8]) -> &aa [type_could_unify]
2171 "#]],
2172 );
2173 }
2174
2175 #[test]
2176 fn suggest_ref_mut() {
2177 cov_mark::check!(suggest_ref);
2178 check_relevance(
2179 r#"
2180struct S;
2181fn foo(s: &mut S) {}
2182fn main() {
2183 let mut s = S;
2184 foo($0);
2185}
2186 "#,
2187 expect![[r#"
2188 lc s S [name+local]
2189 lc &mut s [type+name+local]
2190 st S S []
2191 st &mut S [type]
2192 st S S []
2193 st &mut S [type]
2194 fn foo(…) fn(&mut S) []
2195 fn main() fn() []
2196 "#]],
2197 );
2198 check_relevance(
2199 r#"
2200struct S;
2201fn foo(s: &mut S) {}
2202fn main() {
2203 let mut s = S;
2204 foo(&mut $0);
2205}
2206 "#,
2207 expect![[r#"
2208 lc s S [type+name+local]
2209 st S S [type]
2210 st S S [type]
2211 ex S [type]
2212 ex s [type]
2213 fn foo(…) fn(&mut S) []
2214 fn main() fn() []
2215 "#]],
2216 );
2217 check_relevance(
2218 r#"
2219struct S;
2220fn foo(s: &mut S) {}
2221fn main() {
2222 let mut ssss = S;
2223 foo(&mut s$0);
2224}
2225 "#,
2226 expect![[r#"
2227 st S S [type]
2228 lc ssss S [type+local]
2229 st S S [type]
2230 ex S [type]
2231 ex ssss [type]
2232 fn foo(…) fn(&mut S) []
2233 fn main() fn() []
2234 "#]],
2235 );
2236 check_relevance(
2237 r#"
2238struct S;
2239fn foo(s: &&S) {}
2240fn main() {
2241 let mut ssss = &S;
2242 foo($0);
2243}
2244 "#,
2245 expect![[r#"
2246 st S S []
2247 lc ssss &S [local]
2248 lc &ssss [type+local]
2249 st S S []
2250 fn foo(…) fn(&&S) []
2251 fn main() fn() []
2252 "#]],
2253 );
2254 }
2255
2256 #[test]
2257 fn suggest_deref_copy() {
2258 cov_mark::check!(suggest_deref);
2259 check_relevance(
2260 r#"
2261//- minicore: copy
2262struct Foo;
2263
2264impl Copy for Foo {}
2265impl Clone for Foo {
2266 fn clone(&self) -> Self { *self }
2267}
2268
2269fn bar(x: Foo) {}
2270
2271fn main() {
2272 let foo = &Foo;
2273 bar($0);
2274}
2275"#,
2276 expect![[r#"
2277 st Foo Foo [type]
2278 st Foo Foo [type]
2279 ex Foo [type]
2280 lc foo &Foo [local]
2281 lc *foo [type+local]
2282 tt Clone []
2283 tt Copy []
2284 fn bar(…) fn(Foo) []
2285 md core []
2286 fn main() fn() []
2287 "#]],
2288 );
2289 }
2290
2291 #[test]
2292 fn suggest_deref_trait() {
2293 check_relevance(
2294 r#"
2295//- minicore: deref
2296struct S;
2297struct T(S);
2298
2299impl core::ops::Deref for T {
2300 type Target = S;
2301
2302 fn deref(&self) -> &Self::Target {
2303 &self.0
2304 }
2305}
2306
2307fn foo(s: &S) {}
2308
2309fn main() {
2310 let t = T(S);
2311 let m = 123;
2312
2313 foo($0);
2314}
2315 "#,
2316 expect![[r#"
2317 st S S []
2318 st &S [type]
2319 ex core::ops::Deref::deref(&t) [type_could_unify]
2320 lc m i32 [local]
2321 lc t T [local]
2322 lc &t [type+local]
2323 st S S []
2324 st &S [type]
2325 st T T []
2326 st &T [type]
2327 md core []
2328 fn foo(…) fn(&S) []
2329 fn main() fn() []
2330 "#]],
2331 )
2332 }
2333
2334 #[test]
2335 fn suggest_deref_mut() {
2336 check_relevance(
2337 r#"
2338//- minicore: deref_mut
2339struct S;
2340struct T(S);
2341
2342impl core::ops::Deref for T {
2343 type Target = S;
2344
2345 fn deref(&self) -> &Self::Target {
2346 &self.0
2347 }
2348}
2349
2350impl core::ops::DerefMut for T {
2351 fn deref_mut(&mut self) -> &mut Self::Target {
2352 &mut self.0
2353 }
2354}
2355
2356fn foo(s: &mut S) {}
2357
2358fn main() {
2359 let t = T(S);
2360 let m = 123;
2361
2362 foo($0);
2363}
2364 "#,
2365 expect![[r#"
2366 st S S []
2367 st &mut S [type]
2368 ex core::ops::DerefMut::deref_mut(&mut t) [type_could_unify]
2369 lc m i32 [local]
2370 lc t T [local]
2371 lc &mut t [type+local]
2372 st S S []
2373 st &mut S [type]
2374 st T T []
2375 st &mut T [type]
2376 md core []
2377 fn foo(…) fn(&mut S) []
2378 fn main() fn() []
2379 "#]],
2380 )
2381 }
2382
2383 #[test]
2384 fn locals() {
2385 check_relevance(
2386 r#"
2387fn foo(bar: u32) {
2388 let baz = 0;
2389
2390 f$0
2391}
2392"#,
2393 expect![[r#"
2394 lc bar u32 [local]
2395 lc baz i32 [local]
2396 fn foo(…) fn(u32) []
2397 "#]],
2398 );
2399 }
2400
2401 #[test]
2402 fn enum_owned() {
2403 check_relevance(
2404 r#"
2405enum Foo { A, B }
2406fn foo() {
2407 bar($0);
2408}
2409fn bar(t: Foo) {}
2410"#,
2411 expect![[r#"
2412 ev Foo::A Foo::A [type]
2413 ev Foo::B Foo::B [type]
2414 en Foo Foo [type]
2415 ex Foo::A [type]
2416 ex Foo::B [type]
2417 fn bar(…) fn(Foo) []
2418 fn foo() fn() []
2419 "#]],
2420 );
2421 }
2422
2423 #[test]
2424 fn enum_ref() {
2425 check_relevance(
2426 r#"
2427enum Foo { A, B }
2428fn foo() {
2429 bar($0);
2430}
2431fn bar(t: &Foo) {}
2432"#,
2433 expect![[r#"
2434 ev Foo::A Foo::A []
2435 ev &Foo::A [type]
2436 ev Foo::B Foo::B []
2437 ev &Foo::B [type]
2438 en Foo Foo []
2439 en &Foo [type]
2440 fn bar(…) fn(&Foo) []
2441 fn foo() fn() []
2442 "#]],
2443 );
2444 }
2445
2446 #[test]
2447 fn suggest_deref_fn_ret() {
2448 check_relevance(
2449 r#"
2450//- minicore: deref
2451struct S;
2452struct T(S);
2453
2454impl core::ops::Deref for T {
2455 type Target = S;
2456
2457 fn deref(&self) -> &Self::Target {
2458 &self.0
2459 }
2460}
2461
2462fn foo(s: &S) {}
2463fn bar() -> T {}
2464
2465fn main() {
2466 foo($0);
2467}
2468"#,
2469 expect![[r#"
2470 st S S []
2471 st &S [type]
2472 ex core::ops::Deref::deref(&bar()) [type_could_unify]
2473 st S S []
2474 st &S [type]
2475 st T T []
2476 st &T [type]
2477 fn bar() fn() -> T []
2478 fn &bar() [type]
2479 md core []
2480 fn foo(…) fn(&S) []
2481 fn main() fn() []
2482 "#]],
2483 )
2484 }
2485
2486 #[test]
2487 fn op_function_relevances() {
2488 check_relevance(
2489 r#"
2490#[lang = "sub"]
2491trait Sub {
2492 fn sub(self, other: Self) -> Self { self }
2493}
2494impl Sub for u32 {}
2495fn foo(a: u32) { a.$0 }
2496"#,
2497 expect![[r#"
2498 me sub(…) fn(self, Self) -> Self [op_method]
2499 "#]],
2500 );
2501 check_relevance(
2502 r#"
2503struct Foo;
2504impl Foo {
2505 fn new() -> Self {}
2506}
2507#[lang = "eq"]
2508pub trait PartialEq<Rhs: ?Sized = Self> {
2509 fn eq(&self, other: &Rhs) -> bool;
2510 fn ne(&self, other: &Rhs) -> bool;
2511}
2512
2513impl PartialEq for Foo {}
2514fn main() {
2515 Foo::$0
2516}
2517"#,
2518 expect![[r#"
2519 fn new() fn() -> Foo []
2520 me eq(…) fn(&self, &Rhs) -> bool [op_method]
2521 me ne(…) fn(&self, &Rhs) -> bool [op_method]
2522 "#]],
2523 );
2524 }
2525
2526 #[test]
2527 fn constructor_order_simple() {
2528 check_relevance(
2529 r#"
2530struct Foo;
2531struct Other;
2532struct Option<T>(T);
2533
2534impl Foo {
2535 fn fn_ctr() -> Foo { unimplemented!() }
2536 fn fn_another(n: u32) -> Other { unimplemented!() }
2537 fn fn_ctr_self() -> Option<Self> { unimplemented!() }
2538}
2539
2540fn test() {
2541 let a = Foo::$0;
2542}
2543"#,
2544 expect![[r#"
2545 fn fn_ctr() fn() -> Foo [type_could_unify]
2546 fn fn_ctr_self() fn() -> Option<Foo> [type_could_unify]
2547 fn fn_another(…) fn(u32) -> Other [type_could_unify]
2548 "#]],
2549 );
2550 }
2551
2552 #[test]
2553 fn constructor_order_kind() {
2554 check_function_relevance(
2555 r#"
2556struct Foo;
2557struct Bar;
2558struct Option<T>(T);
2559enum Result<T, E> { Ok(T), Err(E) };
2560
2561impl Foo {
2562 fn fn_ctr(&self) -> Foo { unimplemented!() }
2563 fn fn_ctr_with_args(&self, n: u32) -> Foo { unimplemented!() }
2564 fn fn_another(&self, n: u32) -> Bar { unimplemented!() }
2565 fn fn_ctr_wrapped(&self, ) -> Option<Self> { unimplemented!() }
2566 fn fn_ctr_wrapped_2(&self, ) -> Result<Self, Bar> { unimplemented!() }
2567 fn fn_ctr_wrapped_3(&self, ) -> Result<Bar, Self> { unimplemented!() } // Self is not the first type
2568 fn fn_ctr_wrapped_with_args(&self, m: u32) -> Option<Self> { unimplemented!() }
2569 fn fn_another_unit(&self) { unimplemented!() }
2570}
2571
2572fn test() {
2573 let a = self::Foo::$0;
2574}
2575"#,
2576 expect![[r#"
2577 [
2578 (
2579 "fn(&self, u32) -> Bar",
2580 Some(
2581 CompletionRelevanceFn {
2582 has_params: true,
2583 has_self_param: true,
2584 return_type: Other,
2585 },
2586 ),
2587 ),
2588 (
2589 "fn(&self)",
2590 Some(
2591 CompletionRelevanceFn {
2592 has_params: true,
2593 has_self_param: true,
2594 return_type: Other,
2595 },
2596 ),
2597 ),
2598 (
2599 "fn(&self) -> Foo",
2600 Some(
2601 CompletionRelevanceFn {
2602 has_params: true,
2603 has_self_param: true,
2604 return_type: DirectConstructor,
2605 },
2606 ),
2607 ),
2608 (
2609 "fn(&self, u32) -> Foo",
2610 Some(
2611 CompletionRelevanceFn {
2612 has_params: true,
2613 has_self_param: true,
2614 return_type: DirectConstructor,
2615 },
2616 ),
2617 ),
2618 (
2619 "fn(&self) -> Option<Foo>",
2620 Some(
2621 CompletionRelevanceFn {
2622 has_params: true,
2623 has_self_param: true,
2624 return_type: Constructor,
2625 },
2626 ),
2627 ),
2628 (
2629 "fn(&self) -> Result<Foo, Bar>",
2630 Some(
2631 CompletionRelevanceFn {
2632 has_params: true,
2633 has_self_param: true,
2634 return_type: Constructor,
2635 },
2636 ),
2637 ),
2638 (
2639 "fn(&self) -> Result<Bar, Foo>",
2640 Some(
2641 CompletionRelevanceFn {
2642 has_params: true,
2643 has_self_param: true,
2644 return_type: Constructor,
2645 },
2646 ),
2647 ),
2648 (
2649 "fn(&self, u32) -> Option<Foo>",
2650 Some(
2651 CompletionRelevanceFn {
2652 has_params: true,
2653 has_self_param: true,
2654 return_type: Constructor,
2655 },
2656 ),
2657 ),
2658 ]
2659 "#]],
2660 );
2661 }
2662
2663 #[test]
2664 fn constructor_order_relevance() {
2665 check_relevance(
2666 r#"
2667struct Foo;
2668struct FooBuilder;
2669struct Result<T>(T);
2670
2671impl Foo {
2672 fn fn_no_ret(&self) {}
2673 fn fn_ctr_with_args(input: u32) -> Foo { unimplemented!() }
2674 fn fn_direct_ctr() -> Self { unimplemented!() }
2675 fn fn_ctr() -> Result<Self> { unimplemented!() }
2676 fn fn_other() -> Result<u32> { unimplemented!() }
2677 fn fn_builder() -> FooBuilder { unimplemented!() }
2678}
2679
2680fn test() {
2681 let a = self::Foo::$0;
2682}
2683"#,
2684 expect![[r#"
2691 fn fn_direct_ctr() fn() -> Foo [type_could_unify]
2692 fn fn_ctr_with_args(…) fn(u32) -> Foo [type_could_unify]
2693 fn fn_builder() fn() -> FooBuilder [type_could_unify]
2694 fn fn_ctr() fn() -> Result<Foo> [type_could_unify]
2695 me fn_no_ret(…) fn(&self) [type_could_unify]
2696 fn fn_other() fn() -> Result<u32> [type_could_unify]
2697 "#]],
2698 );
2699
2700 }
2702
2703 #[test]
2704 fn function_relevance_generic_1() {
2705 check_relevance(
2706 r#"
2707struct Foo<T: Default>(T);
2708struct FooBuilder;
2709struct Option<T>(T);
2710enum Result<T, E>{Ok(T), Err(E)};
2711
2712impl<T: Default> Foo<T> {
2713 fn fn_returns_unit(&self) {}
2714 fn fn_ctr_with_args(input: T) -> Foo<T> { unimplemented!() }
2715 fn fn_direct_ctr() -> Self { unimplemented!() }
2716 fn fn_ctr_wrapped() -> Option<Self> { unimplemented!() }
2717 fn fn_ctr_wrapped_2() -> Result<Self, u32> { unimplemented!() }
2718 fn fn_other() -> Option<u32> { unimplemented!() }
2719 fn fn_builder() -> FooBuilder { unimplemented!() }
2720}
2721
2722fn test() {
2723 let a = self::Foo::<u32>::$0;
2724}
2725 "#,
2726 expect![[r#"
2727 fn fn_direct_ctr() fn() -> Foo<T> [type_could_unify]
2728 fn fn_ctr_with_args(…) fn(T) -> Foo<T> [type_could_unify]
2729 fn fn_builder() fn() -> FooBuilder [type_could_unify]
2730 fn fn_ctr_wrapped() fn() -> Option<Foo<T>> [type_could_unify]
2731 fn fn_ctr_wrapped_2() fn() -> Result<Foo<T>, u32> [type_could_unify]
2732 fn fn_other() fn() -> Option<u32> [type_could_unify]
2733 me fn_returns_unit(…) fn(&self) [type_could_unify]
2734 "#]],
2735 );
2736 }
2737
2738 #[test]
2739 fn function_relevance_generic_2() {
2740 check_relevance(
2742 r#"
2743struct Foo<T: Default>(T);
2744struct FooBuilder;
2745struct Option<T>(T);
2746enum Result<T, E>{Ok(T), Err(E)};
2747
2748impl<T: Default> Foo<T> {
2749 fn fn_no_ret(&self) {}
2750 fn fn_ctr_with_args(input: T) -> Foo<T> { unimplemented!() }
2751 fn fn_direct_ctr() -> Self { unimplemented!() }
2752 fn fn_ctr() -> Option<Self> { unimplemented!() }
2753 fn fn_ctr2() -> Result<Self, u32> { unimplemented!() }
2754 fn fn_other() -> Option<u32> { unimplemented!() }
2755 fn fn_builder() -> FooBuilder { unimplemented!() }
2756}
2757
2758fn test() {
2759 let a : Res<Foo<u32>> = Foo::$0;
2760}
2761 "#,
2762 expect![[r#"
2763 fn fn_direct_ctr() fn() -> Foo<T> [type_could_unify]
2764 fn fn_ctr_with_args(…) fn(T) -> Foo<T> [type_could_unify]
2765 fn fn_builder() fn() -> FooBuilder [type_could_unify]
2766 fn fn_ctr() fn() -> Option<Foo<T>> [type_could_unify]
2767 fn fn_ctr2() fn() -> Result<Foo<T>, u32> [type_could_unify]
2768 me fn_no_ret(…) fn(&self) [type_could_unify]
2769 fn fn_other() fn() -> Option<u32> [type_could_unify]
2770 "#]],
2771 );
2772 }
2773
2774 #[test]
2775 fn struct_field_method_ref() {
2776 check_kinds(
2777 r#"
2778struct Foo { bar: u32, qux: fn() }
2779impl Foo { fn baz(&self) -> u32 { 0 } }
2780
2781fn foo(f: Foo) { let _: &u32 = f.b$0 }
2782"#,
2783 &[
2784 CompletionItemKind::SymbolKind(SymbolKind::Method),
2785 CompletionItemKind::SymbolKind(SymbolKind::Field),
2786 ],
2787 expect![[r#"
2788 [
2789 CompletionItem {
2790 label: "baz()",
2791 detail_left: None,
2792 detail_right: Some(
2793 "fn(&self) -> u32",
2794 ),
2795 source_range: 109..110,
2796 delete: 109..110,
2797 insert: "baz()$0",
2798 kind: SymbolKind(
2799 Method,
2800 ),
2801 lookup: "baz",
2802 detail: "fn(&self) -> u32",
2803 relevance: CompletionRelevance {
2804 exact_name_match: false,
2805 type_match: None,
2806 is_local: false,
2807 trait_: None,
2808 is_name_already_imported: false,
2809 requires_import: false,
2810 is_private_editable: false,
2811 postfix_match: None,
2812 function: Some(
2813 CompletionRelevanceFn {
2814 has_params: true,
2815 has_self_param: true,
2816 return_type: Other,
2817 },
2818 ),
2819 is_skipping_completion: false,
2820 },
2821 ref_match: "&@107",
2822 },
2823 CompletionItem {
2824 label: "bar",
2825 detail_left: None,
2826 detail_right: Some(
2827 "u32",
2828 ),
2829 source_range: 109..110,
2830 delete: 109..110,
2831 insert: "bar",
2832 kind: SymbolKind(
2833 Field,
2834 ),
2835 detail: "u32",
2836 ref_match: "&@107",
2837 },
2838 CompletionItem {
2839 label: "qux",
2840 detail_left: None,
2841 detail_right: Some(
2842 "fn()",
2843 ),
2844 source_range: 109..110,
2845 text_edit: TextEdit {
2846 indels: [
2847 Indel {
2848 insert: "(",
2849 delete: 107..107,
2850 },
2851 Indel {
2852 insert: "qux)()",
2853 delete: 109..110,
2854 },
2855 ],
2856 annotation: None,
2857 },
2858 kind: SymbolKind(
2859 Field,
2860 ),
2861 detail: "fn()",
2862 },
2863 ]
2864 "#]],
2865 );
2866 }
2867
2868 #[test]
2869 fn expected_fn_type_ref() {
2870 check_kinds(
2871 r#"
2872struct S { field: fn() }
2873
2874fn foo() {
2875 let foo: fn() = S { fields: || {}}.fi$0;
2876}
2877"#,
2878 &[CompletionItemKind::SymbolKind(SymbolKind::Field)],
2879 expect![[r#"
2880 [
2881 CompletionItem {
2882 label: "field",
2883 detail_left: None,
2884 detail_right: Some(
2885 "fn()",
2886 ),
2887 source_range: 76..78,
2888 delete: 76..78,
2889 insert: "field",
2890 kind: SymbolKind(
2891 Field,
2892 ),
2893 detail: "fn()",
2894 relevance: CompletionRelevance {
2895 exact_name_match: false,
2896 type_match: Some(
2897 Exact,
2898 ),
2899 is_local: false,
2900 trait_: None,
2901 is_name_already_imported: false,
2902 requires_import: false,
2903 is_private_editable: false,
2904 postfix_match: None,
2905 function: None,
2906 is_skipping_completion: false,
2907 },
2908 },
2909 ]
2910 "#]],
2911 )
2912 }
2913
2914 #[test]
2915 fn qualified_path_ref() {
2916 check_kinds(
2917 r#"
2918struct S;
2919
2920struct T;
2921impl T {
2922 fn foo() -> S {}
2923}
2924
2925fn bar(s: &S) {}
2926
2927fn main() {
2928 bar(T::$0);
2929}
2930"#,
2931 &[CompletionItemKind::SymbolKind(SymbolKind::Function)],
2932 expect![[r#"
2933 [
2934 CompletionItem {
2935 label: "foo()",
2936 detail_left: None,
2937 detail_right: Some(
2938 "fn() -> S",
2939 ),
2940 source_range: 95..95,
2941 delete: 95..95,
2942 insert: "foo()$0",
2943 kind: SymbolKind(
2944 Function,
2945 ),
2946 lookup: "foo",
2947 detail: "fn() -> S",
2948 relevance: CompletionRelevance {
2949 exact_name_match: false,
2950 type_match: None,
2951 is_local: false,
2952 trait_: None,
2953 is_name_already_imported: false,
2954 requires_import: false,
2955 is_private_editable: false,
2956 postfix_match: None,
2957 function: Some(
2958 CompletionRelevanceFn {
2959 has_params: false,
2960 has_self_param: false,
2961 return_type: Other,
2962 },
2963 ),
2964 is_skipping_completion: false,
2965 },
2966 ref_match: "&@92",
2967 },
2968 ]
2969 "#]],
2970 );
2971 }
2972
2973 #[test]
2974 fn generic_enum() {
2975 check_relevance(
2976 r#"
2977enum Foo<T> { A(T), B }
2978// bar() should not be an exact type match
2979// because the generic parameters are different
2980fn bar() -> Foo<u8> { Foo::B }
2981// FIXME baz() should be an exact type match
2982// because the types could unify, but it currently
2983// is not. This is due to the T here being
2984// TyKind::Placeholder rather than TyKind::Missing.
2985fn baz<T>() -> Foo<T> { Foo::B }
2986fn foo() {
2987 let foo: Foo<u32> = Foo::B;
2988 let _: Foo<u32> = f$0;
2989}
2990"#,
2991 expect![[r#"
2992 ev Foo::B Foo::B [type_could_unify]
2993 ev Foo::A(…) Foo::A(T) [type_could_unify]
2994 lc foo Foo<u32> [type+local]
2995 ex Foo::B [type]
2996 ex foo [type]
2997 en Foo Foo<{unknown}> [type_could_unify]
2998 fn bar() fn() -> Foo<u8> []
2999 fn baz() fn() -> Foo<T> []
3000 fn foo() fn() []
3001 "#]],
3002 );
3003 }
3004
3005 #[test]
3006 fn postfix_exact_match_is_high_priority() {
3007 cov_mark::check!(postfix_exact_match_is_high_priority);
3008 check_relevance_for_kinds(
3009 r#"
3010mod ops {
3011 pub trait Not {
3012 type Output;
3013 fn not(self) -> Self::Output;
3014 }
3015
3016 impl Not for bool {
3017 type Output = bool;
3018 fn not(self) -> bool { if self { false } else { true }}
3019 }
3020}
3021
3022fn main() {
3023 let _: bool = (9 > 2).not$0;
3024}
3025 "#,
3026 &[CompletionItemKind::Snippet, CompletionItemKind::SymbolKind(SymbolKind::Method)],
3027 expect![[r#"
3028 sn not !expr [snippet]
3029 sn box Box::new(expr) []
3030 sn call function(expr) []
3031 sn const const {} []
3032 sn dbg dbg!(expr) []
3033 sn dbgr dbg!(&expr) []
3034 sn deref *expr []
3035 sn if if expr {} []
3036 sn match match expr {} []
3037 sn ref &expr []
3038 sn refm &mut expr []
3039 sn return return expr []
3040 sn unsafe unsafe {} []
3041 sn while while expr {} []
3042 me not() fn(self) -> <Self as Not>::Output [requires_import]
3043 "#]],
3044 );
3045 }
3046
3047 #[test]
3048 fn postfix_inexact_match_is_low_priority() {
3049 cov_mark::check!(postfix_inexact_match_is_low_priority);
3050 check_relevance_for_kinds(
3051 r#"
3052struct S;
3053impl S {
3054 fn f(&self) {}
3055}
3056fn main() {
3057 S.$0
3058}
3059 "#,
3060 &[CompletionItemKind::Snippet, CompletionItemKind::SymbolKind(SymbolKind::Method)],
3061 expect![[r#"
3062 me f() fn(&self) []
3063 sn box Box::new(expr) []
3064 sn call function(expr) []
3065 sn const const {} []
3066 sn dbg dbg!(expr) []
3067 sn dbgr dbg!(&expr) []
3068 sn deref *expr []
3069 sn let let []
3070 sn letm let mut []
3071 sn match match expr {} []
3072 sn ref &expr []
3073 sn refm &mut expr []
3074 sn return return expr []
3075 sn unsafe unsafe {} []
3076 "#]],
3077 );
3078 }
3079
3080 #[test]
3081 fn flyimport_reduced_relevance() {
3082 check_relevance(
3083 r#"
3084mod std {
3085 pub mod io {
3086 pub trait BufRead {}
3087 pub struct BufReader;
3088 pub struct BufWriter;
3089 }
3090}
3091struct Buffer;
3092
3093fn f() {
3094 Buf$0
3095}
3096"#,
3097 expect![[r#"
3098 st Buffer Buffer []
3099 fn f() fn() []
3100 md std []
3101 tt BufRead [requires_import]
3102 st BufReader BufReader [requires_import]
3103 st BufWriter BufWriter [requires_import]
3104 "#]],
3105 );
3106 }
3107
3108 #[test]
3109 fn completes_struct_with_raw_identifier() {
3110 check_edit(
3111 "type",
3112 r#"
3113mod m { pub struct r#type {} }
3114fn main() {
3115 let r#type = m::t$0;
3116}
3117"#,
3118 r#"
3119mod m { pub struct r#type {} }
3120fn main() {
3121 let r#type = m::r#type;
3122}
3123"#,
3124 )
3125 }
3126
3127 #[test]
3128 fn completes_fn_with_raw_identifier() {
3129 check_edit(
3130 "type",
3131 r#"
3132mod m { pub fn r#type {} }
3133fn main() {
3134 m::t$0
3135}
3136"#,
3137 r#"
3138mod m { pub fn r#type {} }
3139fn main() {
3140 m::r#type();$0
3141}
3142"#,
3143 )
3144 }
3145
3146 #[test]
3147 fn completes_macro_with_raw_identifier() {
3148 check_edit(
3149 "let!",
3150 r#"
3151macro_rules! r#let { () => {} }
3152fn main() {
3153 $0
3154}
3155"#,
3156 r#"
3157macro_rules! r#let { () => {} }
3158fn main() {
3159 r#let!($0)
3160}
3161"#,
3162 )
3163 }
3164
3165 #[test]
3166 fn completes_variant_with_raw_identifier() {
3167 check_edit(
3168 "type",
3169 r#"
3170enum A { r#type }
3171fn main() {
3172 let a = A::t$0
3173}
3174"#,
3175 r#"
3176enum A { r#type }
3177fn main() {
3178 let a = A::r#type$0
3179}
3180"#,
3181 )
3182 }
3183
3184 #[test]
3185 fn completes_field_with_raw_identifier() {
3186 check_edit(
3187 "fn",
3188 r#"
3189mod r#type {
3190 pub struct r#struct {
3191 pub r#fn: u32
3192 }
3193}
3194
3195fn main() {
3196 let a = r#type::r#struct {};
3197 a.$0
3198}
3199"#,
3200 r#"
3201mod r#type {
3202 pub struct r#struct {
3203 pub r#fn: u32
3204 }
3205}
3206
3207fn main() {
3208 let a = r#type::r#struct {};
3209 a.r#fn
3210}
3211"#,
3212 )
3213 }
3214
3215 #[test]
3216 fn completes_const_with_raw_identifier() {
3217 check_edit(
3218 "type",
3219 r#"
3220struct r#struct {}
3221impl r#struct { pub const r#type: u8 = 1; }
3222fn main() {
3223 r#struct::t$0
3224}
3225"#,
3226 r#"
3227struct r#struct {}
3228impl r#struct { pub const r#type: u8 = 1; }
3229fn main() {
3230 r#struct::r#type
3231}
3232"#,
3233 )
3234 }
3235
3236 #[test]
3237 fn completes_type_alias_with_raw_identifier() {
3238 check_edit(
3239 "type type",
3240 r#"
3241struct r#struct {}
3242trait r#trait { type r#type; }
3243impl r#trait for r#struct { type t$0 }
3244"#,
3245 r#"
3246struct r#struct {}
3247trait r#trait { type r#type; }
3248impl r#trait for r#struct { type r#type = $0; }
3249"#,
3250 )
3251 }
3252
3253 #[test]
3254 fn field_access_includes_self() {
3255 check_edit(
3256 "length",
3257 r#"
3258struct S {
3259 length: i32
3260}
3261
3262impl S {
3263 fn some_fn(&self) {
3264 let l = len$0
3265 }
3266}
3267"#,
3268 r#"
3269struct S {
3270 length: i32
3271}
3272
3273impl S {
3274 fn some_fn(&self) {
3275 let l = self.length
3276 }
3277}
3278"#,
3279 )
3280 }
3281
3282 #[test]
3283 fn field_access_includes_closure_this_param() {
3284 check_edit(
3285 "length",
3286 r#"
3287//- minicore: fn
3288struct S {
3289 length: i32
3290}
3291
3292impl S {
3293 fn pack(&mut self, f: impl FnOnce(&mut Self, i32)) {
3294 self.length += 1;
3295 f(self, 3);
3296 self.length -= 1;
3297 }
3298
3299 fn some_fn(&mut self) {
3300 self.pack(|this, n| len$0);
3301 }
3302}
3303"#,
3304 r#"
3305struct S {
3306 length: i32
3307}
3308
3309impl S {
3310 fn pack(&mut self, f: impl FnOnce(&mut Self, i32)) {
3311 self.length += 1;
3312 f(self, 3);
3313 self.length -= 1;
3314 }
3315
3316 fn some_fn(&mut self) {
3317 self.pack(|this, n| this.length);
3318 }
3319}
3320"#,
3321 )
3322 }
3323
3324 #[test]
3325 fn notable_traits_method_relevance() {
3326 check_kinds(
3327 r#"
3328#[doc(notable_trait)]
3329trait Write {
3330 fn write(&self);
3331 fn flush(&self);
3332}
3333
3334struct Writer;
3335
3336impl Write for Writer {
3337 fn write(&self) {}
3338 fn flush(&self) {}
3339}
3340
3341fn main() {
3342 Writer.$0
3343}
3344"#,
3345 &[
3346 CompletionItemKind::SymbolKind(SymbolKind::Method),
3347 CompletionItemKind::SymbolKind(SymbolKind::Field),
3348 CompletionItemKind::SymbolKind(SymbolKind::Function),
3349 ],
3350 expect![[r#"
3351 [
3352 CompletionItem {
3353 label: "flush()",
3354 detail_left: Some(
3355 "(as Write)",
3356 ),
3357 detail_right: Some(
3358 "fn(&self)",
3359 ),
3360 source_range: 193..193,
3361 delete: 193..193,
3362 insert: "flush();$0",
3363 kind: SymbolKind(
3364 Method,
3365 ),
3366 lookup: "flush",
3367 detail: "fn(&self)",
3368 relevance: CompletionRelevance {
3369 exact_name_match: false,
3370 type_match: None,
3371 is_local: false,
3372 trait_: Some(
3373 CompletionRelevanceTraitInfo {
3374 notable_trait: true,
3375 is_op_method: false,
3376 },
3377 ),
3378 is_name_already_imported: false,
3379 requires_import: false,
3380 is_private_editable: false,
3381 postfix_match: None,
3382 function: None,
3383 is_skipping_completion: false,
3384 },
3385 },
3386 CompletionItem {
3387 label: "write()",
3388 detail_left: Some(
3389 "(as Write)",
3390 ),
3391 detail_right: Some(
3392 "fn(&self)",
3393 ),
3394 source_range: 193..193,
3395 delete: 193..193,
3396 insert: "write();$0",
3397 kind: SymbolKind(
3398 Method,
3399 ),
3400 lookup: "write",
3401 detail: "fn(&self)",
3402 relevance: CompletionRelevance {
3403 exact_name_match: false,
3404 type_match: None,
3405 is_local: false,
3406 trait_: Some(
3407 CompletionRelevanceTraitInfo {
3408 notable_trait: true,
3409 is_op_method: false,
3410 },
3411 ),
3412 is_name_already_imported: false,
3413 requires_import: false,
3414 is_private_editable: false,
3415 postfix_match: None,
3416 function: None,
3417 is_skipping_completion: false,
3418 },
3419 },
3420 ]
3421 "#]],
3422 );
3423 }
3424}