1 //! This module defines an accumulator for completions which are going to be presented to user.
3 pub(crate) mod attribute
;
6 pub(crate) mod extern_abi
;
8 pub(crate) mod flyimport
;
9 pub(crate) mod fn_param
;
10 pub(crate) mod format_string
;
11 pub(crate) mod item_list
;
12 pub(crate) mod keyword
;
13 pub(crate) mod lifetime
;
15 pub(crate) mod pattern
;
16 pub(crate) mod postfix
;
17 pub(crate) mod record
;
18 pub(crate) mod snippet
;
19 pub(crate) mod r
#type;
22 pub(crate) mod env_vars
;
26 use hir
::{known, ScopeDef}
;
27 use ide_db
::{imports::import_assets::LocatedImport, SymbolKind}
;
32 DotAccess
, ItemListKind
, NameContext
, NameKind
, NameRefContext
, NameRefKind
,
33 PathCompletionCtx
, PathKind
, PatternContext
, TypeLocation
, Visible
,
38 function
::{render_fn, render_method}
,
39 literal
::{render_struct_literal, render_variant_lit}
,
41 pattern
::{render_struct_pat, render_variant_pat}
,
42 render_field
, render_path_resolution
, render_pattern_resolution
, render_tuple_field
,
43 type_alias
::{render_type_alias, render_type_alias_with_eq}
,
44 union_literal
::render_union_literal
,
47 CompletionContext
, CompletionItem
, CompletionItemKind
,
50 /// Represents an in-progress set of completions being built.
51 #[derive(Debug, Default)]
52 pub struct Completions
{
53 buf
: Vec
<CompletionItem
>,
56 impl From
<Completions
> for Vec
<CompletionItem
> {
57 fn from(val
: Completions
) -> Self {
63 /// Convenience method, which allows to add a freshly created completion into accumulator
64 /// without binding it to the variable.
65 pub(crate) fn add_to(self, acc
: &mut Completions
) {
71 fn add(&mut self, item
: CompletionItem
) {
75 fn add_opt(&mut self, item
: Option
<CompletionItem
>) {
76 if let Some(item
) = item
{
81 pub(crate) fn add_all
<I
>(&mut self, items
: I
)
84 I
::Item
: Into
<CompletionItem
>,
86 items
.into_iter().for_each(|item
| self.add(item
.into()))
89 pub(crate) fn add_keyword(&mut self, ctx
: &CompletionContext
<'_
>, keyword
: &'
static str) {
90 let item
= CompletionItem
::new(CompletionItemKind
::Keyword
, ctx
.source_range(), keyword
);
94 pub(crate) fn add_nameref_keywords_with_colon(&mut self, ctx
: &CompletionContext
<'_
>) {
95 ["self::", "crate::"].into_iter().for_each(|kw
| self.add_keyword(ctx
, kw
));
97 if ctx
.depth_from_crate_root
> 0 {
98 self.add_keyword(ctx
, "super::");
102 pub(crate) fn add_nameref_keywords(&mut self, ctx
: &CompletionContext
<'_
>) {
103 ["self", "crate"].into_iter().for_each(|kw
| self.add_keyword(ctx
, kw
));
105 if ctx
.depth_from_crate_root
> 0 {
106 self.add_keyword(ctx
, "super");
110 pub(crate) fn add_super_keyword(
112 ctx
: &CompletionContext
<'_
>,
113 super_chain_len
: Option
<usize>,
115 if let Some(len
) = super_chain_len
{
116 if len
> 0 && len
< ctx
.depth_from_crate_root
{
117 self.add_keyword(ctx
, "super::");
122 pub(crate) fn add_keyword_snippet_expr(
124 ctx
: &CompletionContext
<'_
>,
125 incomplete_let
: bool
,
129 let mut item
= CompletionItem
::new(CompletionItemKind
::Keyword
, ctx
.source_range(), kw
);
131 match ctx
.config
.snippet_cap
{
133 if incomplete_let
&& snippet
.ends_with('
}'
) {
134 // complete block expression snippets with a trailing semicolon, if inside an incomplete let
135 cov_mark
::hit
!(let_semi
);
136 item
.insert_snippet(cap
, format
!("{};", snippet
));
138 item
.insert_snippet(cap
, snippet
);
142 item
.insert_text(if snippet
.contains('$'
) { kw }
else { snippet }
);
148 pub(crate) fn add_keyword_snippet(
150 ctx
: &CompletionContext
<'_
>,
154 let mut item
= CompletionItem
::new(CompletionItemKind
::Keyword
, ctx
.source_range(), kw
);
156 match ctx
.config
.snippet_cap
{
157 Some(cap
) => item
.insert_snippet(cap
, snippet
),
158 None
=> item
.insert_text(if snippet
.contains('$'
) { kw }
else { snippet }
),
163 pub(crate) fn add_crate_roots(
165 ctx
: &CompletionContext
<'_
>,
166 path_ctx
: &PathCompletionCtx
,
168 ctx
.process_all_names(&mut |name
, res
| match res
{
169 ScopeDef
::ModuleDef(hir
::ModuleDef
::Module(m
)) if m
.is_crate_root(ctx
.db
) => {
170 self.add_module(ctx
, path_ctx
, m
, name
);
176 pub(crate) fn add_path_resolution(
178 ctx
: &CompletionContext
<'_
>,
179 path_ctx
: &PathCompletionCtx
,
180 local_name
: hir
::Name
,
181 resolution
: hir
::ScopeDef
,
183 let is_private_editable
= match ctx
.def_is_visible(&resolution
) {
184 Visible
::Yes
=> false,
185 Visible
::Editable
=> true,
186 Visible
::No
=> return,
189 render_path_resolution(
190 RenderContext
::new(ctx
).private_editable(is_private_editable
),
199 pub(crate) fn add_pattern_resolution(
201 ctx
: &CompletionContext
<'_
>,
202 pattern_ctx
: &PatternContext
,
203 local_name
: hir
::Name
,
204 resolution
: hir
::ScopeDef
,
206 let is_private_editable
= match ctx
.def_is_visible(&resolution
) {
207 Visible
::Yes
=> false,
208 Visible
::Editable
=> true,
209 Visible
::No
=> return,
212 render_pattern_resolution(
213 RenderContext
::new(ctx
).private_editable(is_private_editable
),
222 pub(crate) fn add_enum_variants(
224 ctx
: &CompletionContext
<'_
>,
225 path_ctx
: &PathCompletionCtx
,
230 .for_each(|variant
| self.add_enum_variant(ctx
, path_ctx
, variant
, None
));
233 pub(crate) fn add_module(
235 ctx
: &CompletionContext
<'_
>,
236 path_ctx
: &PathCompletionCtx
,
238 local_name
: hir
::Name
,
240 self.add_path_resolution(
244 hir
::ScopeDef
::ModuleDef(module
.into()),
248 pub(crate) fn add_macro(
250 ctx
: &CompletionContext
<'_
>,
251 path_ctx
: &PathCompletionCtx
,
253 local_name
: hir
::Name
,
255 let is_private_editable
= match ctx
.is_visible(&mac
) {
256 Visible
::Yes
=> false,
257 Visible
::Editable
=> true,
258 Visible
::No
=> return,
262 RenderContext
::new(ctx
).private_editable(is_private_editable
),
271 pub(crate) fn add_function(
273 ctx
: &CompletionContext
<'_
>,
274 path_ctx
: &PathCompletionCtx
,
276 local_name
: Option
<hir
::Name
>,
278 let is_private_editable
= match ctx
.is_visible(&func
) {
279 Visible
::Yes
=> false,
280 Visible
::Editable
=> true,
281 Visible
::No
=> return,
285 RenderContext
::new(ctx
).private_editable(is_private_editable
),
294 pub(crate) fn add_method(
296 ctx
: &CompletionContext
<'_
>,
297 dot_access
: &DotAccess
,
299 receiver
: Option
<hir
::Name
>,
300 local_name
: Option
<hir
::Name
>,
302 let is_private_editable
= match ctx
.is_visible(&func
) {
303 Visible
::Yes
=> false,
304 Visible
::Editable
=> true,
305 Visible
::No
=> return,
309 RenderContext
::new(ctx
).private_editable(is_private_editable
),
319 pub(crate) fn add_method_with_import(
321 ctx
: &CompletionContext
<'_
>,
322 dot_access
: &DotAccess
,
324 import
: LocatedImport
,
326 let is_private_editable
= match ctx
.is_visible(&func
) {
327 Visible
::Yes
=> false,
328 Visible
::Editable
=> true,
329 Visible
::No
=> return,
333 RenderContext
::new(ctx
)
334 .private_editable(is_private_editable
)
335 .import_to_add(Some(import
)),
345 pub(crate) fn add_const(&mut self, ctx
: &CompletionContext
<'_
>, konst
: hir
::Const
) {
346 let is_private_editable
= match ctx
.is_visible(&konst
) {
347 Visible
::Yes
=> false,
348 Visible
::Editable
=> true,
349 Visible
::No
=> return,
351 self.add_opt(render_const(
352 RenderContext
::new(ctx
).private_editable(is_private_editable
),
357 pub(crate) fn add_type_alias(
359 ctx
: &CompletionContext
<'_
>,
360 type_alias
: hir
::TypeAlias
,
362 let is_private_editable
= match ctx
.is_visible(&type_alias
) {
363 Visible
::Yes
=> false,
364 Visible
::Editable
=> true,
365 Visible
::No
=> return,
367 self.add_opt(render_type_alias(
368 RenderContext
::new(ctx
).private_editable(is_private_editable
),
373 pub(crate) fn add_type_alias_with_eq(
375 ctx
: &CompletionContext
<'_
>,
376 type_alias
: hir
::TypeAlias
,
378 self.add_opt(render_type_alias_with_eq(RenderContext
::new(ctx
), type_alias
));
381 pub(crate) fn add_qualified_enum_variant(
383 ctx
: &CompletionContext
<'_
>,
384 path_ctx
: &PathCompletionCtx
,
385 variant
: hir
::Variant
,
388 if let Some(builder
) =
389 render_variant_lit(RenderContext
::new(ctx
), path_ctx
, None
, variant
, Some(path
))
391 self.add(builder
.build());
395 pub(crate) fn add_enum_variant(
397 ctx
: &CompletionContext
<'_
>,
398 path_ctx
: &PathCompletionCtx
,
399 variant
: hir
::Variant
,
400 local_name
: Option
<hir
::Name
>,
402 if let PathCompletionCtx { kind: PathKind::Pat { pat_ctx }
, .. } = path_ctx
{
403 cov_mark
::hit
!(enum_variant_pattern_path
);
404 self.add_variant_pat(ctx
, pat_ctx
, Some(path_ctx
), variant
, local_name
);
408 if let Some(builder
) =
409 render_variant_lit(RenderContext
::new(ctx
), path_ctx
, local_name
, variant
, None
)
411 self.add(builder
.build());
415 pub(crate) fn add_field(
417 ctx
: &CompletionContext
<'_
>,
418 dot_access
: &DotAccess
,
419 receiver
: Option
<hir
::Name
>,
423 let is_private_editable
= match ctx
.is_visible(&field
) {
424 Visible
::Yes
=> false,
425 Visible
::Editable
=> true,
426 Visible
::No
=> return,
428 let item
= render_field(
429 RenderContext
::new(ctx
).private_editable(is_private_editable
),
438 pub(crate) fn add_struct_literal(
440 ctx
: &CompletionContext
<'_
>,
441 path_ctx
: &PathCompletionCtx
,
443 path
: Option
<hir
::ModPath
>,
444 local_name
: Option
<hir
::Name
>,
446 if let Some(builder
) =
447 render_struct_literal(RenderContext
::new(ctx
), path_ctx
, strukt
, path
, local_name
)
449 self.add(builder
.build());
453 pub(crate) fn add_union_literal(
455 ctx
: &CompletionContext
<'_
>,
457 path
: Option
<hir
::ModPath
>,
458 local_name
: Option
<hir
::Name
>,
460 let item
= render_union_literal(RenderContext
::new(ctx
), un
, path
, local_name
);
464 pub(crate) fn add_tuple_field(
466 ctx
: &CompletionContext
<'_
>,
467 receiver
: Option
<hir
::Name
>,
471 let item
= render_tuple_field(RenderContext
::new(ctx
), receiver
, field
, ty
);
475 pub(crate) fn add_lifetime(&mut self, ctx
: &CompletionContext
<'_
>, name
: hir
::Name
) {
476 CompletionItem
::new(SymbolKind
::LifetimeParam
, ctx
.source_range(), name
.to_smol_str())
480 pub(crate) fn add_label(&mut self, ctx
: &CompletionContext
<'_
>, name
: hir
::Name
) {
481 CompletionItem
::new(SymbolKind
::Label
, ctx
.source_range(), name
.to_smol_str()).add_to(self)
484 pub(crate) fn add_variant_pat(
486 ctx
: &CompletionContext
<'_
>,
487 pattern_ctx
: &PatternContext
,
488 path_ctx
: Option
<&PathCompletionCtx
>,
489 variant
: hir
::Variant
,
490 local_name
: Option
<hir
::Name
>,
492 self.add_opt(render_variant_pat(
493 RenderContext
::new(ctx
),
502 pub(crate) fn add_qualified_variant_pat(
504 ctx
: &CompletionContext
<'_
>,
505 pattern_ctx
: &PatternContext
,
506 variant
: hir
::Variant
,
509 let path
= Some(&path
);
510 self.add_opt(render_variant_pat(
511 RenderContext
::new(ctx
),
520 pub(crate) fn add_struct_pat(
522 ctx
: &CompletionContext
<'_
>,
523 pattern_ctx
: &PatternContext
,
525 local_name
: Option
<hir
::Name
>,
527 self.add_opt(render_struct_pat(RenderContext
::new(ctx
), pattern_ctx
, strukt
, local_name
));
531 /// Calls the callback for each variant of the provided enum with the path to the variant.
532 /// Skips variants that are visible with single segment paths.
533 fn enum_variants_with_paths(
534 acc
: &mut Completions
,
535 ctx
: &CompletionContext
<'_
>,
537 impl_
: &Option
<ast
::Impl
>,
538 cb
: impl Fn(&mut Completions
, &CompletionContext
<'_
>, hir
::Variant
, hir
::ModPath
),
540 let variants
= enum_
.variants(ctx
.db
);
542 if let Some(impl_
) = impl_
.as_ref().and_then(|impl_
| ctx
.sema
.to_def(impl_
)) {
543 if impl_
.self_ty(ctx
.db
).as_adt() == Some(hir
::Adt
::Enum(enum_
)) {
544 for &variant
in &variants
{
545 let self_path
= hir
::ModPath
::from_segments(
546 hir
::PathKind
::Plain
,
547 iter
::once(known
::SELF_TYPE
).chain(iter
::once(variant
.name(ctx
.db
))),
549 cb(acc
, ctx
, variant
, self_path
);
554 for variant
in variants
{
555 if let Some(path
) = ctx
.module
.find_use_path(
557 hir
::ModuleDef
::from(variant
),
558 ctx
.config
.prefer_no_std
,
560 // Variants with trivial paths are already added by the existing completion logic,
561 // so we should avoid adding these twice
562 if path
.segments().len() > 1 {
563 cb(acc
, ctx
, variant
, path
);
569 pub(super) fn complete_name(
570 acc
: &mut Completions
,
571 ctx
: &CompletionContext
<'_
>,
572 NameContext { name, kind }
: &NameContext
,
576 item_list
::trait_impl
::complete_trait_impl_const(acc
, ctx
, name
);
578 NameKind
::Function
=> {
579 item_list
::trait_impl
::complete_trait_impl_fn(acc
, ctx
, name
);
581 NameKind
::IdentPat(pattern_ctx
) => {
582 if ctx
.token
.kind() != syntax
::T
![_
] {
583 complete_patterns(acc
, ctx
, pattern_ctx
)
586 NameKind
::Module(mod_under_caret
) => {
587 mod_
::complete_mod(acc
, ctx
, mod_under_caret
);
589 NameKind
::TypeAlias
=> {
590 item_list
::trait_impl
::complete_trait_impl_type_alias(acc
, ctx
, name
);
592 NameKind
::RecordField
=> {
593 field
::complete_field_list_record_variant(acc
, ctx
);
598 | NameKind
::MacroRules
600 | NameKind
::SelfParam
604 | NameKind
::TypeParam
606 | NameKind
::Variant
=> (),
610 pub(super) fn complete_name_ref(
611 acc
: &mut Completions
,
612 ctx
: &CompletionContext
<'_
>,
613 NameRefContext { nameref, kind }
: &NameRefContext
,
616 NameRefKind
::Path(path_ctx
) => {
617 flyimport
::import_on_the_fly_path(acc
, ctx
, path_ctx
);
619 match &path_ctx
.kind
{
620 PathKind
::Expr { expr_ctx }
=> {
621 expr
::complete_expr_path(acc
, ctx
, path_ctx
, expr_ctx
);
623 dot
::complete_undotted_self(acc
, ctx
, path_ctx
, expr_ctx
);
624 item_list
::complete_item_list_in_expr(acc
, ctx
, path_ctx
, expr_ctx
);
625 snippet
::complete_expr_snippet(acc
, ctx
, path_ctx
, expr_ctx
);
627 PathKind
::Type { location }
=> {
628 r
#type::complete_type_path(acc, ctx, path_ctx, location);
631 TypeLocation
::TupleField
=> {
632 field
::complete_field_list_tuple_variant(acc
, ctx
, path_ctx
);
634 TypeLocation
::TypeAscription(ascription
) => {
635 r
#type::complete_ascribed_type(acc, ctx, path_ctx, ascription);
637 TypeLocation
::GenericArgList(_
)
638 | TypeLocation
::TypeBound
639 | TypeLocation
::ImplTarget
640 | TypeLocation
::ImplTrait
641 | TypeLocation
::Other
=> (),
644 PathKind
::Attr { attr_ctx }
=> {
645 attribute
::complete_attribute_path(acc
, ctx
, path_ctx
, attr_ctx
);
647 PathKind
::Derive { existing_derives }
=> {
648 attribute
::complete_derive_path(acc
, ctx
, path_ctx
, existing_derives
);
650 PathKind
::Item { kind }
=> {
651 item_list
::complete_item_list(acc
, ctx
, path_ctx
, kind
);
653 snippet
::complete_item_snippet(acc
, ctx
, path_ctx
, kind
);
654 if let ItemListKind
::TraitImpl(impl_
) = kind
{
655 item_list
::trait_impl
::complete_trait_impl_item_by_name(
656 acc
, ctx
, path_ctx
, nameref
, impl_
,
660 PathKind
::Pat { .. }
=> {
661 pattern
::complete_pattern_path(acc
, ctx
, path_ctx
);
663 PathKind
::Vis { has_in_token }
=> {
664 vis
::complete_vis_path(acc
, ctx
, path_ctx
, has_in_token
);
667 use_
::complete_use_path(acc
, ctx
, path_ctx
, nameref
);
671 NameRefKind
::DotAccess(dot_access
) => {
672 flyimport
::import_on_the_fly_dot(acc
, ctx
, dot_access
);
673 dot
::complete_dot(acc
, ctx
, dot_access
);
674 postfix
::complete_postfix(acc
, ctx
, dot_access
);
676 NameRefKind
::Keyword(item
) => {
677 keyword
::complete_for_and_where(acc
, ctx
, item
);
679 NameRefKind
::RecordExpr { dot_prefix, expr }
=> {
680 record
::complete_record_expr_fields(acc
, ctx
, expr
, dot_prefix
);
682 NameRefKind
::Pattern(pattern_ctx
) => complete_patterns(acc
, ctx
, pattern_ctx
),
686 fn complete_patterns(
687 acc
: &mut Completions
,
688 ctx
: &CompletionContext
<'_
>,
689 pattern_ctx
: &PatternContext
,
691 flyimport
::import_on_the_fly_pat(acc
, ctx
, pattern_ctx
);
692 fn_param
::complete_fn_param(acc
, ctx
, pattern_ctx
);
693 pattern
::complete_pattern(acc
, ctx
, pattern_ctx
);
694 record
::complete_record_pattern_fields(acc
, ctx
, pattern_ctx
);