1 //! Completion of names from the current scope in expression position.
7 completions
::record
::add_default_update
,
8 context
::{ExprCtx, PathCompletionCtx, Qualified}
,
9 CompletionContext
, Completions
,
12 pub(crate) fn complete_expr_path(
13 acc
: &mut Completions
,
14 ctx
: &CompletionContext
<'_
>,
15 path_ctx @ PathCompletionCtx { qualified, .. }
: &PathCompletionCtx
,
18 let _p
= profile
::span("complete_expr_path");
19 if !ctx
.qualifier_ctx
.none() {
38 ref_expr_parent
.as_ref().map(|it
| it
.mut_token().is_none()).unwrap_or(false);
40 let scope_def_applicable
= |def
| match def
{
41 ScopeDef
::GenericParam(hir
::GenericParam
::LifetimeParam(_
)) | ScopeDef
::Label(_
) => false,
42 ScopeDef
::ModuleDef(hir
::ModuleDef
::Macro(mac
)) => mac
.is_fn_like(ctx
.db
),
46 let add_assoc_item
= |acc
: &mut Completions
, item
| match item
{
47 hir
::AssocItem
::Function(func
) => acc
.add_function(ctx
, path_ctx
, func
, None
),
48 hir
::AssocItem
::Const(ct
) => acc
.add_const(ctx
, ct
),
49 hir
::AssocItem
::TypeAlias(ty
) => acc
.add_type_alias(ctx
, ty
),
53 Qualified
::TypeAnchor { ty: None, trait_: None }
=> ctx
56 .flat_map(|&it
| hir
::Trait
::from(it
).items(ctx
.sema
.db
))
57 .for_each(|item
| add_assoc_item(acc
, item
)),
58 Qualified
::TypeAnchor { trait_: Some(trait_), .. }
=> {
59 trait_
.items(ctx
.sema
.db
).into_iter().for_each(|item
| add_assoc_item(acc
, item
))
61 Qualified
::TypeAnchor { ty: Some(ty), trait_: None }
=> {
62 if let Some(hir
::Adt
::Enum(e
)) = ty
.as_adt() {
63 cov_mark
::hit
!(completes_variant_through_alias
);
64 acc
.add_enum_variants(ctx
, path_ctx
, e
);
67 ctx
.iterate_path_candidates(&ty
, |item
| {
68 add_assoc_item(acc
, item
);
71 // Iterate assoc types separately
72 ty
.iterate_assoc_items(ctx
.db
, ctx
.krate
, |item
| {
73 if let hir
::AssocItem
::TypeAlias(ty
) = item
{
74 acc
.add_type_alias(ctx
, ty
)
79 Qualified
::With { resolution: None, .. }
=> {}
80 Qualified
::With { resolution: Some(resolution), .. }
=> {
81 // Add associated types on type parameters and `Self`.
82 ctx
.scope
.assoc_type_shorthand_candidates(resolution
, |_
, alias
| {
83 acc
.add_type_alias(ctx
, alias
);
87 hir
::PathResolution
::Def(hir
::ModuleDef
::Module(module
)) => {
88 let module_scope
= module
.scope(ctx
.db
, Some(ctx
.module
));
89 for (name
, def
) in module_scope
{
90 if scope_def_applicable(def
) {
91 acc
.add_path_resolution(ctx
, path_ctx
, name
, def
);
95 hir
::PathResolution
::Def(
96 def @
(hir
::ModuleDef
::Adt(_
)
97 | hir
::ModuleDef
::TypeAlias(_
)
98 | hir
::ModuleDef
::BuiltinType(_
)),
101 hir
::ModuleDef
::Adt(adt
) => adt
.ty(ctx
.db
),
102 hir
::ModuleDef
::TypeAlias(a
) => a
.ty(ctx
.db
),
103 hir
::ModuleDef
::BuiltinType(builtin
) => {
104 cov_mark
::hit
!(completes_primitive_assoc_const
);
110 if let Some(hir
::Adt
::Enum(e
)) = ty
.as_adt() {
111 cov_mark
::hit
!(completes_variant_through_alias
);
112 acc
.add_enum_variants(ctx
, path_ctx
, e
);
115 // XXX: For parity with Rust bug #22519, this does not complete Ty::AssocType.
116 // (where AssocType is defined on a trait, not an inherent impl)
118 ctx
.iterate_path_candidates(&ty
, |item
| {
119 add_assoc_item(acc
, item
);
122 // Iterate assoc types separately
123 ty
.iterate_assoc_items(ctx
.db
, ctx
.krate
, |item
| {
124 if let hir
::AssocItem
::TypeAlias(ty
) = item
{
125 acc
.add_type_alias(ctx
, ty
)
130 hir
::PathResolution
::Def(hir
::ModuleDef
::Trait(t
)) => {
131 // Handles `Trait::assoc` as well as `<Ty as Trait>::assoc`.
132 for item
in t
.items(ctx
.db
) {
133 add_assoc_item(acc
, item
);
136 hir
::PathResolution
::TypeParam(_
) | hir
::PathResolution
::SelfType(_
) => {
137 let ty
= match resolution
{
138 hir
::PathResolution
::TypeParam(param
) => param
.ty(ctx
.db
),
139 hir
::PathResolution
::SelfType(impl_def
) => impl_def
.self_ty(ctx
.db
),
143 if let Some(hir
::Adt
::Enum(e
)) = ty
.as_adt() {
144 cov_mark
::hit
!(completes_variant_through_self
);
145 acc
.add_enum_variants(ctx
, path_ctx
, e
);
148 ctx
.iterate_path_candidates(&ty
, |item
| {
149 add_assoc_item(acc
, item
);
155 Qualified
::Absolute
=> acc
.add_crate_roots(ctx
, path_ctx
),
157 acc
.add_nameref_keywords_with_colon(ctx
);
159 ctx
.expected_type
.as_ref().and_then(|ty
| ty
.strip_references().as_adt())
161 let self_ty
= (|| ctx
.sema
.to_def(impl_
.as_ref()?
)?
.self_ty(ctx
.db
).as_adt())();
162 let complete_self
= self_ty
== Some(adt
);
165 hir
::Adt
::Struct(strukt
) => {
170 hir
::ModuleDef
::from(strukt
),
171 ctx
.config
.prefer_no_std
,
173 .filter(|it
| it
.len() > 1);
175 acc
.add_struct_literal(ctx
, path_ctx
, strukt
, path
, None
);
178 acc
.add_struct_literal(
183 Some(hir
::known
::SELF_TYPE
),
187 hir
::Adt
::Union(un
) => {
192 hir
::ModuleDef
::from(un
),
193 ctx
.config
.prefer_no_std
,
195 .filter(|it
| it
.len() > 1);
197 acc
.add_union_literal(ctx
, un
, path
, None
);
199 acc
.add_union_literal(ctx
, un
, None
, Some(hir
::known
::SELF_TYPE
));
202 hir
::Adt
::Enum(e
) => {
203 super::enum_variants_with_paths(
208 |acc
, ctx
, variant
, path
| {
209 acc
.add_qualified_enum_variant(ctx
, path_ctx
, variant
, path
)
215 ctx
.process_all_names(&mut |name
, def
| match def
{
216 ScopeDef
::ModuleDef(hir
::ModuleDef
::Trait(t
)) => {
217 let assocs
= t
.items_with_supertraits(ctx
.db
);
219 // traits with no assoc items are unusable as expressions since
220 // there is no associated item path that can be constructed with them
222 // FIXME: Render the assoc item with the trait qualified
223 &[_item
] => acc
.add_path_resolution(ctx
, path_ctx
, name
, def
),
224 // FIXME: Append `::` to the thing here, since a trait on its own won't work
225 [..] => acc
.add_path_resolution(ctx
, path_ctx
, name
, def
),
228 _
if scope_def_applicable(def
) => acc
.add_path_resolution(ctx
, path_ctx
, name
, def
),
232 match is_func_update
{
233 Some(record_expr
) => {
234 let ty
= ctx
.sema
.type_of_expr(&ast
::Expr
::RecordExpr(record_expr
.clone()));
236 match ty
.as_ref().and_then(|t
| t
.original
.as_adt()) {
237 Some(hir
::Adt
::Union(_
)) => (),
239 cov_mark
::hit
!(functional_update
);
241 ctx
.sema
.record_literal_missing_fields(record_expr
);
242 if !missing_fields
.is_empty() {
243 add_default_update(acc
, ctx
, ty
);
249 let mut add_keyword
= |kw
, snippet
| {
250 acc
.add_keyword_snippet_expr(ctx
, incomplete_let
, kw
, snippet
)
254 add_keyword("unsafe", "unsafe {\n $0\n}");
256 add_keyword("match", "match $1 {\n $0\n}");
257 add_keyword("while", "while $1 {\n $0\n}");
258 add_keyword("while let", "while let $1 = $2 {\n $0\n}");
259 add_keyword("loop", "loop {\n $0\n}");
261 add_keyword("if", "if $0");
263 add_keyword("if", "if $1 {\n $0\n}");
265 add_keyword("if let", "if let $1 = $2 {\n $0\n}");
266 add_keyword("for", "for $1 in $2 {\n $0\n}");
267 add_keyword("true", "true");
268 add_keyword("false", "false");
270 if in_condition
|| in_block_expr
{
271 add_keyword("let", "let");
275 add_keyword("else", "else {\n $0\n}");
276 add_keyword("else if", "else if $1 {\n $0\n}");
280 add_keyword("mut", "mut ");
285 add_keyword("continue", "continue;");
286 add_keyword("break", "break;");
288 add_keyword("continue", "continue");
289 add_keyword("break", "break");
293 if let Some(ret_ty
) = innermost_ret_ty
{
296 match (ret_ty
.is_unit(), in_block_expr
) {
298 cov_mark
::hit
!(return_unit_block
);
302 cov_mark
::hit
!(return_unit_no_block
);
306 cov_mark
::hit
!(return_value_block
);
310 cov_mark
::hit
!(return_value_no_block
);