diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs index 380c1e07977..5abd6ee37f7 100644 --- a/crates/ide_completion/src/completions/unqualified_path.rs +++ b/crates/ide_completion/src/completions/unqualified_path.rs @@ -36,6 +36,20 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC return; } + if matches!(&ctx.completion_location, Some(ImmediateLocation::TypeBound)) { + ctx.scope.process_all_names(&mut |name, res| { + let add_resolution = match res { + ScopeDef::MacroDef(mac) => mac.is_fn_like(), + ScopeDef::ModuleDef(hir::ModuleDef::Trait(_) | hir::ModuleDef::Module(_)) => true, + _ => false, + }; + if add_resolution { + acc.add_resolution(ctx, name, &res); + } + }); + return; + } + if !ctx.expects_type() { if let Some(hir::Adt::Enum(e)) = ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt()) diff --git a/crates/ide_completion/src/patterns.rs b/crates/ide_completion/src/patterns.rs index 757c9a3daa3..b673ce8c9ad 100644 --- a/crates/ide_completion/src/patterns.rs +++ b/crates/ide_completion/src/patterns.rs @@ -36,6 +36,7 @@ pub(crate) enum ImmediateLocation { IdentPat, BlockExpr, ItemList, + TypeBound, // Fake file ast node Attribute(ast::Attr), // Fake file ast node @@ -154,6 +155,13 @@ pub(crate) fn determine_location( ast::NameLike::Lifetime(lt) => lt.syntax().clone(), }; + match_ast! { + match node { + ast::TypeBoundList(_it) => return Some(ImmediateLocation::TypeBound), + _ => (), + } + }; + let parent = match node.parent() { Some(parent) => match ast::MacroCall::cast(parent.clone()) { // When a path is being typed in an (Assoc)ItemList the parser will always emit a macro_call. @@ -195,6 +203,8 @@ pub(crate) fn determine_location( }, ast::TupleField(_it) => ImmediateLocation::TupleField, ast::TupleFieldList(_it) => ImmediateLocation::TupleField, + ast::TypeBound(_it) => ImmediateLocation::TypeBound, + ast::TypeBoundList(_it) => ImmediateLocation::TypeBound, ast::AssocItemList(it) => match it.syntax().parent().map(|it| it.kind()) { Some(IMPL) => ImmediateLocation::Impl, Some(TRAIT) => ImmediateLocation::Trait, diff --git a/crates/ide_completion/src/tests/predicate.rs b/crates/ide_completion/src/tests/predicate.rs index 04ff08669df..2130c538f2f 100644 --- a/crates/ide_completion/src/tests/predicate.rs +++ b/crates/ide_completion/src/tests/predicate.rs @@ -37,17 +37,9 @@ fn bound_for_type_pred() { struct Foo<'lt, T, const C: usize> where T: $0 {} "#, expect![[r#" - sp Self - tp T tt Trait - en Enum - st Record - st Tuple md module - st Foo<…> - st Unit ma makro!(…) macro_rules! makro - bt u32 "#]], ); } @@ -60,40 +52,23 @@ fn bound_for_lifetime_pred() { struct Foo<'lt, T, const C: usize> where 'lt: $0 {} "#, expect![[r#" - sp Self - tp T tt Trait - en Enum - st Record - st Tuple md module - st Foo<…> - st Unit ma makro!(…) macro_rules! makro - bt u32 "#]], ); } #[test] fn bound_for_for_pred() { - // FIXME: only show traits, macros and modules check( r#" struct Foo<'lt, T, const C: usize> where for<'a> T: $0 {} "#, expect![[r#" - sp Self - tp T tt Trait - en Enum - st Record - st Tuple md module - st Foo<…> - st Unit ma makro!(…) macro_rules! makro - bt u32 "#]], ); } @@ -120,7 +95,6 @@ struct Foo<'lt, T, const C: usize> where for<'a> $0 {} #[test] fn pred_on_fn_in_impl() { - // FIXME: only show traits, macros and modules check( r#" impl Record {