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);