• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! `render` module provides utilities for rendering completion suggestions
2 //! into code pieces that will be presented to user.
3 
4 pub(crate) mod macro_;
5 pub(crate) mod function;
6 pub(crate) mod const_;
7 pub(crate) mod pattern;
8 pub(crate) mod type_alias;
9 pub(crate) mod variant;
10 pub(crate) mod union_literal;
11 pub(crate) mod literal;
12 
13 use hir::{AsAssocItem, HasAttrs, HirDisplay, ScopeDef};
14 use ide_db::{
15     helpers::item_name, imports::import_assets::LocatedImport, RootDatabase, SnippetCap, SymbolKind,
16 };
17 use syntax::{AstNode, SmolStr, SyntaxKind, TextRange};
18 
19 use crate::{
20     context::{DotAccess, PathCompletionCtx, PathKind, PatternContext},
21     item::{Builder, CompletionRelevanceTypeMatch},
22     render::{
23         function::render_fn,
24         literal::render_variant_lit,
25         macro_::{render_macro, render_macro_pat},
26     },
27     CompletionContext, CompletionItem, CompletionItemKind, CompletionRelevance,
28 };
29 /// Interface for data and methods required for items rendering.
30 #[derive(Debug, Clone)]
31 pub(crate) struct RenderContext<'a> {
32     completion: &'a CompletionContext<'a>,
33     is_private_editable: bool,
34     import_to_add: Option<LocatedImport>,
35     doc_aliases: Vec<SmolStr>,
36 }
37 
38 impl<'a> RenderContext<'a> {
new(completion: &'a CompletionContext<'a>) -> RenderContext<'a>39     pub(crate) fn new(completion: &'a CompletionContext<'a>) -> RenderContext<'a> {
40         RenderContext {
41             completion,
42             is_private_editable: false,
43             import_to_add: None,
44             doc_aliases: vec![],
45         }
46     }
47 
private_editable(mut self, private_editable: bool) -> Self48     pub(crate) fn private_editable(mut self, private_editable: bool) -> Self {
49         self.is_private_editable = private_editable;
50         self
51     }
52 
import_to_add(mut self, import_to_add: Option<LocatedImport>) -> Self53     pub(crate) fn import_to_add(mut self, import_to_add: Option<LocatedImport>) -> Self {
54         self.import_to_add = import_to_add;
55         self
56     }
57 
doc_aliases(mut self, doc_aliases: Vec<SmolStr>) -> Self58     pub(crate) fn doc_aliases(mut self, doc_aliases: Vec<SmolStr>) -> Self {
59         self.doc_aliases = doc_aliases;
60         self
61     }
62 
snippet_cap(&self) -> Option<SnippetCap>63     fn snippet_cap(&self) -> Option<SnippetCap> {
64         self.completion.config.snippet_cap
65     }
66 
db(&self) -> &'a RootDatabase67     fn db(&self) -> &'a RootDatabase {
68         self.completion.db
69     }
70 
source_range(&self) -> TextRange71     fn source_range(&self) -> TextRange {
72         self.completion.source_range()
73     }
74 
completion_relevance(&self) -> CompletionRelevance75     fn completion_relevance(&self) -> CompletionRelevance {
76         CompletionRelevance {
77             is_private_editable: self.is_private_editable,
78             requires_import: self.import_to_add.is_some(),
79             ..Default::default()
80         }
81     }
82 
is_immediately_after_macro_bang(&self) -> bool83     fn is_immediately_after_macro_bang(&self) -> bool {
84         self.completion.token.kind() == SyntaxKind::BANG
85             && self
86                 .completion
87                 .token
88                 .parent()
89                 .map_or(false, |it| it.kind() == SyntaxKind::MACRO_CALL)
90     }
91 
is_deprecated(&self, def: impl HasAttrs) -> bool92     fn is_deprecated(&self, def: impl HasAttrs) -> bool {
93         let attrs = def.attrs(self.db());
94         attrs.by_key("deprecated").exists()
95     }
96 
is_deprecated_assoc_item(&self, as_assoc_item: impl AsAssocItem) -> bool97     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                 .containing_trait_or_trait_impl(db)
112                 .map(|trait_| self.is_deprecated(trait_))
113                 .unwrap_or(false)
114     }
115 
116     // FIXME: remove this
docs(&self, def: impl HasAttrs) -> Option<hir::Documentation>117     fn docs(&self, def: impl HasAttrs) -> Option<hir::Documentation> {
118         def.docs(self.db())
119     }
120 }
121 
render_field( ctx: RenderContext<'_>, dot_access: &DotAccess, receiver: Option<hir::Name>, field: hir::Field, ty: &hir::Type, ) -> CompletionItem122 pub(crate) fn render_field(
123     ctx: RenderContext<'_>,
124     dot_access: &DotAccess,
125     receiver: Option<hir::Name>,
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) = (name.unescaped().to_smol_str(), name.to_smol_str());
133     let mut item = CompletionItem::new(
134         SymbolKind::Field,
135         ctx.source_range(),
136         field_with_receiver(db, receiver.as_ref(), &name),
137     );
138     item.set_relevance(CompletionRelevance {
139         type_match: compute_type_match(ctx.completion, ty),
140         exact_name_match: compute_exact_name_match(ctx.completion, name.as_str()),
141         ..CompletionRelevance::default()
142     });
143     item.detail(ty.display(db).to_string())
144         .set_documentation(field.docs(db))
145         .set_deprecated(is_deprecated)
146         .lookup_by(name);
147     item.insert_text(field_with_receiver(db, receiver.as_ref(), &escaped_name));
148     if let Some(receiver) = &dot_access.receiver {
149         if let Some(original) = ctx.completion.sema.original_ast_node(receiver.clone()) {
150             if let Some(ref_match) = compute_ref_match(ctx.completion, ty) {
151                 item.ref_match(ref_match, original.syntax().text_range().start());
152             }
153         }
154     }
155     item.doc_aliases(ctx.doc_aliases);
156     item.build(db)
157 }
158 
field_with_receiver( db: &RootDatabase, receiver: Option<&hir::Name>, field_name: &str, ) -> SmolStr159 fn field_with_receiver(
160     db: &RootDatabase,
161     receiver: Option<&hir::Name>,
162     field_name: &str,
163 ) -> SmolStr {
164     receiver.map_or_else(
165         || field_name.into(),
166         |receiver| format!("{}.{field_name}", receiver.display(db)).into(),
167     )
168 }
169 
render_tuple_field( ctx: RenderContext<'_>, receiver: Option<hir::Name>, field: usize, ty: &hir::Type, ) -> CompletionItem170 pub(crate) fn render_tuple_field(
171     ctx: RenderContext<'_>,
172     receiver: Option<hir::Name>,
173     field: usize,
174     ty: &hir::Type,
175 ) -> CompletionItem {
176     let mut item = CompletionItem::new(
177         SymbolKind::Field,
178         ctx.source_range(),
179         field_with_receiver(ctx.db(), receiver.as_ref(), &field.to_string()),
180     );
181     item.detail(ty.display(ctx.db()).to_string()).lookup_by(field.to_string());
182     item.build(ctx.db())
183 }
184 
render_type_inference( ty_string: String, ctx: &CompletionContext<'_>, ) -> CompletionItem185 pub(crate) fn render_type_inference(
186     ty_string: String,
187     ctx: &CompletionContext<'_>,
188 ) -> CompletionItem {
189     let mut builder =
190         CompletionItem::new(CompletionItemKind::InferredType, ctx.source_range(), ty_string);
191     builder.set_relevance(CompletionRelevance { is_definite: true, ..Default::default() });
192     builder.build(ctx.db)
193 }
194 
render_path_resolution( ctx: RenderContext<'_>, path_ctx: &PathCompletionCtx, local_name: hir::Name, resolution: ScopeDef, ) -> Builder195 pub(crate) fn render_path_resolution(
196     ctx: RenderContext<'_>,
197     path_ctx: &PathCompletionCtx,
198     local_name: hir::Name,
199     resolution: ScopeDef,
200 ) -> Builder {
201     render_resolution_path(ctx, path_ctx, local_name, None, resolution)
202 }
203 
render_pattern_resolution( ctx: RenderContext<'_>, pattern_ctx: &PatternContext, local_name: hir::Name, resolution: ScopeDef, ) -> Builder204 pub(crate) fn render_pattern_resolution(
205     ctx: RenderContext<'_>,
206     pattern_ctx: &PatternContext,
207     local_name: hir::Name,
208     resolution: ScopeDef,
209 ) -> Builder {
210     render_resolution_pat(ctx, pattern_ctx, local_name, None, resolution)
211 }
212 
render_resolution_with_import( ctx: RenderContext<'_>, path_ctx: &PathCompletionCtx, import_edit: LocatedImport, ) -> Option<Builder>213 pub(crate) fn render_resolution_with_import(
214     ctx: RenderContext<'_>,
215     path_ctx: &PathCompletionCtx,
216     import_edit: LocatedImport,
217 ) -> Option<Builder> {
218     let resolution = ScopeDef::from(import_edit.original_item);
219     let local_name = scope_def_to_name(resolution, &ctx, &import_edit)?;
220     //this now just renders the alias text, but we need to find the aliases earlier and call this with the alias instead
221     let doc_aliases = ctx.completion.doc_aliases_in_scope(resolution);
222     let ctx = ctx.doc_aliases(doc_aliases);
223     Some(render_resolution_path(ctx, path_ctx, local_name, Some(import_edit), resolution))
224 }
225 
render_resolution_with_import_pat( ctx: RenderContext<'_>, pattern_ctx: &PatternContext, import_edit: LocatedImport, ) -> Option<Builder>226 pub(crate) fn render_resolution_with_import_pat(
227     ctx: RenderContext<'_>,
228     pattern_ctx: &PatternContext,
229     import_edit: LocatedImport,
230 ) -> Option<Builder> {
231     let resolution = ScopeDef::from(import_edit.original_item);
232     let local_name = scope_def_to_name(resolution, &ctx, &import_edit)?;
233     Some(render_resolution_pat(ctx, pattern_ctx, local_name, Some(import_edit), resolution))
234 }
235 
scope_def_to_name( resolution: ScopeDef, ctx: &RenderContext<'_>, import_edit: &LocatedImport, ) -> Option<hir::Name>236 fn scope_def_to_name(
237     resolution: ScopeDef,
238     ctx: &RenderContext<'_>,
239     import_edit: &LocatedImport,
240 ) -> Option<hir::Name> {
241     Some(match resolution {
242         ScopeDef::ModuleDef(hir::ModuleDef::Function(f)) => f.name(ctx.completion.db),
243         ScopeDef::ModuleDef(hir::ModuleDef::Const(c)) => c.name(ctx.completion.db)?,
244         ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(t)) => t.name(ctx.completion.db),
245         _ => item_name(ctx.db(), import_edit.original_item)?,
246     })
247 }
248 
render_resolution_pat( ctx: RenderContext<'_>, pattern_ctx: &PatternContext, local_name: hir::Name, import_to_add: Option<LocatedImport>, resolution: ScopeDef, ) -> Builder249 fn render_resolution_pat(
250     ctx: RenderContext<'_>,
251     pattern_ctx: &PatternContext,
252     local_name: hir::Name,
253     import_to_add: Option<LocatedImport>,
254     resolution: ScopeDef,
255 ) -> Builder {
256     let _p = profile::span("render_resolution");
257     use hir::ModuleDef::*;
258 
259     match resolution {
260         ScopeDef::ModuleDef(Macro(mac)) => {
261             let ctx = ctx.import_to_add(import_to_add);
262             return render_macro_pat(ctx, pattern_ctx, local_name, mac);
263         }
264         _ => (),
265     }
266 
267     render_resolution_simple_(ctx, &local_name, import_to_add, resolution)
268 }
269 
render_resolution_path( ctx: RenderContext<'_>, path_ctx: &PathCompletionCtx, local_name: hir::Name, import_to_add: Option<LocatedImport>, resolution: ScopeDef, ) -> Builder270 fn render_resolution_path(
271     ctx: RenderContext<'_>,
272     path_ctx: &PathCompletionCtx,
273     local_name: hir::Name,
274     import_to_add: Option<LocatedImport>,
275     resolution: ScopeDef,
276 ) -> Builder {
277     let _p = profile::span("render_resolution");
278     use hir::ModuleDef::*;
279 
280     match resolution {
281         ScopeDef::ModuleDef(Macro(mac)) => {
282             let ctx = ctx.import_to_add(import_to_add);
283             return render_macro(ctx, path_ctx, local_name, mac);
284         }
285         ScopeDef::ModuleDef(Function(func)) => {
286             let ctx = ctx.import_to_add(import_to_add);
287             return render_fn(ctx, path_ctx, Some(local_name), func);
288         }
289         ScopeDef::ModuleDef(Variant(var)) => {
290             let ctx = ctx.clone().import_to_add(import_to_add.clone());
291             if let Some(item) =
292                 render_variant_lit(ctx, path_ctx, Some(local_name.clone()), var, None)
293             {
294                 return item;
295             }
296         }
297         _ => (),
298     }
299 
300     let completion = ctx.completion;
301     let cap = ctx.snippet_cap();
302     let db = completion.db;
303     let config = completion.config;
304 
305     let name = local_name.to_smol_str();
306     let mut item = render_resolution_simple_(ctx, &local_name, import_to_add, resolution);
307     if local_name.is_escaped() {
308         item.insert_text(local_name.to_smol_str());
309     }
310     // Add `<>` for generic types
311     let type_path_no_ty_args = matches!(
312         path_ctx,
313         PathCompletionCtx { kind: PathKind::Type { .. }, has_type_args: false, .. }
314     ) && config.callable.is_some();
315     if type_path_no_ty_args {
316         if let Some(cap) = cap {
317             let has_non_default_type_params = match resolution {
318                 ScopeDef::ModuleDef(hir::ModuleDef::Adt(it)) => it.has_non_default_type_params(db),
319                 ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(it)) => {
320                     it.has_non_default_type_params(db)
321                 }
322                 _ => false,
323             };
324 
325             if has_non_default_type_params {
326                 cov_mark::hit!(inserts_angle_brackets_for_generics);
327                 item.lookup_by(name.clone())
328                     .label(SmolStr::from_iter([&name, "<…>"]))
329                     .trigger_call_info()
330                     .insert_snippet(cap, format!("{}<$0>", local_name.display(db)));
331             }
332         }
333     }
334     if let ScopeDef::Local(local) = resolution {
335         let ty = local.ty(db);
336         if !ty.is_unknown() {
337             item.detail(ty.display(db).to_string());
338         }
339 
340         item.set_relevance(CompletionRelevance {
341             type_match: compute_type_match(completion, &ty),
342             exact_name_match: compute_exact_name_match(completion, &name),
343             is_local: true,
344             ..CompletionRelevance::default()
345         });
346 
347         path_ref_match(completion, path_ctx, &ty, &mut item);
348     };
349     item
350 }
351 
render_resolution_simple_( ctx: RenderContext<'_>, local_name: &hir::Name, import_to_add: Option<LocatedImport>, resolution: ScopeDef, ) -> Builder352 fn render_resolution_simple_(
353     ctx: RenderContext<'_>,
354     local_name: &hir::Name,
355     import_to_add: Option<LocatedImport>,
356     resolution: ScopeDef,
357 ) -> Builder {
358     let _p = profile::span("render_resolution");
359 
360     let db = ctx.db();
361     let ctx = ctx.import_to_add(import_to_add);
362     let kind = res_to_kind(resolution);
363 
364     let mut item =
365         CompletionItem::new(kind, ctx.source_range(), local_name.unescaped().to_smol_str());
366     item.set_relevance(ctx.completion_relevance())
367         .set_documentation(scope_def_docs(db, resolution))
368         .set_deprecated(scope_def_is_deprecated(&ctx, resolution));
369 
370     if let Some(import_to_add) = ctx.import_to_add {
371         item.add_import(import_to_add);
372     }
373 
374     item.doc_aliases(ctx.doc_aliases);
375     item
376 }
377 
res_to_kind(resolution: ScopeDef) -> CompletionItemKind378 fn res_to_kind(resolution: ScopeDef) -> CompletionItemKind {
379     use hir::ModuleDef::*;
380     match resolution {
381         ScopeDef::Unknown => CompletionItemKind::UnresolvedReference,
382         ScopeDef::ModuleDef(Function(_)) => CompletionItemKind::SymbolKind(SymbolKind::Function),
383         ScopeDef::ModuleDef(Variant(_)) => CompletionItemKind::SymbolKind(SymbolKind::Variant),
384         ScopeDef::ModuleDef(Macro(_)) => CompletionItemKind::SymbolKind(SymbolKind::Macro),
385         ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::SymbolKind(SymbolKind::Module),
386         ScopeDef::ModuleDef(Adt(adt)) => CompletionItemKind::SymbolKind(match adt {
387             hir::Adt::Struct(_) => SymbolKind::Struct,
388             hir::Adt::Union(_) => SymbolKind::Union,
389             hir::Adt::Enum(_) => SymbolKind::Enum,
390         }),
391         ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::SymbolKind(SymbolKind::Const),
392         ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::SymbolKind(SymbolKind::Static),
393         ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::SymbolKind(SymbolKind::Trait),
394         ScopeDef::ModuleDef(TraitAlias(..)) => {
395             CompletionItemKind::SymbolKind(SymbolKind::TraitAlias)
396         }
397         ScopeDef::ModuleDef(TypeAlias(..)) => CompletionItemKind::SymbolKind(SymbolKind::TypeAlias),
398         ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType,
399         ScopeDef::GenericParam(param) => CompletionItemKind::SymbolKind(match param {
400             hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam,
401             hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam,
402             hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam,
403         }),
404         ScopeDef::Local(..) => CompletionItemKind::SymbolKind(SymbolKind::Local),
405         ScopeDef::Label(..) => CompletionItemKind::SymbolKind(SymbolKind::Label),
406         ScopeDef::AdtSelfType(..) | ScopeDef::ImplSelfType(..) => {
407             CompletionItemKind::SymbolKind(SymbolKind::SelfParam)
408         }
409     }
410 }
411 
scope_def_docs(db: &RootDatabase, resolution: ScopeDef) -> Option<hir::Documentation>412 fn scope_def_docs(db: &RootDatabase, resolution: ScopeDef) -> Option<hir::Documentation> {
413     use hir::ModuleDef::*;
414     match resolution {
415         ScopeDef::ModuleDef(Module(it)) => it.docs(db),
416         ScopeDef::ModuleDef(Adt(it)) => it.docs(db),
417         ScopeDef::ModuleDef(Variant(it)) => it.docs(db),
418         ScopeDef::ModuleDef(Const(it)) => it.docs(db),
419         ScopeDef::ModuleDef(Static(it)) => it.docs(db),
420         ScopeDef::ModuleDef(Trait(it)) => it.docs(db),
421         ScopeDef::ModuleDef(TypeAlias(it)) => it.docs(db),
422         _ => None,
423     }
424 }
425 
scope_def_is_deprecated(ctx: &RenderContext<'_>, resolution: ScopeDef) -> bool426 fn scope_def_is_deprecated(ctx: &RenderContext<'_>, resolution: ScopeDef) -> bool {
427     match resolution {
428         ScopeDef::ModuleDef(it) => ctx.is_deprecated_assoc_item(it),
429         ScopeDef::GenericParam(it) => ctx.is_deprecated(it),
430         ScopeDef::AdtSelfType(it) => ctx.is_deprecated(it),
431         _ => false,
432     }
433 }
434 
compute_type_match( ctx: &CompletionContext<'_>, completion_ty: &hir::Type, ) -> Option<CompletionRelevanceTypeMatch>435 fn compute_type_match(
436     ctx: &CompletionContext<'_>,
437     completion_ty: &hir::Type,
438 ) -> Option<CompletionRelevanceTypeMatch> {
439     let expected_type = ctx.expected_type.as_ref()?;
440 
441     // We don't ever consider unit type to be an exact type match, since
442     // nearly always this is not meaningful to the user.
443     if expected_type.is_unit() {
444         return None;
445     }
446 
447     if completion_ty == expected_type {
448         Some(CompletionRelevanceTypeMatch::Exact)
449     } else if expected_type.could_unify_with(ctx.db, completion_ty) {
450         Some(CompletionRelevanceTypeMatch::CouldUnify)
451     } else {
452         None
453     }
454 }
455 
compute_exact_name_match(ctx: &CompletionContext<'_>, completion_name: &str) -> bool456 fn compute_exact_name_match(ctx: &CompletionContext<'_>, completion_name: &str) -> bool {
457     ctx.expected_name.as_ref().map_or(false, |name| name.text() == completion_name)
458 }
459 
compute_ref_match( ctx: &CompletionContext<'_>, completion_ty: &hir::Type, ) -> Option<hir::Mutability>460 fn compute_ref_match(
461     ctx: &CompletionContext<'_>,
462     completion_ty: &hir::Type,
463 ) -> Option<hir::Mutability> {
464     let expected_type = ctx.expected_type.as_ref()?;
465     if completion_ty != expected_type {
466         let expected_type_without_ref = expected_type.remove_ref()?;
467         if completion_ty.autoderef(ctx.db).any(|deref_ty| deref_ty == expected_type_without_ref) {
468             cov_mark::hit!(suggest_ref);
469             let mutability = if expected_type.is_mutable_reference() {
470                 hir::Mutability::Mut
471             } else {
472                 hir::Mutability::Shared
473             };
474             return Some(mutability);
475         };
476     }
477     None
478 }
479 
path_ref_match( completion: &CompletionContext<'_>, path_ctx: &PathCompletionCtx, ty: &hir::Type, item: &mut Builder, )480 fn path_ref_match(
481     completion: &CompletionContext<'_>,
482     path_ctx: &PathCompletionCtx,
483     ty: &hir::Type,
484     item: &mut Builder,
485 ) {
486     if let Some(original_path) = &path_ctx.original_path {
487         // At least one char was typed by the user already, in that case look for the original path
488         if let Some(original_path) = completion.sema.original_ast_node(original_path.clone()) {
489             if let Some(ref_match) = compute_ref_match(completion, ty) {
490                 item.ref_match(ref_match, original_path.syntax().text_range().start());
491             }
492         }
493     } else {
494         // completion requested on an empty identifier, there is no path here yet.
495         // FIXME: This might create inconsistent completions where we show a ref match in macro inputs
496         // as long as nothing was typed yet
497         if let Some(ref_match) = compute_ref_match(completion, ty) {
498             item.ref_match(ref_match, completion.position.offset);
499         }
500     }
501 }
502 
503 #[cfg(test)]
504 mod tests {
505     use std::cmp;
506 
507     use expect_test::{expect, Expect};
508     use ide_db::SymbolKind;
509     use itertools::Itertools;
510 
511     use crate::{
512         item::CompletionRelevanceTypeMatch,
513         tests::{check_edit, do_completion, get_all_items, TEST_CONFIG},
514         CompletionItem, CompletionItemKind, CompletionRelevance, CompletionRelevancePostfixMatch,
515     };
516 
517     #[track_caller]
check(ra_fixture: &str, kind: impl Into<CompletionItemKind>, expect: Expect)518     fn check(ra_fixture: &str, kind: impl Into<CompletionItemKind>, expect: Expect) {
519         let actual = do_completion(ra_fixture, kind.into());
520         expect.assert_debug_eq(&actual);
521     }
522 
523     #[track_caller]
check_kinds(ra_fixture: &str, kinds: &[CompletionItemKind], expect: Expect)524     fn check_kinds(ra_fixture: &str, kinds: &[CompletionItemKind], expect: Expect) {
525         let actual: Vec<_> =
526             kinds.iter().flat_map(|&kind| do_completion(ra_fixture, kind)).collect();
527         expect.assert_debug_eq(&actual);
528     }
529 
530     #[track_caller]
check_relevance_for_kinds(ra_fixture: &str, kinds: &[CompletionItemKind], expect: Expect)531     fn check_relevance_for_kinds(ra_fixture: &str, kinds: &[CompletionItemKind], expect: Expect) {
532         let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
533         actual.retain(|it| kinds.contains(&it.kind));
534         actual.sort_by_key(|it| cmp::Reverse(it.relevance.score()));
535         check_relevance_(actual, expect);
536     }
537 
538     #[track_caller]
check_relevance(ra_fixture: &str, expect: Expect)539     fn check_relevance(ra_fixture: &str, expect: Expect) {
540         let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
541         actual.retain(|it| it.kind != CompletionItemKind::Snippet);
542         actual.retain(|it| it.kind != CompletionItemKind::Keyword);
543         actual.retain(|it| it.kind != CompletionItemKind::BuiltinType);
544         actual.sort_by_key(|it| cmp::Reverse(it.relevance.score()));
545         check_relevance_(actual, expect);
546     }
547 
548     #[track_caller]
check_relevance_(actual: Vec<CompletionItem>, expect: Expect)549     fn check_relevance_(actual: Vec<CompletionItem>, expect: Expect) {
550         let actual = actual
551             .into_iter()
552             .flat_map(|it| {
553                 let mut items = vec![];
554 
555                 let tag = it.kind.tag();
556                 let relevance = display_relevance(it.relevance);
557                 items.push(format!("{tag} {} {relevance}\n", it.label));
558 
559                 if let Some((label, _indel, relevance)) = it.ref_match() {
560                     let relevance = display_relevance(relevance);
561 
562                     items.push(format!("{tag} {label} {relevance}\n"));
563                 }
564 
565                 items
566             })
567             .collect::<String>();
568 
569         expect.assert_eq(&actual);
570 
571         fn display_relevance(relevance: CompletionRelevance) -> String {
572             let relevance_factors = vec![
573                 (relevance.type_match == Some(CompletionRelevanceTypeMatch::Exact), "type"),
574                 (
575                     relevance.type_match == Some(CompletionRelevanceTypeMatch::CouldUnify),
576                     "type_could_unify",
577                 ),
578                 (relevance.exact_name_match, "name"),
579                 (relevance.is_local, "local"),
580                 (
581                     relevance.postfix_match == Some(CompletionRelevancePostfixMatch::Exact),
582                     "snippet",
583                 ),
584                 (relevance.is_op_method, "op_method"),
585                 (relevance.requires_import, "requires_import"),
586             ]
587             .into_iter()
588             .filter_map(|(cond, desc)| if cond { Some(desc) } else { None })
589             .join("+");
590 
591             format!("[{relevance_factors}]")
592         }
593     }
594 
595     #[test]
enum_detail_includes_record_fields()596     fn enum_detail_includes_record_fields() {
597         check(
598             r#"
599 enum Foo { Foo { x: i32, y: i32 } }
600 
601 fn main() { Foo::Fo$0 }
602 "#,
603             SymbolKind::Variant,
604             expect![[r#"
605                 [
606                     CompletionItem {
607                         label: "Foo {…}",
608                         source_range: 54..56,
609                         delete: 54..56,
610                         insert: "Foo { x: ${1:()}, y: ${2:()} }$0",
611                         kind: SymbolKind(
612                             Variant,
613                         ),
614                         lookup: "Foo{}",
615                         detail: "Foo { x: i32, y: i32 }",
616                         trigger_call_info: true,
617                     },
618                 ]
619             "#]],
620         );
621     }
622 
623     #[test]
enum_detail_includes_tuple_fields()624     fn enum_detail_includes_tuple_fields() {
625         check(
626             r#"
627 enum Foo { Foo (i32, i32) }
628 
629 fn main() { Foo::Fo$0 }
630 "#,
631             SymbolKind::Variant,
632             expect![[r#"
633                 [
634                     CompletionItem {
635                         label: "Foo(…)",
636                         source_range: 46..48,
637                         delete: 46..48,
638                         insert: "Foo(${1:()}, ${2:()})$0",
639                         kind: SymbolKind(
640                             Variant,
641                         ),
642                         lookup: "Foo()",
643                         detail: "Foo(i32, i32)",
644                         trigger_call_info: true,
645                     },
646                 ]
647             "#]],
648         );
649     }
650 
651     #[test]
fn_detail_includes_args_and_return_type()652     fn fn_detail_includes_args_and_return_type() {
653         check(
654             r#"
655 fn foo<T>(a: u32, b: u32, t: T) -> (u32, T) { (a, t) }
656 
657 fn main() { fo$0 }
658 "#,
659             SymbolKind::Function,
660             expect![[r#"
661                 [
662                     CompletionItem {
663                         label: "foo(…)",
664                         source_range: 68..70,
665                         delete: 68..70,
666                         insert: "foo(${1:a}, ${2:b}, ${3:t})$0",
667                         kind: SymbolKind(
668                             Function,
669                         ),
670                         lookup: "foo",
671                         detail: "fn(u32, u32, T) -> (u32, T)",
672                         trigger_call_info: true,
673                     },
674                     CompletionItem {
675                         label: "main()",
676                         source_range: 68..70,
677                         delete: 68..70,
678                         insert: "main()$0",
679                         kind: SymbolKind(
680                             Function,
681                         ),
682                         lookup: "main",
683                         detail: "fn()",
684                     },
685                 ]
686             "#]],
687         );
688     }
689 
690     #[test]
enum_detail_just_name_for_unit()691     fn enum_detail_just_name_for_unit() {
692         check(
693             r#"
694 enum Foo { Foo }
695 
696 fn main() { Foo::Fo$0 }
697 "#,
698             SymbolKind::Variant,
699             expect![[r#"
700                 [
701                     CompletionItem {
702                         label: "Foo",
703                         source_range: 35..37,
704                         delete: 35..37,
705                         insert: "Foo$0",
706                         kind: SymbolKind(
707                             Variant,
708                         ),
709                         detail: "Foo",
710                         trigger_call_info: true,
711                     },
712                 ]
713             "#]],
714         );
715     }
716 
717     #[test]
lookup_enums_by_two_qualifiers()718     fn lookup_enums_by_two_qualifiers() {
719         check_kinds(
720             r#"
721 mod m {
722     pub enum Spam { Foo, Bar(i32) }
723 }
724 fn main() { let _: m::Spam = S$0 }
725 "#,
726             &[
727                 CompletionItemKind::SymbolKind(SymbolKind::Function),
728                 CompletionItemKind::SymbolKind(SymbolKind::Module),
729                 CompletionItemKind::SymbolKind(SymbolKind::Variant),
730             ],
731             expect![[r#"
732                 [
733                     CompletionItem {
734                         label: "main()",
735                         source_range: 75..76,
736                         delete: 75..76,
737                         insert: "main()$0",
738                         kind: SymbolKind(
739                             Function,
740                         ),
741                         lookup: "main",
742                         detail: "fn()",
743                     },
744                     CompletionItem {
745                         label: "m",
746                         source_range: 75..76,
747                         delete: 75..76,
748                         insert: "m",
749                         kind: SymbolKind(
750                             Module,
751                         ),
752                     },
753                     CompletionItem {
754                         label: "m::Spam::Bar(…)",
755                         source_range: 75..76,
756                         delete: 75..76,
757                         insert: "m::Spam::Bar(${1:()})$0",
758                         kind: SymbolKind(
759                             Variant,
760                         ),
761                         lookup: "Spam::Bar()",
762                         detail: "m::Spam::Bar(i32)",
763                         relevance: CompletionRelevance {
764                             exact_name_match: false,
765                             type_match: Some(
766                                 Exact,
767                             ),
768                             is_local: false,
769                             is_item_from_trait: false,
770                             is_name_already_imported: false,
771                             requires_import: false,
772                             is_op_method: false,
773                             is_private_editable: false,
774                             postfix_match: None,
775                             is_definite: false,
776                         },
777                         trigger_call_info: true,
778                     },
779                     CompletionItem {
780                         label: "m::Spam::Foo",
781                         source_range: 75..76,
782                         delete: 75..76,
783                         insert: "m::Spam::Foo$0",
784                         kind: SymbolKind(
785                             Variant,
786                         ),
787                         lookup: "Spam::Foo",
788                         detail: "m::Spam::Foo",
789                         relevance: CompletionRelevance {
790                             exact_name_match: false,
791                             type_match: Some(
792                                 Exact,
793                             ),
794                             is_local: false,
795                             is_item_from_trait: false,
796                             is_name_already_imported: false,
797                             requires_import: false,
798                             is_op_method: false,
799                             is_private_editable: false,
800                             postfix_match: None,
801                             is_definite: false,
802                         },
803                         trigger_call_info: true,
804                     },
805                 ]
806             "#]],
807         )
808     }
809 
810     #[test]
sets_deprecated_flag_in_items()811     fn sets_deprecated_flag_in_items() {
812         check(
813             r#"
814 #[deprecated]
815 fn something_deprecated() {}
816 
817 fn main() { som$0 }
818 "#,
819             SymbolKind::Function,
820             expect![[r#"
821                 [
822                     CompletionItem {
823                         label: "main()",
824                         source_range: 56..59,
825                         delete: 56..59,
826                         insert: "main()$0",
827                         kind: SymbolKind(
828                             Function,
829                         ),
830                         lookup: "main",
831                         detail: "fn()",
832                     },
833                     CompletionItem {
834                         label: "something_deprecated()",
835                         source_range: 56..59,
836                         delete: 56..59,
837                         insert: "something_deprecated()$0",
838                         kind: SymbolKind(
839                             Function,
840                         ),
841                         lookup: "something_deprecated",
842                         detail: "fn()",
843                         deprecated: true,
844                     },
845                 ]
846             "#]],
847         );
848 
849         check(
850             r#"
851 struct A { #[deprecated] the_field: u32 }
852 fn foo() { A { the$0 } }
853 "#,
854             SymbolKind::Field,
855             expect![[r#"
856                 [
857                     CompletionItem {
858                         label: "the_field",
859                         source_range: 57..60,
860                         delete: 57..60,
861                         insert: "the_field",
862                         kind: SymbolKind(
863                             Field,
864                         ),
865                         detail: "u32",
866                         deprecated: true,
867                         relevance: CompletionRelevance {
868                             exact_name_match: false,
869                             type_match: Some(
870                                 CouldUnify,
871                             ),
872                             is_local: false,
873                             is_item_from_trait: false,
874                             is_name_already_imported: false,
875                             requires_import: false,
876                             is_op_method: false,
877                             is_private_editable: false,
878                             postfix_match: None,
879                             is_definite: false,
880                         },
881                     },
882                 ]
883             "#]],
884         );
885     }
886 
887     #[test]
renders_docs()888     fn renders_docs() {
889         check_kinds(
890             r#"
891 struct S {
892     /// Field docs
893     foo:
894 }
895 impl S {
896     /// Method docs
897     fn bar(self) { self.$0 }
898 }"#,
899             &[CompletionItemKind::Method, CompletionItemKind::SymbolKind(SymbolKind::Field)],
900             expect![[r#"
901                 [
902                     CompletionItem {
903                         label: "bar()",
904                         source_range: 94..94,
905                         delete: 94..94,
906                         insert: "bar()$0",
907                         kind: Method,
908                         lookup: "bar",
909                         detail: "fn(self)",
910                         documentation: Documentation(
911                             "Method docs",
912                         ),
913                     },
914                     CompletionItem {
915                         label: "foo",
916                         source_range: 94..94,
917                         delete: 94..94,
918                         insert: "foo",
919                         kind: SymbolKind(
920                             Field,
921                         ),
922                         detail: "{unknown}",
923                         documentation: Documentation(
924                             "Field docs",
925                         ),
926                     },
927                 ]
928             "#]],
929         );
930 
931         check_kinds(
932             r#"
933 use self::my$0;
934 
935 /// mod docs
936 mod my { }
937 
938 /// enum docs
939 enum E {
940     /// variant docs
941     V
942 }
943 use self::E::*;
944 "#,
945             &[
946                 CompletionItemKind::SymbolKind(SymbolKind::Module),
947                 CompletionItemKind::SymbolKind(SymbolKind::Variant),
948                 CompletionItemKind::SymbolKind(SymbolKind::Enum),
949             ],
950             expect![[r#"
951                 [
952                     CompletionItem {
953                         label: "my",
954                         source_range: 10..12,
955                         delete: 10..12,
956                         insert: "my",
957                         kind: SymbolKind(
958                             Module,
959                         ),
960                         documentation: Documentation(
961                             "mod docs",
962                         ),
963                     },
964                     CompletionItem {
965                         label: "V",
966                         source_range: 10..12,
967                         delete: 10..12,
968                         insert: "V$0",
969                         kind: SymbolKind(
970                             Variant,
971                         ),
972                         detail: "V",
973                         documentation: Documentation(
974                             "variant docs",
975                         ),
976                         trigger_call_info: true,
977                     },
978                     CompletionItem {
979                         label: "E",
980                         source_range: 10..12,
981                         delete: 10..12,
982                         insert: "E",
983                         kind: SymbolKind(
984                             Enum,
985                         ),
986                         documentation: Documentation(
987                             "enum docs",
988                         ),
989                     },
990                 ]
991             "#]],
992         )
993     }
994 
995     #[test]
dont_render_attrs()996     fn dont_render_attrs() {
997         check(
998             r#"
999 struct S;
1000 impl S {
1001     #[inline]
1002     fn the_method(&self) { }
1003 }
1004 fn foo(s: S) { s.$0 }
1005 "#,
1006             CompletionItemKind::Method,
1007             expect![[r#"
1008                 [
1009                     CompletionItem {
1010                         label: "the_method()",
1011                         source_range: 81..81,
1012                         delete: 81..81,
1013                         insert: "the_method()$0",
1014                         kind: Method,
1015                         lookup: "the_method",
1016                         detail: "fn(&self)",
1017                     },
1018                 ]
1019             "#]],
1020         )
1021     }
1022 
1023     #[test]
no_call_parens_if_fn_ptr_needed()1024     fn no_call_parens_if_fn_ptr_needed() {
1025         cov_mark::check!(no_call_parens_if_fn_ptr_needed);
1026         check_edit(
1027             "foo",
1028             r#"
1029 fn foo(foo: u8, bar: u8) {}
1030 struct ManualVtable { f: fn(u8, u8) }
1031 
1032 fn main() -> ManualVtable {
1033     ManualVtable { f: f$0 }
1034 }
1035 "#,
1036             r#"
1037 fn foo(foo: u8, bar: u8) {}
1038 struct ManualVtable { f: fn(u8, u8) }
1039 
1040 fn main() -> ManualVtable {
1041     ManualVtable { f: foo }
1042 }
1043 "#,
1044         );
1045         check_edit(
1046             "type",
1047             r#"
1048 struct RawIdentTable { r#type: u32 }
1049 
1050 fn main() -> RawIdentTable {
1051     RawIdentTable { t$0: 42 }
1052 }
1053 "#,
1054             r#"
1055 struct RawIdentTable { r#type: u32 }
1056 
1057 fn main() -> RawIdentTable {
1058     RawIdentTable { r#type: 42 }
1059 }
1060 "#,
1061         );
1062     }
1063 
1064     #[test]
no_parens_in_use_item()1065     fn no_parens_in_use_item() {
1066         check_edit(
1067             "foo",
1068             r#"
1069 mod m { pub fn foo() {} }
1070 use crate::m::f$0;
1071 "#,
1072             r#"
1073 mod m { pub fn foo() {} }
1074 use crate::m::foo;
1075 "#,
1076         );
1077     }
1078 
1079     #[test]
no_parens_in_call()1080     fn no_parens_in_call() {
1081         check_edit(
1082             "foo",
1083             r#"
1084 fn foo(x: i32) {}
1085 fn main() { f$0(); }
1086 "#,
1087             r#"
1088 fn foo(x: i32) {}
1089 fn main() { foo(); }
1090 "#,
1091         );
1092         check_edit(
1093             "foo",
1094             r#"
1095 struct Foo;
1096 impl Foo { fn foo(&self){} }
1097 fn f(foo: &Foo) { foo.f$0(); }
1098 "#,
1099             r#"
1100 struct Foo;
1101 impl Foo { fn foo(&self){} }
1102 fn f(foo: &Foo) { foo.foo(); }
1103 "#,
1104         );
1105     }
1106 
1107     #[test]
inserts_angle_brackets_for_generics()1108     fn inserts_angle_brackets_for_generics() {
1109         cov_mark::check!(inserts_angle_brackets_for_generics);
1110         check_edit(
1111             "Vec",
1112             r#"
1113 struct Vec<T> {}
1114 fn foo(xs: Ve$0)
1115 "#,
1116             r#"
1117 struct Vec<T> {}
1118 fn foo(xs: Vec<$0>)
1119 "#,
1120         );
1121         check_edit(
1122             "Vec",
1123             r#"
1124 type Vec<T> = (T,);
1125 fn foo(xs: Ve$0)
1126 "#,
1127             r#"
1128 type Vec<T> = (T,);
1129 fn foo(xs: Vec<$0>)
1130 "#,
1131         );
1132         check_edit(
1133             "Vec",
1134             r#"
1135 struct Vec<T = i128> {}
1136 fn foo(xs: Ve$0)
1137 "#,
1138             r#"
1139 struct Vec<T = i128> {}
1140 fn foo(xs: Vec)
1141 "#,
1142         );
1143         check_edit(
1144             "Vec",
1145             r#"
1146 struct Vec<T> {}
1147 fn foo(xs: Ve$0<i128>)
1148 "#,
1149             r#"
1150 struct Vec<T> {}
1151 fn foo(xs: Vec<i128>)
1152 "#,
1153         );
1154     }
1155 
1156     #[test]
active_param_relevance()1157     fn active_param_relevance() {
1158         check_relevance(
1159             r#"
1160 struct S { foo: i64, bar: u32, baz: u32 }
1161 fn test(bar: u32) { }
1162 fn foo(s: S) { test(s.$0) }
1163 "#,
1164             expect![[r#"
1165                 fd bar [type+name]
1166                 fd baz [type]
1167                 fd foo []
1168             "#]],
1169         );
1170     }
1171 
1172     #[test]
record_field_relevances()1173     fn record_field_relevances() {
1174         check_relevance(
1175             r#"
1176 struct A { foo: i64, bar: u32, baz: u32 }
1177 struct B { x: (), y: f32, bar: u32 }
1178 fn foo(a: A) { B { bar: a.$0 }; }
1179 "#,
1180             expect![[r#"
1181                 fd bar [type+name]
1182                 fd baz [type]
1183                 fd foo []
1184             "#]],
1185         )
1186     }
1187 
1188     #[test]
record_field_and_call_relevances()1189     fn record_field_and_call_relevances() {
1190         check_relevance(
1191             r#"
1192 struct A { foo: i64, bar: u32, baz: u32 }
1193 struct B { x: (), y: f32, bar: u32 }
1194 fn f(foo: i64) {  }
1195 fn foo(a: A) { B { bar: f(a.$0) }; }
1196 "#,
1197             expect![[r#"
1198                 fd foo [type+name]
1199                 fd bar []
1200                 fd baz []
1201             "#]],
1202         );
1203         check_relevance(
1204             r#"
1205 struct A { foo: i64, bar: u32, baz: u32 }
1206 struct B { x: (), y: f32, bar: u32 }
1207 fn f(foo: i64) {  }
1208 fn foo(a: A) { f(B { bar: a.$0 }); }
1209 "#,
1210             expect![[r#"
1211                 fd bar [type+name]
1212                 fd baz [type]
1213                 fd foo []
1214             "#]],
1215         );
1216     }
1217 
1218     #[test]
prioritize_exact_ref_match()1219     fn prioritize_exact_ref_match() {
1220         check_relevance(
1221             r#"
1222 struct WorldSnapshot { _f: () };
1223 fn go(world: &WorldSnapshot) { go(w$0) }
1224 "#,
1225             expect![[r#"
1226                 lc world [type+name+local]
1227                 st WorldSnapshot {…} []
1228                 st &WorldSnapshot {…} [type]
1229                 st WorldSnapshot []
1230                 fn go(…) []
1231             "#]],
1232         );
1233     }
1234 
1235     #[test]
too_many_arguments()1236     fn too_many_arguments() {
1237         cov_mark::check!(too_many_arguments);
1238         check_relevance(
1239             r#"
1240 struct Foo;
1241 fn f(foo: &Foo) { f(foo, w$0) }
1242 "#,
1243             expect![[r#"
1244                 lc foo [local]
1245                 st Foo []
1246                 fn f(…) []
1247             "#]],
1248         );
1249     }
1250 
1251     #[test]
score_fn_type_and_name_match()1252     fn score_fn_type_and_name_match() {
1253         check_relevance(
1254             r#"
1255 struct A { bar: u8 }
1256 fn baz() -> u8 { 0 }
1257 fn bar() -> u8 { 0 }
1258 fn f() { A { bar: b$0 }; }
1259 "#,
1260             expect![[r#"
1261                 fn bar() [type+name]
1262                 fn baz() [type]
1263                 st A []
1264                 fn f() []
1265             "#]],
1266         );
1267     }
1268 
1269     #[test]
score_method_type_and_name_match()1270     fn score_method_type_and_name_match() {
1271         check_relevance(
1272             r#"
1273 fn baz(aaa: u32){}
1274 struct Foo;
1275 impl Foo {
1276 fn aaa(&self) -> u32 { 0 }
1277 fn bbb(&self) -> u32 { 0 }
1278 fn ccc(&self) -> u64 { 0 }
1279 }
1280 fn f() {
1281     baz(Foo.$0
1282 }
1283 "#,
1284             expect![[r#"
1285                 me aaa() [type+name]
1286                 me bbb() [type]
1287                 me ccc() []
1288             "#]],
1289         );
1290     }
1291 
1292     #[test]
score_method_name_match_only()1293     fn score_method_name_match_only() {
1294         check_relevance(
1295             r#"
1296 fn baz(aaa: u32){}
1297 struct Foo;
1298 impl Foo {
1299 fn aaa(&self) -> u64 { 0 }
1300 }
1301 fn f() {
1302     baz(Foo.$0
1303 }
1304 "#,
1305             expect![[r#"
1306                 me aaa() [name]
1307             "#]],
1308         );
1309     }
1310 
1311     #[test]
suggest_ref_mut()1312     fn suggest_ref_mut() {
1313         cov_mark::check!(suggest_ref);
1314         check_relevance(
1315             r#"
1316 struct S;
1317 fn foo(s: &mut S) {}
1318 fn main() {
1319     let mut s = S;
1320     foo($0);
1321 }
1322             "#,
1323             expect![[r#"
1324                 lc s [name+local]
1325                 lc &mut s [type+name+local]
1326                 st S []
1327                 st &mut S [type]
1328                 st S []
1329                 fn foo(…) []
1330                 fn main() []
1331             "#]],
1332         );
1333         check_relevance(
1334             r#"
1335 struct S;
1336 fn foo(s: &mut S) {}
1337 fn main() {
1338     let mut s = S;
1339     foo(&mut $0);
1340 }
1341             "#,
1342             expect![[r#"
1343                 lc s [type+name+local]
1344                 st S [type]
1345                 st S []
1346                 fn foo(…) []
1347                 fn main() []
1348             "#]],
1349         );
1350         check_relevance(
1351             r#"
1352 struct S;
1353 fn foo(s: &mut S) {}
1354 fn main() {
1355     let mut ssss = S;
1356     foo(&mut s$0);
1357 }
1358             "#,
1359             expect![[r#"
1360                 lc ssss [type+local]
1361                 st S [type]
1362                 st S []
1363                 fn foo(…) []
1364                 fn main() []
1365             "#]],
1366         );
1367     }
1368 
1369     #[test]
suggest_deref()1370     fn suggest_deref() {
1371         check_relevance(
1372             r#"
1373 //- minicore: deref
1374 struct S;
1375 struct T(S);
1376 
1377 impl core::ops::Deref for T {
1378     type Target = S;
1379 
1380     fn deref(&self) -> &Self::Target {
1381         &self.0
1382     }
1383 }
1384 
1385 fn foo(s: &S) {}
1386 
1387 fn main() {
1388     let t = T(S);
1389     let m = 123;
1390 
1391     foo($0);
1392 }
1393             "#,
1394             expect![[r#"
1395                 lc m [local]
1396                 lc t [local]
1397                 lc &t [type+local]
1398                 st S []
1399                 st &S [type]
1400                 st S []
1401                 st T []
1402                 fn foo(…) []
1403                 fn main() []
1404                 md core []
1405             "#]],
1406         )
1407     }
1408 
1409     #[test]
suggest_deref_mut()1410     fn suggest_deref_mut() {
1411         check_relevance(
1412             r#"
1413 //- minicore: deref_mut
1414 struct S;
1415 struct T(S);
1416 
1417 impl core::ops::Deref for T {
1418     type Target = S;
1419 
1420     fn deref(&self) -> &Self::Target {
1421         &self.0
1422     }
1423 }
1424 
1425 impl core::ops::DerefMut for T {
1426     fn deref_mut(&mut self) -> &mut Self::Target {
1427         &mut self.0
1428     }
1429 }
1430 
1431 fn foo(s: &mut S) {}
1432 
1433 fn main() {
1434     let t = T(S);
1435     let m = 123;
1436 
1437     foo($0);
1438 }
1439             "#,
1440             expect![[r#"
1441                 lc m [local]
1442                 lc t [local]
1443                 lc &mut t [type+local]
1444                 st S []
1445                 st &mut S [type]
1446                 st S []
1447                 st T []
1448                 fn foo(…) []
1449                 fn main() []
1450                 md core []
1451             "#]],
1452         )
1453     }
1454 
1455     #[test]
locals()1456     fn locals() {
1457         check_relevance(
1458             r#"
1459 fn foo(bar: u32) {
1460     let baz = 0;
1461 
1462     f$0
1463 }
1464 "#,
1465             expect![[r#"
1466                 lc baz [local]
1467                 lc bar [local]
1468                 fn foo(…) []
1469             "#]],
1470         );
1471     }
1472 
1473     #[test]
enum_owned()1474     fn enum_owned() {
1475         check_relevance(
1476             r#"
1477 enum Foo { A, B }
1478 fn foo() {
1479     bar($0);
1480 }
1481 fn bar(t: Foo) {}
1482 "#,
1483             expect![[r#"
1484                 ev Foo::A [type]
1485                 ev Foo::B [type]
1486                 en Foo []
1487                 fn bar(…) []
1488                 fn foo() []
1489             "#]],
1490         );
1491     }
1492 
1493     #[test]
enum_ref()1494     fn enum_ref() {
1495         check_relevance(
1496             r#"
1497 enum Foo { A, B }
1498 fn foo() {
1499     bar($0);
1500 }
1501 fn bar(t: &Foo) {}
1502 "#,
1503             expect![[r#"
1504                 ev Foo::A []
1505                 ev &Foo::A [type]
1506                 ev Foo::B []
1507                 ev &Foo::B [type]
1508                 en Foo []
1509                 fn bar(…) []
1510                 fn foo() []
1511             "#]],
1512         );
1513     }
1514 
1515     #[test]
suggest_deref_fn_ret()1516     fn suggest_deref_fn_ret() {
1517         check_relevance(
1518             r#"
1519 //- minicore: deref
1520 struct S;
1521 struct T(S);
1522 
1523 impl core::ops::Deref for T {
1524     type Target = S;
1525 
1526     fn deref(&self) -> &Self::Target {
1527         &self.0
1528     }
1529 }
1530 
1531 fn foo(s: &S) {}
1532 fn bar() -> T {}
1533 
1534 fn main() {
1535     foo($0);
1536 }
1537 "#,
1538             expect![[r#"
1539                 st S []
1540                 st &S [type]
1541                 st S []
1542                 st T []
1543                 fn bar() []
1544                 fn &bar() [type]
1545                 fn foo(…) []
1546                 fn main() []
1547                 md core []
1548             "#]],
1549         )
1550     }
1551 
1552     #[test]
op_function_relevances()1553     fn op_function_relevances() {
1554         check_relevance(
1555             r#"
1556 #[lang = "sub"]
1557 trait Sub {
1558     fn sub(self, other: Self) -> Self { self }
1559 }
1560 impl Sub for u32 {}
1561 fn foo(a: u32) { a.$0 }
1562 "#,
1563             expect![[r#"
1564                 me sub(…) (as Sub) [op_method]
1565             "#]],
1566         );
1567         check_relevance(
1568             r#"
1569 struct Foo;
1570 impl Foo {
1571     fn new() -> Self {}
1572 }
1573 #[lang = "eq"]
1574 pub trait PartialEq<Rhs: ?Sized = Self> {
1575     fn eq(&self, other: &Rhs) -> bool;
1576     fn ne(&self, other: &Rhs) -> bool;
1577 }
1578 
1579 impl PartialEq for Foo {}
1580 fn main() {
1581     Foo::$0
1582 }
1583 "#,
1584             expect![[r#"
1585                 fn new() []
1586                 me eq(…) (as PartialEq) [op_method]
1587                 me ne(…) (as PartialEq) [op_method]
1588             "#]],
1589         );
1590     }
1591 
1592     #[test]
struct_field_method_ref()1593     fn struct_field_method_ref() {
1594         check_kinds(
1595             r#"
1596 struct Foo { bar: u32 }
1597 impl Foo { fn baz(&self) -> u32 { 0 } }
1598 
1599 fn foo(f: Foo) { let _: &u32 = f.b$0 }
1600 "#,
1601             &[CompletionItemKind::Method, CompletionItemKind::SymbolKind(SymbolKind::Field)],
1602             expect![[r#"
1603                 [
1604                     CompletionItem {
1605                         label: "baz()",
1606                         source_range: 98..99,
1607                         delete: 98..99,
1608                         insert: "baz()$0",
1609                         kind: Method,
1610                         lookup: "baz",
1611                         detail: "fn(&self) -> u32",
1612                         ref_match: "&@96",
1613                     },
1614                     CompletionItem {
1615                         label: "bar",
1616                         source_range: 98..99,
1617                         delete: 98..99,
1618                         insert: "bar",
1619                         kind: SymbolKind(
1620                             Field,
1621                         ),
1622                         detail: "u32",
1623                         ref_match: "&@96",
1624                     },
1625                 ]
1626             "#]],
1627         );
1628     }
1629 
1630     #[test]
qualified_path_ref()1631     fn qualified_path_ref() {
1632         check_kinds(
1633             r#"
1634 struct S;
1635 
1636 struct T;
1637 impl T {
1638     fn foo() -> S {}
1639 }
1640 
1641 fn bar(s: &S) {}
1642 
1643 fn main() {
1644     bar(T::$0);
1645 }
1646 "#,
1647             &[CompletionItemKind::SymbolKind(SymbolKind::Function)],
1648             expect![[r#"
1649                 [
1650                     CompletionItem {
1651                         label: "foo()",
1652                         source_range: 95..95,
1653                         delete: 95..95,
1654                         insert: "foo()$0",
1655                         kind: SymbolKind(
1656                             Function,
1657                         ),
1658                         lookup: "foo",
1659                         detail: "fn() -> S",
1660                         ref_match: "&@92",
1661                     },
1662                 ]
1663             "#]],
1664         );
1665     }
1666 
1667     #[test]
generic_enum()1668     fn generic_enum() {
1669         check_relevance(
1670             r#"
1671 enum Foo<T> { A(T), B }
1672 // bar() should not be an exact type match
1673 // because the generic parameters are different
1674 fn bar() -> Foo<u8> { Foo::B }
1675 // FIXME baz() should be an exact type match
1676 // because the types could unify, but it currently
1677 // is not. This is due to the T here being
1678 // TyKind::Placeholder rather than TyKind::Missing.
1679 fn baz<T>() -> Foo<T> { Foo::B }
1680 fn foo() {
1681     let foo: Foo<u32> = Foo::B;
1682     let _: Foo<u32> = f$0;
1683 }
1684 "#,
1685             expect![[r#"
1686                 lc foo [type+local]
1687                 ev Foo::A(…) [type_could_unify]
1688                 ev Foo::B [type_could_unify]
1689                 fn foo() []
1690                 en Foo []
1691                 fn bar() []
1692                 fn baz() []
1693             "#]],
1694         );
1695     }
1696 
1697     #[test]
postfix_exact_match_is_high_priority()1698     fn postfix_exact_match_is_high_priority() {
1699         cov_mark::check!(postfix_exact_match_is_high_priority);
1700         check_relevance_for_kinds(
1701             r#"
1702 mod ops {
1703     pub trait Not {
1704         type Output;
1705         fn not(self) -> Self::Output;
1706     }
1707 
1708     impl Not for bool {
1709         type Output = bool;
1710         fn not(self) -> bool { if self { false } else { true }}
1711     }
1712 }
1713 
1714 fn main() {
1715     let _: bool = (9 > 2).not$0;
1716 }
1717     "#,
1718             &[CompletionItemKind::Snippet, CompletionItemKind::Method],
1719             expect![[r#"
1720                 sn not [snippet]
1721                 me not() (use ops::Not) [type_could_unify+requires_import]
1722                 sn if []
1723                 sn while []
1724                 sn ref []
1725                 sn refm []
1726                 sn unsafe []
1727                 sn match []
1728                 sn box []
1729                 sn dbg []
1730                 sn dbgr []
1731                 sn call []
1732             "#]],
1733         );
1734     }
1735 
1736     #[test]
postfix_inexact_match_is_low_priority()1737     fn postfix_inexact_match_is_low_priority() {
1738         cov_mark::check!(postfix_inexact_match_is_low_priority);
1739         check_relevance_for_kinds(
1740             r#"
1741 struct S;
1742 impl S {
1743     fn f(&self) {}
1744 }
1745 fn main() {
1746     S.$0
1747 }
1748     "#,
1749             &[CompletionItemKind::Snippet, CompletionItemKind::Method],
1750             expect![[r#"
1751                 me f() []
1752                 sn ref []
1753                 sn refm []
1754                 sn unsafe []
1755                 sn match []
1756                 sn box []
1757                 sn dbg []
1758                 sn dbgr []
1759                 sn call []
1760                 sn let []
1761                 sn letm []
1762             "#]],
1763         );
1764     }
1765 
1766     #[test]
flyimport_reduced_relevance()1767     fn flyimport_reduced_relevance() {
1768         check_relevance(
1769             r#"
1770 mod std {
1771     pub mod io {
1772         pub trait BufRead {}
1773         pub struct BufReader;
1774         pub struct BufWriter;
1775     }
1776 }
1777 struct Buffer;
1778 
1779 fn f() {
1780     Buf$0
1781 }
1782 "#,
1783             expect![[r#"
1784                 st Buffer []
1785                 fn f() []
1786                 md std []
1787                 tt BufRead (use std::io::BufRead) [requires_import]
1788                 st BufReader (use std::io::BufReader) [requires_import]
1789                 st BufWriter (use std::io::BufWriter) [requires_import]
1790             "#]],
1791         );
1792     }
1793 
1794     #[test]
completes_struct_with_raw_identifier()1795     fn completes_struct_with_raw_identifier() {
1796         check_edit(
1797             "type",
1798             r#"
1799 mod m { pub struct r#type {} }
1800 fn main() {
1801     let r#type = m::t$0;
1802 }
1803 "#,
1804             r#"
1805 mod m { pub struct r#type {} }
1806 fn main() {
1807     let r#type = m::r#type;
1808 }
1809 "#,
1810         )
1811     }
1812 
1813     #[test]
completes_fn_with_raw_identifier()1814     fn completes_fn_with_raw_identifier() {
1815         check_edit(
1816             "type",
1817             r#"
1818 mod m { pub fn r#type {} }
1819 fn main() {
1820     m::t$0
1821 }
1822 "#,
1823             r#"
1824 mod m { pub fn r#type {} }
1825 fn main() {
1826     m::r#type()$0
1827 }
1828 "#,
1829         )
1830     }
1831 
1832     #[test]
completes_macro_with_raw_identifier()1833     fn completes_macro_with_raw_identifier() {
1834         check_edit(
1835             "let!",
1836             r#"
1837 macro_rules! r#let { () => {} }
1838 fn main() {
1839     $0
1840 }
1841 "#,
1842             r#"
1843 macro_rules! r#let { () => {} }
1844 fn main() {
1845     r#let!($0)
1846 }
1847 "#,
1848         )
1849     }
1850 
1851     #[test]
completes_variant_with_raw_identifier()1852     fn completes_variant_with_raw_identifier() {
1853         check_edit(
1854             "type",
1855             r#"
1856 enum A { r#type }
1857 fn main() {
1858     let a = A::t$0
1859 }
1860 "#,
1861             r#"
1862 enum A { r#type }
1863 fn main() {
1864     let a = A::r#type$0
1865 }
1866 "#,
1867         )
1868     }
1869 
1870     #[test]
completes_field_with_raw_identifier()1871     fn completes_field_with_raw_identifier() {
1872         check_edit(
1873             "fn",
1874             r#"
1875 mod r#type {
1876     pub struct r#struct {
1877         pub r#fn: u32
1878     }
1879 }
1880 
1881 fn main() {
1882     let a = r#type::r#struct {};
1883     a.$0
1884 }
1885 "#,
1886             r#"
1887 mod r#type {
1888     pub struct r#struct {
1889         pub r#fn: u32
1890     }
1891 }
1892 
1893 fn main() {
1894     let a = r#type::r#struct {};
1895     a.r#fn
1896 }
1897 "#,
1898         )
1899     }
1900 
1901     #[test]
completes_const_with_raw_identifier()1902     fn completes_const_with_raw_identifier() {
1903         check_edit(
1904             "type",
1905             r#"
1906 struct r#struct {}
1907 impl r#struct { pub const r#type: u8 = 1; }
1908 fn main() {
1909     r#struct::t$0
1910 }
1911 "#,
1912             r#"
1913 struct r#struct {}
1914 impl r#struct { pub const r#type: u8 = 1; }
1915 fn main() {
1916     r#struct::r#type
1917 }
1918 "#,
1919         )
1920     }
1921 
1922     #[test]
completes_type_alias_with_raw_identifier()1923     fn completes_type_alias_with_raw_identifier() {
1924         check_edit(
1925             "type type",
1926             r#"
1927 struct r#struct {}
1928 trait r#trait { type r#type; }
1929 impl r#trait for r#struct { type t$0 }
1930 "#,
1931             r#"
1932 struct r#struct {}
1933 trait r#trait { type r#type; }
1934 impl r#trait for r#struct { type r#type = $0; }
1935 "#,
1936         )
1937     }
1938 
1939     #[test]
field_access_includes_self()1940     fn field_access_includes_self() {
1941         check_edit(
1942             "length",
1943             r#"
1944 struct S {
1945     length: i32
1946 }
1947 
1948 impl S {
1949     fn some_fn(&self) {
1950         let l = len$0
1951     }
1952 }
1953 "#,
1954             r#"
1955 struct S {
1956     length: i32
1957 }
1958 
1959 impl S {
1960     fn some_fn(&self) {
1961         let l = self.length
1962     }
1963 }
1964 "#,
1965         )
1966     }
1967 }
1968