Skip to content

Commit 817f46b

Browse files
committed
Auto merge of rust-lang#12580 - Veykril:completion, r=Veykril
internal: Move more things out of `CompletionContext::function_def` into more specific parts
2 parents 7a87f81 + f271b18 commit 817f46b

File tree

9 files changed

+226
-112
lines changed

9 files changed

+226
-112
lines changed

crates/ide-completion/src/completions.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use std::iter;
2424

2525
use hir::{db::HirDatabase, known, ScopeDef};
2626
use ide_db::SymbolKind;
27+
use syntax::ast;
2728

2829
use crate::{
2930
context::Visible,
@@ -110,12 +111,18 @@ impl Completions {
110111
["self", "super", "crate"].into_iter().for_each(|kw| self.add_keyword(ctx, kw));
111112
}
112113

113-
pub(crate) fn add_keyword_snippet(&mut self, ctx: &CompletionContext, kw: &str, snippet: &str) {
114+
pub(crate) fn add_keyword_snippet_expr(
115+
&mut self,
116+
ctx: &CompletionContext,
117+
kw: &str,
118+
snippet: &str,
119+
incomplete_let: bool,
120+
) {
114121
let mut item = CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), kw);
115122

116123
match ctx.config.snippet_cap {
117124
Some(cap) => {
118-
if snippet.ends_with('}') && ctx.incomplete_let {
125+
if snippet.ends_with('}') && incomplete_let {
119126
// complete block expression snippets with a trailing semicolon, if inside an incomplete let
120127
cov_mark::hit!(let_semi);
121128
item.insert_snippet(cap, format!("{};", snippet));
@@ -130,6 +137,16 @@ impl Completions {
130137
item.add_to(self);
131138
}
132139

140+
pub(crate) fn add_keyword_snippet(&mut self, ctx: &CompletionContext, kw: &str, snippet: &str) {
141+
let mut item = CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), kw);
142+
143+
match ctx.config.snippet_cap {
144+
Some(cap) => item.insert_snippet(cap, snippet),
145+
None => item.insert_text(if snippet.contains('$') { kw } else { snippet }),
146+
};
147+
item.add_to(self);
148+
}
149+
133150
pub(crate) fn add_crate_roots(&mut self, ctx: &CompletionContext) {
134151
ctx.process_all_names(&mut |name, res| match res {
135152
ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) if m.is_crate_root(ctx.db) => {
@@ -393,11 +410,12 @@ fn enum_variants_with_paths(
393410
acc: &mut Completions,
394411
ctx: &CompletionContext,
395412
enum_: hir::Enum,
413+
impl_: &Option<ast::Impl>,
396414
cb: impl Fn(&mut Completions, &CompletionContext, hir::Variant, hir::ModPath),
397415
) {
398416
let variants = enum_.variants(ctx.db);
399417

400-
if let Some(impl_) = ctx.impl_def.as_ref().and_then(|impl_| ctx.sema.to_def(impl_)) {
418+
if let Some(impl_) = impl_.as_ref().and_then(|impl_| ctx.sema.to_def(impl_)) {
401419
if impl_.self_ty(ctx.db).as_adt() == Some(hir::Adt::Enum(enum_)) {
402420
for &variant in &variants {
403421
let self_path = hir::ModPath::from_segments(

crates/ide-completion/src/completions/dot.rs

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -46,27 +46,26 @@ pub(crate) fn complete_undotted_self(
4646
if !ctx.config.enable_self_on_the_fly {
4747
return;
4848
}
49-
match path_ctx {
50-
PathCompletionCtx { qualified: Qualified::No, kind: PathKind::Expr { .. }, .. }
51-
if path_ctx.is_trivial_path() && ctx.qualifier_ctx.none() => {}
49+
let self_param = match path_ctx {
50+
PathCompletionCtx {
51+
qualified: Qualified::No,
52+
kind: PathKind::Expr { self_param: Some(self_param), .. },
53+
..
54+
} if path_ctx.is_trivial_path() && ctx.qualifier_ctx.none() => self_param,
5255
_ => return,
53-
}
56+
};
5457

55-
if let Some(func) = ctx.function_def.as_ref().and_then(|fn_| ctx.sema.to_def(fn_)) {
56-
if let Some(self_) = func.self_param(ctx.db) {
57-
let ty = self_.ty(ctx.db);
58-
complete_fields(
59-
acc,
60-
ctx,
61-
&ty,
62-
|acc, field, ty| acc.add_field(ctx, Some(hir::known::SELF_PARAM), field, &ty),
63-
|acc, field, ty| acc.add_tuple_field(ctx, Some(hir::known::SELF_PARAM), field, &ty),
64-
);
65-
complete_methods(ctx, &ty, |func| {
66-
acc.add_method(ctx, func, Some(hir::known::SELF_PARAM), None)
67-
});
68-
}
69-
}
58+
let ty = self_param.ty(ctx.db);
59+
complete_fields(
60+
acc,
61+
ctx,
62+
&ty,
63+
|acc, field, ty| acc.add_field(ctx, Some(hir::known::SELF_PARAM), field, &ty),
64+
|acc, field, ty| acc.add_tuple_field(ctx, Some(hir::known::SELF_PARAM), field, &ty),
65+
);
66+
complete_methods(ctx, &ty, |func| {
67+
acc.add_method(ctx, func, Some(hir::known::SELF_PARAM), None)
68+
});
7069
}
7170

7271
fn complete_fields(

crates/ide-completion/src/completions/expr.rs

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ pub(crate) fn complete_expr_path(
1414
path_ctx: &PathCompletionCtx,
1515
) {
1616
let _p = profile::span("complete_expr_path");
17-
17+
if !ctx.qualifier_ctx.none() {
18+
return;
19+
}
1820
let (
1921
qualified,
2022
in_block_expr,
@@ -23,6 +25,9 @@ pub(crate) fn complete_expr_path(
2325
after_if_expr,
2426
wants_mut_token,
2527
in_condition,
28+
ty,
29+
incomplete_let,
30+
impl_,
2631
) = match path_ctx {
2732
&PathCompletionCtx {
2833
kind:
@@ -31,19 +36,26 @@ pub(crate) fn complete_expr_path(
3136
in_loop_body,
3237
after_if_expr,
3338
in_condition,
39+
incomplete_let,
3440
ref ref_expr_parent,
3541
ref is_func_update,
42+
ref innermost_ret_ty,
43+
ref impl_,
44+
..
3645
},
3746
ref qualified,
3847
..
39-
} if ctx.qualifier_ctx.none() => (
48+
} => (
4049
qualified,
4150
in_block_expr,
4251
in_loop_body,
4352
is_func_update.is_some(),
4453
after_if_expr,
4554
ref_expr_parent.as_ref().map(|it| it.mut_token().is_none()).unwrap_or(false),
4655
in_condition,
56+
innermost_ret_ty,
57+
incomplete_let,
58+
impl_,
4759
),
4860
_ => return,
4961
};
@@ -172,8 +184,7 @@ pub(crate) fn complete_expr_path(
172184
if let Some(adt) =
173185
ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt())
174186
{
175-
let self_ty =
176-
(|| ctx.sema.to_def(ctx.impl_def.as_ref()?)?.self_ty(ctx.db).as_adt())();
187+
let self_ty = (|| ctx.sema.to_def(impl_.as_ref()?)?.self_ty(ctx.db).as_adt())();
177188
let complete_self = self_ty == Some(adt);
178189

179190
match adt {
@@ -201,9 +212,15 @@ pub(crate) fn complete_expr_path(
201212
}
202213
}
203214
hir::Adt::Enum(e) => {
204-
super::enum_variants_with_paths(acc, ctx, e, |acc, ctx, variant, path| {
205-
acc.add_qualified_enum_variant(ctx, variant, path)
206-
});
215+
super::enum_variants_with_paths(
216+
acc,
217+
ctx,
218+
e,
219+
impl_,
220+
|acc, ctx, variant, path| {
221+
acc.add_qualified_enum_variant(ctx, variant, path)
222+
},
223+
);
207224
}
208225
}
209226
}
@@ -214,7 +231,8 @@ pub(crate) fn complete_expr_path(
214231
});
215232

216233
if !is_func_update {
217-
let mut add_keyword = |kw, snippet| acc.add_keyword_snippet(ctx, kw, snippet);
234+
let mut add_keyword =
235+
|kw, snippet| acc.add_keyword_snippet_expr(ctx, kw, snippet, incomplete_let);
218236

219237
if !in_block_expr {
220238
add_keyword("unsafe", "unsafe {\n $0\n}");
@@ -252,10 +270,10 @@ pub(crate) fn complete_expr_path(
252270
}
253271
}
254272

255-
if let Some(fn_def) = &ctx.function_def {
273+
if let Some(ty) = ty {
256274
add_keyword(
257275
"return",
258-
match (in_block_expr, fn_def.ret_type().is_some()) {
276+
match (in_block_expr, ty.is_unit()) {
259277
(true, true) => "return ;",
260278
(true, false) => "return;",
261279
(false, true) => "return $0",

crates/ide-completion/src/completions/fn_param.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ pub(crate) fn complete_fn_param(
2424
ctx: &CompletionContext,
2525
pattern_ctx: &PatternContext,
2626
) -> Option<()> {
27-
let (param_list, _, param_kind) = match pattern_ctx {
28-
PatternContext { param_ctx: Some(kind), .. } => kind,
27+
let ((param_list, _, param_kind), impl_) = match pattern_ctx {
28+
PatternContext { param_ctx: Some(kind), impl_, .. } => (kind, impl_),
2929
_ => return None,
3030
};
3131

@@ -45,7 +45,7 @@ pub(crate) fn complete_fn_param(
4545

4646
match param_kind {
4747
ParamKind::Function(function) => {
48-
fill_fn_params(ctx, function, param_list, add_new_item_to_acc);
48+
fill_fn_params(ctx, function, param_list, impl_, add_new_item_to_acc);
4949
}
5050
ParamKind::Closure(closure) => {
5151
let stmt_list = closure.syntax().ancestors().find_map(ast::StmtList::cast)?;
@@ -62,6 +62,7 @@ fn fill_fn_params(
6262
ctx: &CompletionContext,
6363
function: &ast::Fn,
6464
param_list: &ast::ParamList,
65+
impl_: &Option<ast::Impl>,
6566
mut add_new_item_to_acc: impl FnMut(&str),
6667
) {
6768
let mut file_params = FxHashMap::default();
@@ -104,7 +105,7 @@ fn fill_fn_params(
104105
}
105106
remove_duplicated(&mut file_params, param_list.params());
106107
let self_completion_items = ["self", "&self", "mut self", "&mut self"];
107-
if should_add_self_completions(ctx, param_list) {
108+
if should_add_self_completions(param_list, impl_) {
108109
self_completion_items.into_iter().for_each(|self_item| add_new_item_to_acc(self_item));
109110
}
110111

@@ -155,11 +156,10 @@ fn remove_duplicated(
155156
})
156157
}
157158

158-
fn should_add_self_completions(ctx: &CompletionContext, param_list: &ast::ParamList) -> bool {
159-
let inside_impl = ctx.impl_def.is_some();
159+
fn should_add_self_completions(param_list: &ast::ParamList, impl_: &Option<ast::Impl>) -> bool {
160160
let no_params = param_list.params().next().is_none() && param_list.self_param().is_none();
161161

162-
inside_impl && no_params
162+
impl_.is_some() && no_params
163163
}
164164

165165
fn comma_wrapper(ctx: &CompletionContext) -> Option<(impl Fn(&str) -> String, TextRange)> {

crates/ide-completion/src/completions/item_list.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ fn add_keywords(acc: &mut Completions, ctx: &CompletionContext, kind: Option<&It
6666
let in_assoc_non_trait_impl = matches!(kind, Some(ItemListKind::Impl | ItemListKind::Trait));
6767
let in_extern_block = matches!(kind, Some(ItemListKind::ExternBlock));
6868
let in_trait = matches!(kind, Some(ItemListKind::Trait));
69-
let in_trait_impl = matches!(kind, Some(ItemListKind::TraitImpl));
69+
let in_trait_impl = matches!(kind, Some(ItemListKind::TraitImpl(_)));
7070
let in_inherent_impl = matches!(kind, Some(ItemListKind::Impl));
7171
let no_qualifiers = ctx.qualifier_ctx.vis_node.is_none();
7272
let in_block = matches!(kind, None);

crates/ide-completion/src/completions/item_list/trait_impl.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ pub(crate) fn complete_trait_impl_name(
8181
kind,
8282
replacement_range(ctx, &item),
8383
// item -> ASSOC_ITEM_LIST -> IMPL
84-
ast::Impl::cast(item.parent()?.parent()?)?,
84+
&ast::Impl::cast(item.parent()?.parent()?)?,
8585
);
8686
Some(())
8787
}
@@ -97,7 +97,7 @@ pub(crate) fn complete_trait_impl_name_ref(
9797
kind:
9898
NameRefKind::Path(
9999
path_ctx @ PathCompletionCtx {
100-
kind: PathKind::Item { kind: ItemListKind::TraitImpl },
100+
kind: PathKind::Item { kind: ItemListKind::TraitImpl(Some(impl_)) },
101101
..
102102
},
103103
),
@@ -109,7 +109,7 @@ pub(crate) fn complete_trait_impl_name_ref(
109109
Some(name) => name.syntax().text_range(),
110110
None => ctx.source_range(),
111111
},
112-
ctx.impl_def.clone()?,
112+
impl_,
113113
),
114114
_ => (),
115115
}
@@ -121,10 +121,10 @@ fn complete_trait_impl(
121121
ctx: &CompletionContext,
122122
kind: ImplCompletionKind,
123123
replacement_range: TextRange,
124-
impl_def: ast::Impl,
124+
impl_def: &ast::Impl,
125125
) {
126-
if let Some(hir_impl) = ctx.sema.to_def(&impl_def) {
127-
get_missing_assoc_items(&ctx.sema, &impl_def).into_iter().for_each(|item| {
126+
if let Some(hir_impl) = ctx.sema.to_def(impl_def) {
127+
get_missing_assoc_items(&ctx.sema, impl_def).into_iter().for_each(|item| {
128128
use self::ImplCompletionKind::*;
129129
match (item, kind) {
130130
(hir::AssocItem::Function(func), All | Fn) => {

crates/ide-completion/src/completions/pattern.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,15 @@ pub(crate) fn complete_pattern(
5151
ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt())
5252
{
5353
if refutable || single_variant_enum(e) {
54-
super::enum_variants_with_paths(acc, ctx, e, |acc, ctx, variant, path| {
55-
acc.add_qualified_variant_pat(ctx, variant, path);
56-
});
54+
super::enum_variants_with_paths(
55+
acc,
56+
ctx,
57+
e,
58+
&patctx.impl_,
59+
|acc, ctx, variant, path| {
60+
acc.add_qualified_variant_pat(ctx, variant, path);
61+
},
62+
);
5763
}
5864
}
5965

crates/ide-completion/src/context.rs

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,12 @@ pub(super) enum PathKind {
9393
after_if_expr: bool,
9494
/// Whether this expression is the direct condition of an if or while expression
9595
in_condition: bool,
96+
incomplete_let: bool,
9697
ref_expr_parent: Option<ast::RefExpr>,
9798
is_func_update: Option<ast::RecordExpr>,
99+
self_param: Option<hir::SelfParam>,
100+
innermost_ret_ty: Option<hir::Type>,
101+
impl_: Option<ast::Impl>,
98102
},
99103
Type {
100104
location: TypeLocation,
@@ -140,12 +144,12 @@ pub(crate) enum TypeAscriptionTarget {
140144
}
141145

142146
/// The kind of item list a [`PathKind::Item`] belongs to.
143-
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
147+
#[derive(Debug, PartialEq, Eq)]
144148
pub(super) enum ItemListKind {
145149
SourceFile,
146150
Module,
147151
Impl,
148-
TraitImpl,
152+
TraitImpl(Option<ast::Impl>),
149153
Trait,
150154
ExternBlock,
151155
}
@@ -176,6 +180,7 @@ pub(super) struct PatternContext {
176180
pub(super) mut_token: Option<SyntaxToken>,
177181
/// The record pattern this name or ref is a field of
178182
pub(super) record_pat: Option<ast::RecordPat>,
183+
pub(super) impl_: Option<ast::Impl>,
179184
}
180185

181186
/// The state of the lifetime we are completing.
@@ -317,16 +322,6 @@ pub(crate) struct CompletionContext<'a> {
317322
/// The expected type of what we are completing.
318323
pub(super) expected_type: Option<Type>,
319324

320-
/// The parent function of the cursor position if it exists.
321-
// FIXME: This probably doesn't belong here
322-
pub(super) function_def: Option<ast::Fn>,
323-
/// The parent impl of the cursor position if it exists.
324-
// FIXME: This probably doesn't belong here
325-
pub(super) impl_def: Option<ast::Impl>,
326-
/// Are we completing inside a let statement with a missing semicolon?
327-
// FIXME: This should be part of PathKind::Expr
328-
pub(super) incomplete_let: bool,
329-
330325
// FIXME: This shouldn't exist
331326
pub(super) previous_token: Option<SyntaxToken>,
332327

@@ -500,9 +495,6 @@ impl<'a> CompletionContext<'a> {
500495
module,
501496
expected_name: None,
502497
expected_type: None,
503-
function_def: None,
504-
impl_def: None,
505-
incomplete_let: false,
506498
previous_token: None,
507499
// dummy value, will be overwritten
508500
ident_ctx: IdentContext::UnexpandedAttrTT { fake_attribute_under_caret: None },

0 commit comments

Comments
 (0)