diff --git a/crates/ide_completion/src/completions/keyword.rs b/crates/ide_completion/src/completions/keyword.rs index c5cd3c2f7e9..c99fdef05c0 100644 --- a/crates/ide_completion/src/completions/keyword.rs +++ b/crates/ide_completion/src/completions/keyword.rs @@ -69,6 +69,9 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte if ctx.has_impl_or_trait_prev_sibling() { add_keyword("where", "where "); + if ctx.has_impl_prev_sibling() { + add_keyword("for", "for "); + } return; } if ctx.previous_token_is(T![unsafe]) { diff --git a/crates/ide_completion/src/completions/snippet.rs b/crates/ide_completion/src/completions/snippet.rs index 81ddfa34fdc..cbc20cc2c39 100644 --- a/crates/ide_completion/src/completions/snippet.rs +++ b/crates/ide_completion/src/completions/snippet.rs @@ -36,7 +36,11 @@ pub(crate) fn complete_expr_snippet(acc: &mut Completions, ctx: &CompletionConte } pub(crate) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionContext) { - if !ctx.expects_item() || ctx.previous_token_is(T![unsafe]) || ctx.path_qual().is_some() { + if !ctx.expects_item() + || ctx.previous_token_is(T![unsafe]) + || ctx.path_qual().is_some() + || ctx.has_impl_or_trait_prev_sibling() + { return; } if ctx.has_visibility_prev_sibling() { diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs index 1864bfbccbd..8ea5a2d5b9b 100644 --- a/crates/ide_completion/src/completions/unqualified_path.rs +++ b/crates/ide_completion/src/completions/unqualified_path.rs @@ -6,7 +6,7 @@ use syntax::{ast, AstNode}; use crate::{patterns::ImmediateLocation, CompletionContext, Completions}; pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) { - if ctx.is_path_disallowed() || !ctx.is_trivial_path() { + if ctx.is_path_disallowed() || !ctx.is_trivial_path() || ctx.has_impl_or_trait_prev_sibling() { return; } @@ -68,6 +68,9 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC return; } let add_resolution = match res { + ScopeDef::ImplSelfType(_) => { + !ctx.previous_token_is(syntax::T![impl]) && !ctx.previous_token_is(syntax::T![for]) + } // Don't suggest attribute macros and derives. ScopeDef::MacroDef(mac) => mac.is_fn_like(), // no values in type places diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs index 240cac1de09..d7a7e9cca84 100644 --- a/crates/ide_completion/src/context.rs +++ b/crates/ide_completion/src/context.rs @@ -305,6 +305,10 @@ impl<'a> CompletionContext<'a> { ) } + pub(crate) fn has_impl_prev_sibling(&self) -> bool { + matches!(self.prev_sibling, Some(ImmediatePrevSibling::ImplDefType)) + } + pub(crate) fn has_visibility_prev_sibling(&self) -> bool { matches!(self.prev_sibling, Some(ImmediatePrevSibling::Visibility)) } diff --git a/crates/ide_completion/src/tests/items.rs b/crates/ide_completion/src/tests/items.rs index dd4ba3864e9..8dfb8221bda 100644 --- a/crates/ide_completion/src/tests/items.rs +++ b/crates/ide_completion/src/tests/items.rs @@ -23,13 +23,45 @@ trait Trait {} #[test] fn target_type_or_trait_in_impl_block() { - // FIXME: should not complete `Self` check( r#" -impl My$0 +impl Tra$0 +"#, + expect![[r##" + tt Trait + en Enum + st Struct + md bar + ma foo!(…) #[macro_export] macro_rules! foo + ma foo!(…) #[macro_export] macro_rules! foo + bt u32 + bt bool + bt u8 + bt isize + bt u16 + bt u64 + bt u128 + bt f32 + bt i128 + bt i16 + bt str + bt i64 + bt char + bt f64 + bt i32 + bt i8 + bt usize + "##]], + ) +} + +#[test] +fn target_type_in_trait_impl_block() { + check( + r#" +impl Trait for Str$0 "#, expect![[r##" - sp Self tt Trait en Enum st Struct @@ -59,35 +91,22 @@ impl My$0 #[test] fn after_trait_name_in_trait_def() { - // FIXME: should only complete `where` check( r"trait A $0", - expect![[r##" + expect![[r#" kw where - sn tmod (Test module) - sn tfn (Test function) - sn macro_rules - md bar - ma foo!(…) #[macro_export] macro_rules! foo - ma foo!(…) #[macro_export] macro_rules! foo - "##]], + "#]], ); } #[test] fn after_trait_or_target_name_in_impl() { - // FIXME: should only complete `for` and `where` check( - r"impl A $0", - expect![[r##" + r"impl Trait $0", + expect![[r#" kw where - sn tmod (Test module) - sn tfn (Test function) - sn macro_rules - md bar - ma foo!(…) #[macro_export] macro_rules! foo - ma foo!(…) #[macro_export] macro_rules! foo - "##]], + kw for + "#]], ); }