Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 96481b7

Browse files
committed
Auto merge of rust-lang#12773 - Veykril:self-compl, r=Veykril
fix: Improve self param completion applicability Fixes rust-lang/rust-analyzer#9522
2 parents d3796ad + b96f8f1 commit 96481b7

File tree

6 files changed

+124
-18
lines changed

6 files changed

+124
-18
lines changed

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

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ use ide_db::FxHashMap;
55
use syntax::{
66
algo,
77
ast::{self, HasModuleItem},
8-
match_ast, AstNode, Direction, SyntaxKind, TextRange,
8+
match_ast, AstNode, Direction, SyntaxKind, TextRange, TextSize,
99
};
1010

1111
use crate::{
12-
context::{ParamKind, PatternContext},
12+
context::{ParamContext, ParamKind, PatternContext},
1313
CompletionContext, CompletionItem, CompletionItemKind, Completions,
1414
};
1515

@@ -24,7 +24,7 @@ pub(crate) fn complete_fn_param(
2424
ctx: &CompletionContext,
2525
pattern_ctx: &PatternContext,
2626
) -> Option<()> {
27-
let ((param_list, _, param_kind), impl_) = match pattern_ctx {
27+
let (ParamContext { param_list, kind, .. }, impl_) = match pattern_ctx {
2828
PatternContext { param_ctx: Some(kind), impl_, .. } => (kind, impl_),
2929
_ => return None,
3030
};
@@ -43,7 +43,7 @@ pub(crate) fn complete_fn_param(
4343
item.add_to(acc)
4444
};
4545

46-
match param_kind {
46+
match kind {
4747
ParamKind::Function(function) => {
4848
fill_fn_params(ctx, function, param_list, impl_, add_new_item_to_acc);
4949
}
@@ -105,7 +105,7 @@ fn fill_fn_params(
105105
}
106106
remove_duplicated(&mut file_params, param_list.params());
107107
let self_completion_items = ["self", "&self", "mut self", "&mut self"];
108-
if should_add_self_completions(param_list, impl_) {
108+
if should_add_self_completions(ctx.token.text_range().start(), param_list, impl_) {
109109
self_completion_items.into_iter().for_each(|self_item| add_new_item_to_acc(self_item));
110110
}
111111

@@ -156,10 +156,18 @@ fn remove_duplicated(
156156
})
157157
}
158158

159-
fn should_add_self_completions(param_list: &ast::ParamList, impl_: &Option<ast::Impl>) -> bool {
160-
let no_params = param_list.params().next().is_none() && param_list.self_param().is_none();
161-
162-
impl_.is_some() && no_params
159+
fn should_add_self_completions(
160+
cursor: TextSize,
161+
param_list: &ast::ParamList,
162+
impl_: &Option<ast::Impl>,
163+
) -> bool {
164+
if impl_.is_none() || param_list.self_param().is_some() {
165+
return false;
166+
}
167+
match param_list.params().next() {
168+
Some(first) => first.pat().map_or(false, |pat| pat.syntax().text_range().contains(cursor)),
169+
None => true,
170+
}
163171
}
164172

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

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,10 @@ impl Test for T {
438438
expect![[r#"
439439
sp Self
440440
st T
441+
bn &mut self
442+
bn &self
443+
bn mut self
444+
bn self
441445
"#]],
442446
);
443447

crates/ide-completion/src/context.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ pub(super) enum Qualified {
199199
#[derive(Debug, Clone, PartialEq, Eq)]
200200
pub(super) struct PatternContext {
201201
pub(super) refutability: PatternRefutability,
202-
pub(super) param_ctx: Option<(ast::ParamList, ast::Param, ParamKind)>,
202+
pub(super) param_ctx: Option<ParamContext>,
203203
pub(super) has_type_ascription: bool,
204204
pub(super) parent_pat: Option<ast::Pat>,
205205
pub(super) ref_token: Option<SyntaxToken>,
@@ -209,6 +209,13 @@ pub(super) struct PatternContext {
209209
pub(super) impl_: Option<ast::Impl>,
210210
}
211211

212+
#[derive(Debug, Clone, PartialEq, Eq)]
213+
pub(super) struct ParamContext {
214+
pub(super) param_list: ast::ParamList,
215+
pub(super) param: ast::Param,
216+
pub(super) kind: ParamKind,
217+
}
218+
212219
/// The state of the lifetime we are completing.
213220
#[derive(Debug)]
214221
pub(super) struct LifetimeContext {

crates/ide-completion/src/context/analysis.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ use syntax::{
1313
use crate::context::{
1414
AttrCtx, CompletionAnalysis, CompletionContext, DotAccess, DotAccessKind, ExprCtx,
1515
ItemListKind, LifetimeContext, LifetimeKind, NameContext, NameKind, NameRefContext,
16-
NameRefKind, ParamKind, PathCompletionCtx, PathKind, PatternContext, PatternRefutability,
17-
Qualified, QualifierCtx, TypeAscriptionTarget, TypeLocation, COMPLETION_MARKER,
16+
NameRefKind, ParamContext, ParamKind, PathCompletionCtx, PathKind, PatternContext,
17+
PatternRefutability, Qualified, QualifierCtx, TypeAscriptionTarget, TypeLocation,
18+
COMPLETION_MARKER,
1819
};
1920

2021
impl<'a> CompletionContext<'a> {
@@ -990,7 +991,7 @@ fn pattern_context_for(
990991
original_file: &SyntaxNode,
991992
pat: ast::Pat,
992993
) -> PatternContext {
993-
let mut is_param = None;
994+
let mut param_ctx = None;
994995
let (refutability, has_type_ascription) =
995996
pat
996997
.syntax()
@@ -1003,7 +1004,7 @@ fn pattern_context_for(
10031004
ast::LetStmt(let_) => return (PatternRefutability::Irrefutable, let_.ty().is_some()),
10041005
ast::Param(param) => {
10051006
let has_type_ascription = param.ty().is_some();
1006-
is_param = (|| {
1007+
param_ctx = (|| {
10071008
let fake_param_list = param.syntax().parent().and_then(ast::ParamList::cast)?;
10081009
let param_list = find_node_in_file_compensated(sema, original_file, &fake_param_list)?;
10091010
let param_list_owner = param_list.syntax().parent()?;
@@ -1014,7 +1015,9 @@ fn pattern_context_for(
10141015
_ => return None,
10151016
}
10161017
};
1017-
Some((param_list, param, kind))
1018+
Some(ParamContext {
1019+
param_list, param, kind
1020+
})
10181021
})();
10191022
return (PatternRefutability::Irrefutable, has_type_ascription)
10201023
},
@@ -1033,7 +1036,7 @@ fn pattern_context_for(
10331036

10341037
PatternContext {
10351038
refutability,
1036-
param_ctx: is_param,
1039+
param_ctx,
10371040
has_type_ascription,
10381041
parent_pat: pat.syntax().parent().and_then(ast::Pat::cast),
10391042
mut_token,

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use itertools::Itertools;
66
use syntax::SmolStr;
77

88
use crate::{
9-
context::{ParamKind, PatternContext},
9+
context::{ParamContext, ParamKind, PatternContext},
1010
render::{
1111
variant::{format_literal_label, visible_fields},
1212
RenderContext,
@@ -102,7 +102,7 @@ fn render_pat(
102102
let needs_ascription = matches!(
103103
pattern_ctx,
104104
PatternContext {
105-
param_ctx: Some((.., ParamKind::Function(_))),
105+
param_ctx: Some(ParamContext { kind: ParamKind::Function(_), .. }),
106106
has_type_ascription: false,
107107
..
108108
}

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

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,3 +630,87 @@ fn f(v: u32) {
630630
"#]],
631631
);
632632
}
633+
634+
#[test]
635+
fn in_method_param() {
636+
check_empty(
637+
r#"
638+
struct Ty(u8);
639+
640+
impl Ty {
641+
fn foo($0)
642+
}
643+
"#,
644+
expect![[r#"
645+
sp Self
646+
st Ty
647+
bn &mut self
648+
bn &self
649+
bn Self(…) Self($1): Self$0
650+
bn Ty(…) Ty($1): Ty$0
651+
bn mut self
652+
bn self
653+
kw mut
654+
kw ref
655+
"#]],
656+
);
657+
check_empty(
658+
r#"
659+
struct Ty(u8);
660+
661+
impl Ty {
662+
fn foo(s$0)
663+
}
664+
"#,
665+
expect![[r#"
666+
sp Self
667+
st Ty
668+
bn &mut self
669+
bn &self
670+
bn Self(…) Self($1): Self$0
671+
bn Ty(…) Ty($1): Ty$0
672+
bn mut self
673+
bn self
674+
kw mut
675+
kw ref
676+
"#]],
677+
);
678+
check_empty(
679+
r#"
680+
struct Ty(u8);
681+
682+
impl Ty {
683+
fn foo(s$0, foo: u8)
684+
}
685+
"#,
686+
expect![[r#"
687+
sp Self
688+
st Ty
689+
bn &mut self
690+
bn &self
691+
bn Self(…) Self($1): Self$0
692+
bn Ty(…) Ty($1): Ty$0
693+
bn mut self
694+
bn self
695+
kw mut
696+
kw ref
697+
"#]],
698+
);
699+
check_empty(
700+
r#"
701+
struct Ty(u8);
702+
703+
impl Ty {
704+
fn foo(foo: u8, b$0)
705+
}
706+
"#,
707+
expect![[r#"
708+
sp Self
709+
st Ty
710+
bn Self(…) Self($1): Self$0
711+
bn Ty(…) Ty($1): Ty$0
712+
kw mut
713+
kw ref
714+
"#]],
715+
);
716+
}

0 commit comments

Comments
 (0)