Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-completion/src/completions/expr.rs')
| -rw-r--r-- | crates/ide-completion/src/completions/expr.rs | 121 |
1 files changed, 78 insertions, 43 deletions
diff --git a/crates/ide-completion/src/completions/expr.rs b/crates/ide-completion/src/completions/expr.rs index 23f47523d6..7c3296a0b3 100644 --- a/crates/ide-completion/src/completions/expr.rs +++ b/crates/ide-completion/src/completions/expr.rs @@ -11,32 +11,38 @@ use crate::{ pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext) { let _p = profile::span("complete_expr_path"); - if ctx.is_path_disallowed() { - return; - } - let (is_absolute_path, qualifier, in_block_expr, in_loop_body, is_func_update, after_if_expr) = - match ctx.nameref_ctx() { - Some(NameRefContext { - path_ctx: - Some(PathCompletionCtx { - kind: PathKind::Expr { in_block_expr, in_loop_body, after_if_expr }, - is_absolute_path, - qualifier, - .. - }), - record_expr, - .. - }) => ( - *is_absolute_path, - qualifier, - *in_block_expr, - *in_loop_body, - record_expr.as_ref().map_or(false, |&(_, it)| it), - *after_if_expr, - ), - _ => return, - }; + let ( + is_absolute_path, + qualifier, + in_block_expr, + in_loop_body, + is_func_update, + after_if_expr, + wants_mut_token, + ) = match ctx.nameref_ctx() { + Some(NameRefContext { + path_ctx: + Some(PathCompletionCtx { + kind: + PathKind::Expr { in_block_expr, in_loop_body, after_if_expr, ref_expr_parent }, + is_absolute_path, + qualifier, + .. + }), + record_expr, + .. + }) if ctx.qualifier_ctx.none() => ( + *is_absolute_path, + qualifier, + *in_block_expr, + *in_loop_body, + record_expr.as_ref().map_or(false, |&(_, it)| it), + *after_if_expr, + ref_expr_parent.as_ref().map(|it| it.mut_token().is_none()).unwrap_or(false), + ), + _ => return, + }; let scope_def_applicable = |def| { use hir::{GenericParam::*, ModuleDef::*}; @@ -164,12 +170,43 @@ pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext) None if is_absolute_path => acc.add_crate_roots(ctx), None => { acc.add_nameref_keywords_with_colon(ctx); - if let Some(hir::Adt::Enum(e)) = + if let Some(adt) = ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt()) { - super::enum_variants_with_paths(acc, ctx, e, |acc, ctx, variant, path| { - acc.add_qualified_enum_variant(ctx, variant, path) - }); + let self_ty = + (|| ctx.sema.to_def(ctx.impl_def.as_ref()?)?.self_ty(ctx.db).as_adt())(); + let complete_self = self_ty == Some(adt); + + match adt { + hir::Adt::Struct(strukt) => { + let path = ctx + .module + .find_use_path(ctx.db, hir::ModuleDef::from(strukt)) + .filter(|it| it.len() > 1); + + acc.add_struct_literal(ctx, strukt, path, None); + + if complete_self { + acc.add_struct_literal(ctx, strukt, None, Some(hir::known::SELF_TYPE)); + } + } + hir::Adt::Union(un) => { + let path = ctx + .module + .find_use_path(ctx.db, hir::ModuleDef::from(un)) + .filter(|it| it.len() > 1); + + acc.add_union_literal(ctx, un, path, None); + if complete_self { + acc.add_union_literal(ctx, un, None, Some(hir::known::SELF_TYPE)); + } + } + hir::Adt::Enum(e) => { + super::enum_variants_with_paths(acc, ctx, e, |acc, ctx, variant, path| { + acc.add_qualified_enum_variant(ctx, variant, path) + }); + } + } } ctx.process_all_names(&mut |name, def| { if scope_def_applicable(def) { @@ -180,20 +217,18 @@ pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext) if !is_func_update { let mut add_keyword = |kw, snippet| acc.add_keyword_snippet(ctx, kw, snippet); - if ctx.expects_expression() { - if !in_block_expr { - add_keyword("unsafe", "unsafe {\n $0\n}"); - } - add_keyword("match", "match $1 {\n $0\n}"); - add_keyword("while", "while $1 {\n $0\n}"); - add_keyword("while let", "while let $1 = $2 {\n $0\n}"); - add_keyword("loop", "loop {\n $0\n}"); - add_keyword("if", "if $1 {\n $0\n}"); - add_keyword("if let", "if let $1 = $2 {\n $0\n}"); - add_keyword("for", "for $1 in $2 {\n $0\n}"); - add_keyword("true", "true"); - add_keyword("false", "false"); + if !in_block_expr { + add_keyword("unsafe", "unsafe {\n $0\n}"); } + add_keyword("match", "match $1 {\n $0\n}"); + add_keyword("while", "while $1 {\n $0\n}"); + add_keyword("while let", "while let $1 = $2 {\n $0\n}"); + add_keyword("loop", "loop {\n $0\n}"); + add_keyword("if", "if $1 {\n $0\n}"); + add_keyword("if let", "if let $1 = $2 {\n $0\n}"); + add_keyword("for", "for $1 in $2 {\n $0\n}"); + add_keyword("true", "true"); + add_keyword("false", "false"); if ctx.previous_token_is(T![if]) || ctx.previous_token_is(T![while]) @@ -207,7 +242,7 @@ pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext) add_keyword("else if", "else if $1 {\n $0\n}"); } - if ctx.expects_ident_ref_expr() { + if wants_mut_token { add_keyword("mut", "mut "); } |