Move CompletionContext::function_def into PathKind::Expr

This commit is contained in:
Lukas Wirth 2022-06-18 09:54:03 +02:00
parent 309ecdd71c
commit 7369e5120d
4 changed files with 82 additions and 39 deletions

View file

@ -46,27 +46,26 @@ pub(crate) fn complete_undotted_self(
if !ctx.config.enable_self_on_the_fly {
return;
}
match path_ctx {
PathCompletionCtx { qualified: Qualified::No, kind: PathKind::Expr { .. }, .. }
if path_ctx.is_trivial_path() && ctx.qualifier_ctx.none() => {}
let self_param = match path_ctx {
PathCompletionCtx {
qualified: Qualified::No,
kind: PathKind::Expr { self_param: Some(self_param), .. },
..
} if path_ctx.is_trivial_path() && ctx.qualifier_ctx.none() => self_param,
_ => return,
}
};
if let Some(func) = ctx.function_def.as_ref().and_then(|fn_| ctx.sema.to_def(fn_)) {
if let Some(self_) = func.self_param(ctx.db) {
let ty = self_.ty(ctx.db);
complete_fields(
acc,
ctx,
&ty,
|acc, field, ty| acc.add_field(ctx, Some(hir::known::SELF_PARAM), field, &ty),
|acc, field, ty| acc.add_tuple_field(ctx, Some(hir::known::SELF_PARAM), field, &ty),
);
complete_methods(ctx, &ty, |func| {
acc.add_method(ctx, func, Some(hir::known::SELF_PARAM), None)
});
}
}
let ty = self_param.ty(ctx.db);
complete_fields(
acc,
ctx,
&ty,
|acc, field, ty| acc.add_field(ctx, Some(hir::known::SELF_PARAM), field, &ty),
|acc, field, ty| acc.add_tuple_field(ctx, Some(hir::known::SELF_PARAM), field, &ty),
);
complete_methods(ctx, &ty, |func| {
acc.add_method(ctx, func, Some(hir::known::SELF_PARAM), None)
});
}
fn complete_fields(

View file

@ -14,7 +14,9 @@ pub(crate) fn complete_expr_path(
path_ctx: &PathCompletionCtx,
) {
let _p = profile::span("complete_expr_path");
if !ctx.qualifier_ctx.none() {
return;
}
let (
qualified,
in_block_expr,
@ -23,6 +25,7 @@ pub(crate) fn complete_expr_path(
after_if_expr,
wants_mut_token,
in_condition,
ty,
) = match path_ctx {
&PathCompletionCtx {
kind:
@ -33,10 +36,12 @@ pub(crate) fn complete_expr_path(
in_condition,
ref ref_expr_parent,
ref is_func_update,
ref innermost_ret_ty,
..
},
ref qualified,
..
} if ctx.qualifier_ctx.none() => (
} => (
qualified,
in_block_expr,
in_loop_body,
@ -44,6 +49,7 @@ pub(crate) fn complete_expr_path(
after_if_expr,
ref_expr_parent.as_ref().map(|it| it.mut_token().is_none()).unwrap_or(false),
in_condition,
innermost_ret_ty,
),
_ => return,
};
@ -252,10 +258,10 @@ pub(crate) fn complete_expr_path(
}
}
if let Some(fn_def) = &ctx.function_def {
if let Some(ty) = ty {
add_keyword(
"return",
match (in_block_expr, fn_def.ret_type().is_some()) {
match (in_block_expr, ty.is_unit()) {
(true, true) => "return ;",
(true, false) => "return;",
(false, true) => "return $0",

View file

@ -95,6 +95,8 @@ pub(super) enum PathKind {
in_condition: bool,
ref_expr_parent: Option<ast::RefExpr>,
is_func_update: Option<ast::RecordExpr>,
self_param: Option<hir::SelfParam>,
innermost_ret_ty: Option<hir::Type>,
},
Type {
location: TypeLocation,
@ -317,9 +319,6 @@ pub(crate) struct CompletionContext<'a> {
/// The expected type of what we are completing.
pub(super) expected_type: Option<Type>,
/// The parent function of the cursor position if it exists.
// FIXME: This probably doesn't belong here
pub(super) function_def: Option<ast::Fn>,
/// The parent impl of the cursor position if it exists.
// FIXME: This probably doesn't belong here
pub(super) impl_def: Option<ast::Impl>,
@ -500,7 +499,6 @@ impl<'a> CompletionContext<'a> {
module,
expected_name: None,
expected_type: None,
function_def: None,
impl_def: None,
incomplete_let: false,
previous_token: None,

View file

@ -404,18 +404,6 @@ impl<'a> CompletionContext<'a> {
ast::Item::Impl(impl_) => Some(impl_),
_ => None,
});
self.function_def = self
.sema
.token_ancestors_with_macros(self.token.clone())
.take_while(|it| {
it.kind() != SyntaxKind::SOURCE_FILE && it.kind() != SyntaxKind::MODULE
})
.filter_map(ast::Item::cast)
.take(2)
.find_map(|it| match it {
ast::Item::Fn(fn_) => Some(fn_),
_ => None,
});
match name_like {
ast::NameLike::Lifetime(lifetime) => {
@ -727,6 +715,56 @@ impl<'a> CompletionContext<'a> {
let after_if_expr = after_if_expr(it.clone());
let ref_expr_parent =
path.as_single_name_ref().and_then(|_| it.parent()).and_then(ast::RefExpr::cast);
let (innermost_ret_ty, self_param) = {
let find_ret_ty = |it: SyntaxNode| {
if let Some(item) = ast::Item::cast(it.clone()) {
match item {
ast::Item::Fn(f) => {
Some(sema.to_def(&f).map(|it| it.ret_type(sema.db)))
}
ast::Item::MacroCall(_) => None,
_ => Some(None),
}
} else {
let expr = ast::Expr::cast(it)?;
let callable = match expr {
// FIXME
// ast::Expr::BlockExpr(b) if b.async_token().is_some() || b.try_token().is_some() => sema.type_of_expr(b),
ast::Expr::ClosureExpr(_) => sema.type_of_expr(&expr),
_ => return None,
};
Some(
callable
.and_then(|c| c.adjusted().as_callable(sema.db))
.map(|it| it.return_type()),
)
}
};
let find_fn_self_param = |it| match it {
ast::Item::Fn(fn_) => {
Some(sema.to_def(&fn_).and_then(|it| it.self_param(sema.db)))
}
ast::Item::MacroCall(_) => None,
_ => Some(None),
};
match dbg!(find_node_in_file_compensated(original_file, &expr)) {
Some(it) => {
let innermost_ret_ty = sema
.ancestors_with_macros(it.syntax().clone())
.find_map(find_ret_ty)
.flatten();
let self_param = sema
.ancestors_with_macros(it.syntax().clone())
.filter_map(ast::Item::cast)
.find_map(find_fn_self_param)
.flatten();
(innermost_ret_ty, self_param)
}
None => (None, None),
}
};
let is_func_update = func_update_record(it);
let in_condition = is_in_condition(&expr);
@ -737,6 +775,8 @@ impl<'a> CompletionContext<'a> {
in_condition,
ref_expr_parent,
is_func_update,
innermost_ret_ty,
self_param,
}
};
let make_path_kind_type = |ty: ast::Type| {