Skip to content

Commit 6f573bd

Browse files
committed
Allow hints after 'fn' keyword if it's an impl trait block
1 parent 8f303da commit 6f573bd

File tree

3 files changed

+37
-4
lines changed

3 files changed

+37
-4
lines changed

crates/ide/src/completion/completion_context.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ use crate::{
1818
patterns::{
1919
fn_is_prev, for_is_prev2, has_bind_pat_parent, has_block_expr_parent,
2020
has_field_list_parent, has_impl_as_prev_sibling, has_impl_parent,
21-
has_item_list_or_source_file_parent, has_ref_parent, has_trait_as_prev_sibling,
22-
has_trait_parent, if_is_prev, is_in_loop_body, is_match_arm, unsafe_is_prev,
21+
has_impl_trait_parent, has_item_list_or_source_file_parent, has_ref_parent,
22+
has_trait_as_prev_sibling, has_trait_parent, if_is_prev, is_in_loop_body, is_match_arm,
23+
unsafe_is_prev,
2324
},
2425
CompletionConfig,
2526
},
@@ -86,6 +87,7 @@ pub(crate) struct CompletionContext<'a> {
8687
pub(super) in_loop_body: bool,
8788
pub(super) has_trait_parent: bool,
8889
pub(super) has_impl_parent: bool,
90+
pub(super) has_impl_trait_parent: bool,
8991
pub(super) has_field_list_parent: bool,
9092
pub(super) trait_as_prev_sibling: bool,
9193
pub(super) impl_as_prev_sibling: bool,
@@ -170,6 +172,7 @@ impl<'a> CompletionContext<'a> {
170172
block_expr_parent: false,
171173
has_trait_parent: false,
172174
has_impl_parent: false,
175+
has_impl_trait_parent: false,
173176
has_field_list_parent: false,
174177
trait_as_prev_sibling: false,
175178
impl_as_prev_sibling: false,
@@ -228,9 +231,10 @@ impl<'a> CompletionContext<'a> {
228231
/// Checks whether completions in that particular case don't make much sense.
229232
/// Examples:
230233
/// - `fn <|>` -- we expect function name, it's unlikely that "hint" will be helpful.
234+
/// Exception for this case is `impl Trait for Foo`, where we would like to hint trait method names.
231235
/// - `for _ i<|>` -- obviously, it'll be "in" keyword.
232236
pub(crate) fn no_completion_required(&self) -> bool {
233-
self.fn_is_prev || self.for_is_prev2
237+
(self.fn_is_prev && !self.has_impl_trait_parent) || self.for_is_prev2
234238
}
235239

236240
/// The range of the identifier that is being completed.
@@ -256,6 +260,7 @@ impl<'a> CompletionContext<'a> {
256260
self.in_loop_body = is_in_loop_body(syntax_element.clone());
257261
self.has_trait_parent = has_trait_parent(syntax_element.clone());
258262
self.has_impl_parent = has_impl_parent(syntax_element.clone());
263+
self.has_impl_trait_parent = has_impl_trait_parent(syntax_element.clone());
259264
self.has_field_list_parent = has_field_list_parent(syntax_element.clone());
260265
self.impl_as_prev_sibling = has_impl_as_prev_sibling(syntax_element.clone());
261266
self.trait_as_prev_sibling = has_trait_as_prev_sibling(syntax_element.clone());

crates/ide/src/completion/patterns.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use syntax::{
99
};
1010

1111
#[cfg(test)]
12-
use crate::completion::test_utils::check_pattern_is_applicable;
12+
use crate::completion::test_utils::{check_pattern_is_applicable, check_pattern_is_not_applicable};
1313

1414
pub(crate) fn has_trait_parent(element: SyntaxElement) -> bool {
1515
not_same_range_ancestor(element)
@@ -34,6 +34,22 @@ pub(crate) fn has_impl_parent(element: SyntaxElement) -> bool {
3434
fn test_has_impl_parent() {
3535
check_pattern_is_applicable(r"impl A { f<|> }", has_impl_parent);
3636
}
37+
38+
pub(crate) fn has_impl_trait_parent(element: SyntaxElement) -> bool {
39+
not_same_range_ancestor(element)
40+
.filter(|it| it.kind() == ASSOC_ITEM_LIST)
41+
.and_then(|it| it.parent())
42+
.filter(|it| it.kind() == IMPL)
43+
.map(|it| ast::Impl::cast(it).unwrap())
44+
.map(|it| it.trait_().is_some())
45+
.unwrap_or(false)
46+
}
47+
#[test]
48+
fn test_has_impl_trait_parent() {
49+
check_pattern_is_applicable(r"impl Foo for Bar { f<|> }", has_impl_trait_parent);
50+
check_pattern_is_not_applicable(r"impl A { f<|> }", has_impl_trait_parent);
51+
}
52+
3753
pub(crate) fn has_field_list_parent(element: SyntaxElement) -> bool {
3854
not_same_range_ancestor(element).filter(|it| it.kind() == RECORD_FIELD_LIST).is_some()
3955
}

crates/ide/src/completion/test_utils.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,18 @@ pub(crate) fn check_pattern_is_applicable(code: &str, check: fn(SyntaxElement) -
104104
.unwrap();
105105
}
106106

107+
pub(crate) fn check_pattern_is_not_applicable(code: &str, check: fn(SyntaxElement) -> bool) {
108+
let (analysis, pos) = fixture::position(code);
109+
analysis
110+
.with_db(|db| {
111+
let sema = Semantics::new(db);
112+
let original_file = sema.parse(pos.file_id);
113+
let token = original_file.syntax().token_at_offset(pos.offset).left_biased().unwrap();
114+
assert!(!check(NodeOrToken::Token(token)));
115+
})
116+
.unwrap();
117+
}
118+
107119
pub(crate) fn get_all_completion_items(
108120
config: CompletionConfig,
109121
code: &str,

0 commit comments

Comments
 (0)