mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-15 22:54:00 +00:00
Auto merge of #12773 - Veykril:self-compl, r=Veykril
fix: Improve self param completion applicability Fixes https://github.com/rust-lang/rust-analyzer/issues/9522
This commit is contained in:
commit
96481b7786
6 changed files with 124 additions and 18 deletions
|
@ -5,11 +5,11 @@ use ide_db::FxHashMap;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
algo,
|
algo,
|
||||||
ast::{self, HasModuleItem},
|
ast::{self, HasModuleItem},
|
||||||
match_ast, AstNode, Direction, SyntaxKind, TextRange,
|
match_ast, AstNode, Direction, SyntaxKind, TextRange, TextSize,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::{ParamKind, PatternContext},
|
context::{ParamContext, ParamKind, PatternContext},
|
||||||
CompletionContext, CompletionItem, CompletionItemKind, Completions,
|
CompletionContext, CompletionItem, CompletionItemKind, Completions,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ pub(crate) fn complete_fn_param(
|
||||||
ctx: &CompletionContext,
|
ctx: &CompletionContext,
|
||||||
pattern_ctx: &PatternContext,
|
pattern_ctx: &PatternContext,
|
||||||
) -> Option<()> {
|
) -> Option<()> {
|
||||||
let ((param_list, _, param_kind), impl_) = match pattern_ctx {
|
let (ParamContext { param_list, kind, .. }, impl_) = match pattern_ctx {
|
||||||
PatternContext { param_ctx: Some(kind), impl_, .. } => (kind, impl_),
|
PatternContext { param_ctx: Some(kind), impl_, .. } => (kind, impl_),
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
@ -43,7 +43,7 @@ pub(crate) fn complete_fn_param(
|
||||||
item.add_to(acc)
|
item.add_to(acc)
|
||||||
};
|
};
|
||||||
|
|
||||||
match param_kind {
|
match kind {
|
||||||
ParamKind::Function(function) => {
|
ParamKind::Function(function) => {
|
||||||
fill_fn_params(ctx, function, param_list, impl_, add_new_item_to_acc);
|
fill_fn_params(ctx, function, param_list, impl_, add_new_item_to_acc);
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ fn fill_fn_params(
|
||||||
}
|
}
|
||||||
remove_duplicated(&mut file_params, param_list.params());
|
remove_duplicated(&mut file_params, param_list.params());
|
||||||
let self_completion_items = ["self", "&self", "mut self", "&mut self"];
|
let self_completion_items = ["self", "&self", "mut self", "&mut self"];
|
||||||
if should_add_self_completions(param_list, impl_) {
|
if should_add_self_completions(ctx.token.text_range().start(), param_list, impl_) {
|
||||||
self_completion_items.into_iter().for_each(|self_item| add_new_item_to_acc(self_item));
|
self_completion_items.into_iter().for_each(|self_item| add_new_item_to_acc(self_item));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,10 +156,18 @@ fn remove_duplicated(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_add_self_completions(param_list: &ast::ParamList, impl_: &Option<ast::Impl>) -> bool {
|
fn should_add_self_completions(
|
||||||
let no_params = param_list.params().next().is_none() && param_list.self_param().is_none();
|
cursor: TextSize,
|
||||||
|
param_list: &ast::ParamList,
|
||||||
impl_.is_some() && no_params
|
impl_: &Option<ast::Impl>,
|
||||||
|
) -> bool {
|
||||||
|
if impl_.is_none() || param_list.self_param().is_some() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
match param_list.params().next() {
|
||||||
|
Some(first) => first.pat().map_or(false, |pat| pat.syntax().text_range().contains(cursor)),
|
||||||
|
None => true,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn comma_wrapper(ctx: &CompletionContext) -> Option<(impl Fn(&str) -> String, TextRange)> {
|
fn comma_wrapper(ctx: &CompletionContext) -> Option<(impl Fn(&str) -> String, TextRange)> {
|
||||||
|
|
|
@ -438,6 +438,10 @@ impl Test for T {
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
sp Self
|
sp Self
|
||||||
st T
|
st T
|
||||||
|
bn &mut self
|
||||||
|
bn &self
|
||||||
|
bn mut self
|
||||||
|
bn self
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -199,7 +199,7 @@ pub(super) enum Qualified {
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub(super) struct PatternContext {
|
pub(super) struct PatternContext {
|
||||||
pub(super) refutability: PatternRefutability,
|
pub(super) refutability: PatternRefutability,
|
||||||
pub(super) param_ctx: Option<(ast::ParamList, ast::Param, ParamKind)>,
|
pub(super) param_ctx: Option<ParamContext>,
|
||||||
pub(super) has_type_ascription: bool,
|
pub(super) has_type_ascription: bool,
|
||||||
pub(super) parent_pat: Option<ast::Pat>,
|
pub(super) parent_pat: Option<ast::Pat>,
|
||||||
pub(super) ref_token: Option<SyntaxToken>,
|
pub(super) ref_token: Option<SyntaxToken>,
|
||||||
|
@ -209,6 +209,13 @@ pub(super) struct PatternContext {
|
||||||
pub(super) impl_: Option<ast::Impl>,
|
pub(super) impl_: Option<ast::Impl>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub(super) struct ParamContext {
|
||||||
|
pub(super) param_list: ast::ParamList,
|
||||||
|
pub(super) param: ast::Param,
|
||||||
|
pub(super) kind: ParamKind,
|
||||||
|
}
|
||||||
|
|
||||||
/// The state of the lifetime we are completing.
|
/// The state of the lifetime we are completing.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(super) struct LifetimeContext {
|
pub(super) struct LifetimeContext {
|
||||||
|
|
|
@ -13,8 +13,9 @@ use syntax::{
|
||||||
use crate::context::{
|
use crate::context::{
|
||||||
AttrCtx, CompletionAnalysis, CompletionContext, DotAccess, DotAccessKind, ExprCtx,
|
AttrCtx, CompletionAnalysis, CompletionContext, DotAccess, DotAccessKind, ExprCtx,
|
||||||
ItemListKind, LifetimeContext, LifetimeKind, NameContext, NameKind, NameRefContext,
|
ItemListKind, LifetimeContext, LifetimeKind, NameContext, NameKind, NameRefContext,
|
||||||
NameRefKind, ParamKind, PathCompletionCtx, PathKind, PatternContext, PatternRefutability,
|
NameRefKind, ParamContext, ParamKind, PathCompletionCtx, PathKind, PatternContext,
|
||||||
Qualified, QualifierCtx, TypeAscriptionTarget, TypeLocation, COMPLETION_MARKER,
|
PatternRefutability, Qualified, QualifierCtx, TypeAscriptionTarget, TypeLocation,
|
||||||
|
COMPLETION_MARKER,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<'a> CompletionContext<'a> {
|
impl<'a> CompletionContext<'a> {
|
||||||
|
@ -990,7 +991,7 @@ fn pattern_context_for(
|
||||||
original_file: &SyntaxNode,
|
original_file: &SyntaxNode,
|
||||||
pat: ast::Pat,
|
pat: ast::Pat,
|
||||||
) -> PatternContext {
|
) -> PatternContext {
|
||||||
let mut is_param = None;
|
let mut param_ctx = None;
|
||||||
let (refutability, has_type_ascription) =
|
let (refutability, has_type_ascription) =
|
||||||
pat
|
pat
|
||||||
.syntax()
|
.syntax()
|
||||||
|
@ -1003,7 +1004,7 @@ fn pattern_context_for(
|
||||||
ast::LetStmt(let_) => return (PatternRefutability::Irrefutable, let_.ty().is_some()),
|
ast::LetStmt(let_) => return (PatternRefutability::Irrefutable, let_.ty().is_some()),
|
||||||
ast::Param(param) => {
|
ast::Param(param) => {
|
||||||
let has_type_ascription = param.ty().is_some();
|
let has_type_ascription = param.ty().is_some();
|
||||||
is_param = (|| {
|
param_ctx = (|| {
|
||||||
let fake_param_list = param.syntax().parent().and_then(ast::ParamList::cast)?;
|
let fake_param_list = param.syntax().parent().and_then(ast::ParamList::cast)?;
|
||||||
let param_list = find_node_in_file_compensated(sema, original_file, &fake_param_list)?;
|
let param_list = find_node_in_file_compensated(sema, original_file, &fake_param_list)?;
|
||||||
let param_list_owner = param_list.syntax().parent()?;
|
let param_list_owner = param_list.syntax().parent()?;
|
||||||
|
@ -1014,7 +1015,9 @@ fn pattern_context_for(
|
||||||
_ => return None,
|
_ => return None,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Some((param_list, param, kind))
|
Some(ParamContext {
|
||||||
|
param_list, param, kind
|
||||||
|
})
|
||||||
})();
|
})();
|
||||||
return (PatternRefutability::Irrefutable, has_type_ascription)
|
return (PatternRefutability::Irrefutable, has_type_ascription)
|
||||||
},
|
},
|
||||||
|
@ -1033,7 +1036,7 @@ fn pattern_context_for(
|
||||||
|
|
||||||
PatternContext {
|
PatternContext {
|
||||||
refutability,
|
refutability,
|
||||||
param_ctx: is_param,
|
param_ctx,
|
||||||
has_type_ascription,
|
has_type_ascription,
|
||||||
parent_pat: pat.syntax().parent().and_then(ast::Pat::cast),
|
parent_pat: pat.syntax().parent().and_then(ast::Pat::cast),
|
||||||
mut_token,
|
mut_token,
|
||||||
|
|
|
@ -6,7 +6,7 @@ use itertools::Itertools;
|
||||||
use syntax::SmolStr;
|
use syntax::SmolStr;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::{ParamKind, PatternContext},
|
context::{ParamContext, ParamKind, PatternContext},
|
||||||
render::{
|
render::{
|
||||||
variant::{format_literal_label, visible_fields},
|
variant::{format_literal_label, visible_fields},
|
||||||
RenderContext,
|
RenderContext,
|
||||||
|
@ -102,7 +102,7 @@ fn render_pat(
|
||||||
let needs_ascription = matches!(
|
let needs_ascription = matches!(
|
||||||
pattern_ctx,
|
pattern_ctx,
|
||||||
PatternContext {
|
PatternContext {
|
||||||
param_ctx: Some((.., ParamKind::Function(_))),
|
param_ctx: Some(ParamContext { kind: ParamKind::Function(_), .. }),
|
||||||
has_type_ascription: false,
|
has_type_ascription: false,
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
|
|
@ -630,3 +630,87 @@ fn f(v: u32) {
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn in_method_param() {
|
||||||
|
check_empty(
|
||||||
|
r#"
|
||||||
|
struct Ty(u8);
|
||||||
|
|
||||||
|
impl Ty {
|
||||||
|
fn foo($0)
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
sp Self
|
||||||
|
st Ty
|
||||||
|
bn &mut self
|
||||||
|
bn &self
|
||||||
|
bn Self(…) Self($1): Self$0
|
||||||
|
bn Ty(…) Ty($1): Ty$0
|
||||||
|
bn mut self
|
||||||
|
bn self
|
||||||
|
kw mut
|
||||||
|
kw ref
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
check_empty(
|
||||||
|
r#"
|
||||||
|
struct Ty(u8);
|
||||||
|
|
||||||
|
impl Ty {
|
||||||
|
fn foo(s$0)
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
sp Self
|
||||||
|
st Ty
|
||||||
|
bn &mut self
|
||||||
|
bn &self
|
||||||
|
bn Self(…) Self($1): Self$0
|
||||||
|
bn Ty(…) Ty($1): Ty$0
|
||||||
|
bn mut self
|
||||||
|
bn self
|
||||||
|
kw mut
|
||||||
|
kw ref
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
check_empty(
|
||||||
|
r#"
|
||||||
|
struct Ty(u8);
|
||||||
|
|
||||||
|
impl Ty {
|
||||||
|
fn foo(s$0, foo: u8)
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
sp Self
|
||||||
|
st Ty
|
||||||
|
bn &mut self
|
||||||
|
bn &self
|
||||||
|
bn Self(…) Self($1): Self$0
|
||||||
|
bn Ty(…) Ty($1): Ty$0
|
||||||
|
bn mut self
|
||||||
|
bn self
|
||||||
|
kw mut
|
||||||
|
kw ref
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
check_empty(
|
||||||
|
r#"
|
||||||
|
struct Ty(u8);
|
||||||
|
|
||||||
|
impl Ty {
|
||||||
|
fn foo(foo: u8, b$0)
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
sp Self
|
||||||
|
st Ty
|
||||||
|
bn Self(…) Self($1): Self$0
|
||||||
|
bn Ty(…) Ty($1): Ty$0
|
||||||
|
kw mut
|
||||||
|
kw ref
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue