diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs index b0763584432b..132440db46a5 100644 --- a/crates/ide-completion/src/completions.rs +++ b/crates/ide-completion/src/completions.rs @@ -103,11 +103,29 @@ impl Completions { } pub(crate) fn add_nameref_keywords_with_colon(&mut self, ctx: &CompletionContext) { - ["self::", "super::", "crate::"].into_iter().for_each(|kw| self.add_keyword(ctx, kw)); + ["self::", "crate::"].into_iter().for_each(|kw| self.add_keyword(ctx, kw)); + + if ctx.depth_from_crate_root > 0 { + self.add_keyword(ctx, "super::"); + } } pub(crate) fn add_nameref_keywords(&mut self, ctx: &CompletionContext) { - ["self", "super", "crate"].into_iter().for_each(|kw| self.add_keyword(ctx, kw)); + ["self", "crate"].into_iter().for_each(|kw| self.add_keyword(ctx, kw)); + + if ctx.depth_from_crate_root > 0 { + self.add_keyword(ctx, "super"); + } + } + + pub(crate) fn add_super_kw_acc_to_mod_depth( + &mut self, + super_chain_len: &usize, + ctx: &CompletionContext, + ) { + if *super_chain_len > 0 && *super_chain_len < ctx.depth_from_crate_root { + self.add_keyword(ctx, "super::"); + } } pub(crate) fn add_keyword_snippet(&mut self, ctx: &CompletionContext, kw: &str, snippet: &str) { diff --git a/crates/ide-completion/src/completions/attribute.rs b/crates/ide-completion/src/completions/attribute.rs index 0b7479fd0e84..3d7f4dda2d76 100644 --- a/crates/ide-completion/src/completions/attribute.rs +++ b/crates/ide-completion/src/completions/attribute.rs @@ -83,10 +83,8 @@ pub(crate) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext) }; match qualifier { - Some(PathQualifierCtx { resolution, is_super_chain, .. }) => { - if *is_super_chain { - acc.add_keyword(ctx, "super::"); - } + Some(PathQualifierCtx { resolution, super_chain_len, .. }) => { + acc.add_super_kw_acc_to_mod_depth(super_chain_len, ctx); let module = match resolution { Some(hir::PathResolution::Def(hir::ModuleDef::Module(it))) => it, diff --git a/crates/ide-completion/src/completions/attribute/derive.rs b/crates/ide-completion/src/completions/attribute/derive.rs index 19414e4b3156..5bf47aebe286 100644 --- a/crates/ide-completion/src/completions/attribute/derive.rs +++ b/crates/ide-completion/src/completions/attribute/derive.rs @@ -24,10 +24,8 @@ pub(crate) fn complete_derive(acc: &mut Completions, ctx: &CompletionContext) { let core = ctx.famous_defs().core(); match qualifier { - Some(PathQualifierCtx { resolution, is_super_chain, .. }) => { - if *is_super_chain { - acc.add_keyword(ctx, "super::"); - } + Some(PathQualifierCtx { resolution, super_chain_len, .. }) => { + acc.add_super_kw_acc_to_mod_depth(super_chain_len, ctx); let module = match resolution { Some(hir::PathResolution::Def(hir::ModuleDef::Module(it))) => it, diff --git a/crates/ide-completion/src/completions/item_list.rs b/crates/ide-completion/src/completions/item_list.rs index d44bf0a6ab74..d463da995a00 100644 --- a/crates/ide-completion/src/completions/item_list.rs +++ b/crates/ide-completion/src/completions/item_list.rs @@ -50,7 +50,7 @@ pub(crate) fn complete_item_list(acc: &mut Completions, ctx: &CompletionContext) } match path_qualifier { - Some(PathQualifierCtx { resolution, is_super_chain, .. }) => { + Some(PathQualifierCtx { resolution, super_chain_len, .. }) => { if let Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))) = resolution { for (name, def) in module.scope(ctx.db, Some(ctx.module)) { if let Some(def) = module_or_fn_macro(ctx.db, def) { @@ -59,9 +59,7 @@ pub(crate) fn complete_item_list(acc: &mut Completions, ctx: &CompletionContext) } } - if *is_super_chain { - acc.add_keyword(ctx, "super::"); - } + acc.add_super_kw_acc_to_mod_depth(super_chain_len, ctx); } None if is_absolute_path => acc.add_crate_roots(ctx), None if ctx.qualifier_ctx.none() => { diff --git a/crates/ide-completion/src/completions/pattern.rs b/crates/ide-completion/src/completions/pattern.rs index ab35dadf92b4..379c7d2b62cd 100644 --- a/crates/ide-completion/src/completions/pattern.rs +++ b/crates/ide-completion/src/completions/pattern.rs @@ -114,10 +114,8 @@ fn pattern_path_completion( PathCompletionCtx { qualifier, is_absolute_path, .. }: &PathCompletionCtx, ) { match qualifier { - Some(PathQualifierCtx { resolution, is_super_chain, .. }) => { - if *is_super_chain { - acc.add_keyword(ctx, "super::"); - } + Some(PathQualifierCtx { resolution, super_chain_len, .. }) => { + acc.add_super_kw_acc_to_mod_depth(super_chain_len, ctx); let resolution = match resolution { Some(it) => it, diff --git a/crates/ide-completion/src/completions/use_.rs b/crates/ide-completion/src/completions/use_.rs index f1beeb454c89..763040be18bd 100644 --- a/crates/ide-completion/src/completions/use_.rs +++ b/crates/ide-completion/src/completions/use_.rs @@ -22,10 +22,8 @@ pub(crate) fn complete_use_tree(acc: &mut Completions, ctx: &CompletionContext) }; match qualifier { - Some(PathQualifierCtx { path, resolution, is_super_chain, use_tree_parent, .. }) => { - if *is_super_chain { - acc.add_keyword(ctx, "super::"); - } + Some(PathQualifierCtx { path, resolution, super_chain_len, use_tree_parent, .. }) => { + acc.add_super_kw_acc_to_mod_depth(super_chain_len, ctx); // only show `self` in a new use-tree when the qualifier doesn't end in self let not_preceded_by_self = *use_tree_parent && !matches!( diff --git a/crates/ide-completion/src/completions/vis.rs b/crates/ide-completion/src/completions/vis.rs index d538f1879e74..ee3c43fbf07f 100644 --- a/crates/ide-completion/src/completions/vis.rs +++ b/crates/ide-completion/src/completions/vis.rs @@ -19,7 +19,7 @@ pub(crate) fn complete_vis_path(acc: &mut Completions, ctx: &CompletionContext) }; match qualifier { - Some(PathQualifierCtx { resolution, is_super_chain, .. }) => { + Some(PathQualifierCtx { resolution, super_chain_len, .. }) => { // Try completing next child module of the path that is still a parent of the current module if let Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))) = resolution { let next_towards_current = ctx @@ -36,9 +36,7 @@ pub(crate) fn complete_vis_path(acc: &mut Completions, ctx: &CompletionContext) } } - if *is_super_chain { - acc.add_keyword(ctx, "super::"); - } + acc.add_super_kw_acc_to_mod_depth(super_chain_len, ctx); } None if !is_absolute_path => { if !has_in_token { diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs index 02307def9e6e..70adebd937a2 100644 --- a/crates/ide-completion/src/context.rs +++ b/crates/ide-completion/src/context.rs @@ -130,8 +130,8 @@ impl PathCompletionCtx { pub(crate) struct PathQualifierCtx { pub(crate) path: ast::Path, pub(crate) resolution: Option, - /// Whether this path consists solely of `super` segments - pub(crate) is_super_chain: bool, + /// How many `super` segments are present in the path + pub(crate) super_chain_len: usize, /// Whether the qualifier comes from a use tree parent or not pub(crate) use_tree_parent: bool, /// <_> @@ -291,6 +291,12 @@ pub(crate) struct CompletionContext<'a> { pub(super) existing_derives: FxHashSet, pub(super) locals: FxHashMap, + + // - crate-root + // - mod foo + // - mod bar + // Here depth will be 2: {[bar<->foo], [foo<->crate-root]} + pub(super) depth_from_crate_root: usize, } impl<'a> CompletionContext<'a> { @@ -490,6 +496,20 @@ impl<'a> CompletionContext<'a> { } }); + let mut mod_ = module; + let mut depth = 0; + loop { + match mod_.parent(db) { + Some(mod_parent) => { + mod_ = mod_parent; + depth += 1; + } + None => { + break; + } + } + } + let mut ctx = CompletionContext { sema, scope, @@ -513,6 +533,7 @@ impl<'a> CompletionContext<'a> { qualifier_ctx: Default::default(), existing_derives: Default::default(), locals, + depth_from_crate_root: depth, }; ctx.expand_and_fill( original_file.syntax().clone(), @@ -1285,8 +1306,9 @@ impl<'a> CompletionContext<'a> { .map(|it| it.parent_path()); path_ctx.qualifier = path.map(|path| { let res = sema.resolve_path(&path); - let is_super_chain = iter::successors(Some(path.clone()), |p| p.qualifier()) - .all(|p| p.segment().and_then(|s| s.super_token()).is_some()); + let super_chain_len = iter::successors(Some(path.clone()), |p| p.qualifier()) + .filter_map(|p| p.segment().and_then(|s| s.super_token())) + .count(); // `<_>::$0` let is_infer_qualifier = path.qualifier().is_none() @@ -1301,7 +1323,7 @@ impl<'a> CompletionContext<'a> { PathQualifierCtx { path, resolution: res, - is_super_chain, + super_chain_len, use_tree_parent, is_infer_qualifier, } diff --git a/crates/ide-completion/src/tests/attribute.rs b/crates/ide-completion/src/tests/attribute.rs index 52c69f84b610..9b724e9d5791 100644 --- a/crates/ide-completion/src/tests/attribute.rs +++ b/crates/ide-completion/src/tests/attribute.rs @@ -35,7 +35,6 @@ struct Foo; md proc_macros kw crate:: kw self:: - kw super:: "#]], ) } @@ -85,7 +84,6 @@ fn with_existing_attr() { at warn(…) kw crate:: kw self:: - kw super:: "#]], ) } @@ -117,7 +115,6 @@ fn attr_on_source_file() { at windows_subsystem = "…" kw crate:: kw self:: - kw super:: "#]], ); } @@ -190,7 +187,6 @@ fn attr_on_macro_rules() { at warn(…) kw crate:: kw self:: - kw super:: "#]], ); } @@ -214,7 +210,6 @@ fn attr_on_macro_def() { at warn(…) kw crate:: kw self:: - kw super:: "#]], ); } @@ -239,7 +234,6 @@ fn attr_on_extern_crate() { at warn(…) kw crate:: kw self:: - kw super:: "#]], ); } @@ -263,7 +257,6 @@ fn attr_on_use() { at warn(…) kw crate:: kw self:: - kw super:: "#]], ); } @@ -287,7 +280,6 @@ fn attr_on_type_alias() { at warn(…) kw crate:: kw self:: - kw super:: "#]], ); } @@ -320,7 +312,6 @@ struct Foo; md core kw crate:: kw self:: - kw super:: "#]], ); } @@ -347,7 +338,6 @@ fn attr_on_enum() { at warn(…) kw crate:: kw self:: - kw super:: "#]], ); } @@ -371,7 +361,6 @@ fn attr_on_const() { at warn(…) kw crate:: kw self:: - kw super:: "#]], ); } @@ -400,7 +389,6 @@ fn attr_on_static() { at warn(…) kw crate:: kw self:: - kw super:: "#]], ); } @@ -425,7 +413,6 @@ fn attr_on_trait() { at warn(…) kw crate:: kw self:: - kw super:: "#]], ); } @@ -450,7 +437,6 @@ fn attr_on_impl() { at warn(…) kw crate:: kw self:: - kw super:: "#]], ); check( @@ -470,7 +456,6 @@ fn attr_on_impl() { at warn(…) kw crate:: kw self:: - kw super:: "#]], ); } @@ -495,7 +480,6 @@ fn attr_on_extern_block() { at warn(…) kw crate:: kw self:: - kw super:: "#]], ); check( @@ -516,7 +500,6 @@ fn attr_on_extern_block() { at warn(…) kw crate:: kw self:: - kw super:: "#]], ); } @@ -535,7 +518,6 @@ fn attr_on_variant() { at warn(…) kw crate:: kw self:: - kw super:: "#]], ); } @@ -574,7 +556,6 @@ fn attr_on_fn() { at warn(…) kw crate:: kw self:: - kw super:: "#]], ); } @@ -622,7 +603,6 @@ fn attr_in_source_file_end() { at warn(…) kw crate:: kw self:: - kw super:: "#]], ); } @@ -679,7 +659,6 @@ mod derive { md core kw crate:: kw self:: - kw super:: "#]], ); } @@ -701,7 +680,6 @@ mod derive { md core kw crate:: kw self:: - kw super:: "#]], ) } @@ -723,7 +701,6 @@ mod derive { md core kw crate:: kw self:: - kw super:: "#]], ); } @@ -744,7 +721,6 @@ mod derive { md core kw crate:: kw self:: - kw super:: "#]], ); } @@ -763,7 +739,6 @@ mod derive { md proc_macros kw crate:: kw self:: - kw super:: "#]], ); check_derive( @@ -779,7 +754,6 @@ use proc_macros::DeriveIdentity; md proc_macros kw crate:: kw self:: - kw super:: "#]], ); } diff --git a/crates/ide-completion/src/tests/expression.rs b/crates/ide-completion/src/tests/expression.rs index 61246b963e15..82c3464e9092 100644 --- a/crates/ide-completion/src/tests/expression.rs +++ b/crates/ide-completion/src/tests/expression.rs @@ -58,7 +58,6 @@ fn baz() { kw mut kw return kw self:: - kw super:: kw true kw unsafe kw while @@ -100,7 +99,6 @@ fn func(param0 @ (param1, param2): (i32, i32)) { kw match kw return kw self:: - kw super:: kw true kw unsafe kw while @@ -162,7 +160,6 @@ impl Unit { kw self:: kw static kw struct - kw super:: kw trait kw true kw type @@ -240,7 +237,6 @@ fn complete_in_block() { kw self:: kw static kw struct - kw super:: kw trait kw true kw type @@ -288,7 +284,6 @@ fn complete_after_if_expr() { kw self:: kw static kw struct - kw super:: kw trait kw true kw type @@ -326,7 +321,6 @@ fn complete_in_match_arm() { kw match kw return kw self:: - kw super:: kw true kw unsafe kw while @@ -362,7 +356,6 @@ fn completes_in_loop_ctx() { kw self:: kw static kw struct - kw super:: kw trait kw true kw type @@ -394,7 +387,6 @@ fn completes_in_let_initializer() { kw match kw return kw self:: - kw super:: kw true kw unsafe kw while @@ -429,7 +421,6 @@ fn foo() { kw match kw return kw self:: - kw super:: kw true kw unsafe kw while @@ -465,7 +456,6 @@ fn foo() { kw match kw return kw self:: - kw super:: kw true kw unsafe kw while @@ -497,7 +487,6 @@ fn quux(x: i32) { kw match kw return kw self:: - kw super:: kw true kw unsafe kw while @@ -525,7 +514,6 @@ fn quux(x: i32) { kw match kw return kw self:: - kw super:: kw true kw unsafe kw while diff --git a/crates/ide-completion/src/tests/item.rs b/crates/ide-completion/src/tests/item.rs index 81303eb38f43..409413c1dcdb 100644 --- a/crates/ide-completion/src/tests/item.rs +++ b/crates/ide-completion/src/tests/item.rs @@ -29,7 +29,6 @@ impl Tra$0 bt u32 kw crate:: kw self:: - kw super:: "#]], ) } @@ -52,7 +51,6 @@ impl Trait for Str$0 bt u32 kw crate:: kw self:: - kw super:: "#]], ) } diff --git a/crates/ide-completion/src/tests/item_list.rs b/crates/ide-completion/src/tests/item_list.rs index 09ea78a3d504..5076c6e86cae 100644 --- a/crates/ide-completion/src/tests/item_list.rs +++ b/crates/ide-completion/src/tests/item_list.rs @@ -60,7 +60,6 @@ fn in_source_file_item_list() { kw self:: kw static kw struct - kw super:: kw trait kw type kw union @@ -93,7 +92,6 @@ fn in_item_list_after_attr() { kw self:: kw static kw struct - kw super:: kw trait kw type kw union @@ -175,7 +173,6 @@ fn in_impl_assoc_item_list() { kw pub(crate) kw pub(super) kw self:: - kw super:: kw unsafe "#]], ) @@ -195,7 +192,6 @@ fn in_impl_assoc_item_list_after_attr() { kw pub(crate) kw pub(super) kw self:: - kw super:: kw unsafe "#]], ) @@ -212,7 +208,6 @@ fn in_trait_assoc_item_list() { kw crate:: kw fn kw self:: - kw super:: kw type kw unsafe "#]], @@ -247,7 +242,6 @@ impl Test for () { ta type Type1 = kw crate:: kw self:: - kw super:: "#]], ); } diff --git a/crates/ide-completion/src/tests/pattern.rs b/crates/ide-completion/src/tests/pattern.rs index bf88070769eb..89cd131a9580 100644 --- a/crates/ide-completion/src/tests/pattern.rs +++ b/crates/ide-completion/src/tests/pattern.rs @@ -402,7 +402,6 @@ fn foo() { bt u32 kw crate:: kw self:: - kw super:: "#]], ); check_empty( @@ -420,7 +419,6 @@ fn foo() { bt u32 kw crate:: kw self:: - kw super:: "#]], ); check_empty( diff --git a/crates/ide-completion/src/tests/predicate.rs b/crates/ide-completion/src/tests/predicate.rs index f2b9c061dc5e..a8676e2f2478 100644 --- a/crates/ide-completion/src/tests/predicate.rs +++ b/crates/ide-completion/src/tests/predicate.rs @@ -28,7 +28,6 @@ struct Foo<'lt, T, const C: usize> where $0 {} bt u32 kw crate:: kw self:: - kw super:: "#]], ); } @@ -45,7 +44,6 @@ struct Foo<'lt, T, const C: usize> where T: $0 {} tt Trait kw crate:: kw self:: - kw super:: "#]], ); } @@ -64,7 +62,6 @@ struct Foo<'lt, T, const C: usize> where 'lt: $0 {} tt Trait kw crate:: kw self:: - kw super:: "#]], ); } @@ -81,7 +78,6 @@ struct Foo<'lt, T, const C: usize> where for<'a> T: $0 {} tt Trait kw crate:: kw self:: - kw super:: "#]], ); } @@ -105,7 +101,6 @@ struct Foo<'lt, T, const C: usize> where for<'a> $0 {} bt u32 kw crate:: kw self:: - kw super:: "#]], ); } @@ -131,7 +126,6 @@ impl Record { bt u32 kw crate:: kw self:: - kw super:: "#]], ); } diff --git a/crates/ide-completion/src/tests/record.rs b/crates/ide-completion/src/tests/record.rs index 9369034cc629..53cd9e23a0eb 100644 --- a/crates/ide-completion/src/tests/record.rs +++ b/crates/ide-completion/src/tests/record.rs @@ -174,7 +174,6 @@ fn main() { bt u32 kw crate:: kw self:: - kw super:: "#]], ); check( diff --git a/crates/ide-completion/src/tests/type_pos.rs b/crates/ide-completion/src/tests/type_pos.rs index 1e5e86eef598..ae895785221b 100644 --- a/crates/ide-completion/src/tests/type_pos.rs +++ b/crates/ide-completion/src/tests/type_pos.rs @@ -31,7 +31,6 @@ struct Foo<'lt, T, const C: usize> { bt u32 kw crate:: kw self:: - kw super:: "#]], ) } @@ -60,7 +59,6 @@ struct Foo<'lt, T, const C: usize>(f$0); kw pub(crate) kw pub(super) kw self:: - kw super:: "#]], ) } @@ -84,7 +82,6 @@ fn x<'lt, T, const C: usize>() -> $0 bt u32 kw crate:: kw self:: - kw super:: "#]], ); } @@ -110,7 +107,6 @@ const FOO: $0 = Foo(2); it Foo kw crate:: kw self:: - kw super:: "#]], ); } @@ -137,7 +133,6 @@ fn f2() { it i32 kw crate:: kw self:: - kw super:: "#]], ); } @@ -166,7 +161,6 @@ fn f2() { it u64 kw crate:: kw self:: - kw super:: "#]], ); } @@ -192,7 +186,6 @@ fn f2(x: u64) -> $0 { it u64 kw crate:: kw self:: - kw super:: "#]], ); } @@ -219,7 +212,6 @@ fn f2(x: $0) { it i32 kw crate:: kw self:: - kw super:: "#]], ); } @@ -254,7 +246,6 @@ fn foo<'lt, T, const C: usize>() { it a::Foo> kw crate:: kw self:: - kw super:: "#]], ); } @@ -284,7 +275,6 @@ fn foo<'lt, T, const C: usize>() { it Foo kw crate:: kw self:: - kw super:: "#]], ); } @@ -311,7 +301,6 @@ fn foo<'lt, T, const C: usize>() { bt u32 kw crate:: kw self:: - kw super:: "#]], ); check( @@ -367,7 +356,6 @@ fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {} bt u32 kw crate:: kw self:: - kw super:: "#]], ); check( @@ -420,7 +408,6 @@ impl Tr<$0 bt u32 kw crate:: kw self:: - kw super:: "#]], ); } diff --git a/crates/ide-completion/src/tests/use_tree.rs b/crates/ide-completion/src/tests/use_tree.rs index 70aa5e5468a5..dc2712cd24f4 100644 --- a/crates/ide-completion/src/tests/use_tree.rs +++ b/crates/ide-completion/src/tests/use_tree.rs @@ -26,7 +26,6 @@ mod foo {} md other_crate kw crate:: kw self:: - kw super:: "#]], ); } @@ -203,7 +202,6 @@ struct Bar; md bar md foo st Bar - kw super:: "#]], ); } @@ -273,9 +271,39 @@ pub use $0; md bar kw crate:: kw self:: + "#]], + ); +} + +#[test] +fn pub_suggest_use_tree_super_acc_to_depth_in_tree() { + // https://github.com/rust-lang/rust-analyzer/issues/12439 + // Check discussion in https://github.com/rust-lang/rust-analyzer/pull/12447 + check( + r#" +mod foo { + mod bar { + pub use super::$0; + } +} +"#, + expect![[r#" + md bar kw super:: "#]], ); + check( + r#" +mod foo { + mod bar { + pub use super::super::$0; + } +} +"#, + expect![[r#" + md foo + "#]], + ); } #[test] @@ -290,7 +318,6 @@ use {$0}; md bar kw crate:: kw self:: - kw super:: "#]], ); } diff --git a/crates/ide-completion/src/tests/visibility.rs b/crates/ide-completion/src/tests/visibility.rs index 151dd6a7e85d..c18d6e66dd60 100644 --- a/crates/ide-completion/src/tests/visibility.rs +++ b/crates/ide-completion/src/tests/visibility.rs @@ -25,7 +25,6 @@ pub($0) kw crate kw in kw self - kw super "#]], ); } @@ -39,7 +38,6 @@ pub(in $0) expect![[r#" kw crate kw self - kw super "#]], ); }