From 4cbde4ed8f9764e0ecf922279f26613fa3edca54 Mon Sep 17 00:00:00 2001 From: feniljain Date: Sun, 10 Jul 2022 14:08:49 +0530 Subject: [PATCH] fix(completion): `super::` completion at crate root and module depth aware --- crates/ide-completion/src/completions.rs | 24 ++++++- .../src/completions/attribute.rs | 6 +- .../src/completions/attribute/derive.rs | 6 +- .../src/completions/item_list.rs | 6 +- .../ide-completion/src/completions/pattern.rs | 6 +- crates/ide-completion/src/completions/use_.rs | 7 +- crates/ide-completion/src/completions/vis.rs | 6 +- crates/ide-completion/src/context.rs | 24 ++++++- crates/ide-completion/src/context/analysis.rs | 23 +++++-- crates/ide-completion/src/tests/attribute.rs | 26 ------- crates/ide-completion/src/tests/expression.rs | 12 ---- crates/ide-completion/src/tests/item.rs | 2 - crates/ide-completion/src/tests/item_list.rs | 6 -- crates/ide-completion/src/tests/pattern.rs | 2 - crates/ide-completion/src/tests/predicate.rs | 6 -- crates/ide-completion/src/tests/record.rs | 1 - crates/ide-completion/src/tests/type_pos.rs | 20 ------ crates/ide-completion/src/tests/use_tree.rs | 67 ++++++++++++++++++- crates/ide-completion/src/tests/visibility.rs | 2 - 19 files changed, 140 insertions(+), 112 deletions(-) diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs index 1bcbb3aaa6..b254e458eb 100644 --- a/crates/ide-completion/src/completions.rs +++ b/crates/ide-completion/src/completions.rs @@ -91,11 +91,31 @@ 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_keyword( + &mut self, + ctx: &CompletionContext, + super_chain_len: Option, + ) { + if let Some(len) = super_chain_len { + if len > 0 && len < ctx.depth_from_crate_root { + self.add_keyword(ctx, "super::"); + } + } } pub(crate) fn add_keyword_snippet_expr( diff --git a/crates/ide-completion/src/completions/attribute.rs b/crates/ide-completion/src/completions/attribute.rs index 2de33a7362..cbf40e9134 100644 --- a/crates/ide-completion/src/completions/attribute.rs +++ b/crates/ide-completion/src/completions/attribute.rs @@ -82,12 +82,10 @@ pub(crate) fn complete_attribute_path( match qualified { Qualified::With { resolution: Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))), - is_super_chain, + super_chain_len, .. } => { - if *is_super_chain { - acc.add_keyword(ctx, "super::"); - } + acc.add_super_keyword(ctx, *super_chain_len); for (name, def) in module.scope(ctx.db, Some(ctx.module)) { match def { diff --git a/crates/ide-completion/src/completions/attribute/derive.rs b/crates/ide-completion/src/completions/attribute/derive.rs index 48eb76029f..b3cc1826a6 100644 --- a/crates/ide-completion/src/completions/attribute/derive.rs +++ b/crates/ide-completion/src/completions/attribute/derive.rs @@ -21,12 +21,10 @@ pub(crate) fn complete_derive_path( match qualified { Qualified::With { resolution: Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))), - is_super_chain, + super_chain_len, .. } => { - if *is_super_chain { - acc.add_keyword(ctx, "super::"); - } + acc.add_super_keyword(ctx, *super_chain_len); for (name, def) in module.scope(ctx.db, Some(ctx.module)) { match def { diff --git a/crates/ide-completion/src/completions/item_list.rs b/crates/ide-completion/src/completions/item_list.rs index 4a32e0ebf5..43b4899390 100644 --- a/crates/ide-completion/src/completions/item_list.rs +++ b/crates/ide-completion/src/completions/item_list.rs @@ -36,7 +36,7 @@ pub(crate) fn complete_item_list( match qualified { Qualified::With { resolution: Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))), - is_super_chain, + super_chain_len, .. } => { for (name, def) in module.scope(ctx.db, Some(ctx.module)) { @@ -51,9 +51,7 @@ pub(crate) fn complete_item_list( } } - if *is_super_chain { - acc.add_keyword(ctx, "super::"); - } + acc.add_super_keyword(ctx, *super_chain_len); } Qualified::Absolute => acc.add_crate_roots(ctx, path_ctx), Qualified::No if ctx.qualifier_ctx.none() => { diff --git a/crates/ide-completion/src/completions/pattern.rs b/crates/ide-completion/src/completions/pattern.rs index 65b6eee188..8d7fbc6627 100644 --- a/crates/ide-completion/src/completions/pattern.rs +++ b/crates/ide-completion/src/completions/pattern.rs @@ -111,10 +111,8 @@ pub(crate) fn complete_pattern_path( path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx, ) { match qualified { - Qualified::With { resolution: Some(resolution), is_super_chain, .. } => { - if *is_super_chain { - acc.add_keyword(ctx, "super::"); - } + Qualified::With { resolution: Some(resolution), super_chain_len, .. } => { + acc.add_super_keyword(ctx, *super_chain_len); match resolution { hir::PathResolution::Def(hir::ModuleDef::Module(module)) => { diff --git a/crates/ide-completion/src/completions/use_.rs b/crates/ide-completion/src/completions/use_.rs index e5689f332d..d4827771ad 100644 --- a/crates/ide-completion/src/completions/use_.rs +++ b/crates/ide-completion/src/completions/use_.rs @@ -17,10 +17,9 @@ pub(crate) fn complete_use_path( name_ref: &Option, ) { match qualified { - Qualified::With { path, resolution: Some(resolution), is_super_chain } => { - if *is_super_chain { - acc.add_keyword(ctx, "super::"); - } + Qualified::With { path, resolution: Some(resolution), super_chain_len } => { + acc.add_super_keyword(ctx, *super_chain_len); + // 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 6621aafe4b..39028eca41 100644 --- a/crates/ide-completion/src/completions/vis.rs +++ b/crates/ide-completion/src/completions/vis.rs @@ -14,7 +14,7 @@ pub(crate) fn complete_vis_path( match qualified { Qualified::With { resolution: Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))), - is_super_chain, + super_chain_len, .. } => { // Try completing next child module of the path that is still a parent of the current module @@ -27,9 +27,7 @@ pub(crate) fn complete_vis_path( } } - if *is_super_chain { - acc.add_keyword(ctx, "super::"); - } + acc.add_super_keyword(ctx, *super_chain_len); } Qualified::Absolute | Qualified::Infer | Qualified::With { .. } => {} Qualified::No => { diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs index b371c97880..c93fd0d7bb 100644 --- a/crates/ide-completion/src/context.rs +++ b/crates/ide-completion/src/context.rs @@ -4,6 +4,8 @@ mod analysis; #[cfg(test)] mod tests; +use std::iter; + use base_db::SourceDatabaseExt; use hir::{ HasAttrs, Local, Name, PathResolution, ScopeDef, Semantics, SemanticsScope, Type, TypeInfo, @@ -174,8 +176,17 @@ pub(super) enum Qualified { With { path: ast::Path, resolution: Option, - /// Whether this path consists solely of `super` segments - is_super_chain: bool, + /// How many `super` segments are present in the path + /// + /// This would be None, if path is not solely made of + /// `super` segments, e.g. + /// + /// ```rust + /// use super::foo; + /// ``` + /// + /// Otherwise it should be Some(count of `super`) + super_chain_len: Option, }, /// <_>:: Infer, @@ -343,6 +354,12 @@ pub(crate) struct CompletionContext<'a> { pub(super) qualifier_ctx: QualifierCtx, 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> { @@ -521,6 +538,8 @@ impl<'a> CompletionContext<'a> { } }); + let depth_from_crate_root = iter::successors(module.parent(db), |m| m.parent(db)).count(); + let mut ctx = CompletionContext { sema, scope, @@ -535,6 +554,7 @@ impl<'a> CompletionContext<'a> { expected_type: None, qualifier_ctx: Default::default(), locals, + depth_from_crate_root, }; let ident_ctx = ctx.expand_and_analyze( original_file.syntax().clone(), diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs index e13950d56a..7fc77aae91 100644 --- a/crates/ide-completion/src/context/analysis.rs +++ b/crates/ide-completion/src/context/analysis.rs @@ -899,10 +899,25 @@ impl<'a> CompletionContext<'a> { Qualified::Infer } else { 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()); - Qualified::With { path, resolution: res, is_super_chain } + + // For understanding how and why super_chain_len is calculated the way it + // is check the documentation at it's definition + let mut segment_count = 0; + let super_count = iter::successors(Some(path.clone()), |p| p.qualifier()) + .take_while(|p| { + p.segment() + .and_then(|s| { + segment_count += 1; + s.super_token() + }) + .is_some() + }) + .count(); + + let super_chain_len = + if segment_count > super_count { None } else { Some(super_count) }; + + Qualified::With { path, resolution: res, super_chain_len } } }; } diff --git a/crates/ide-completion/src/tests/attribute.rs b/crates/ide-completion/src/tests/attribute.rs index 3b366c94bf..1578ba2c37 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 c05a7ad9fa..ce9d01d337 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 81303eb38f..409413c1dc 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 09ea78a3d5..5076c6e86c 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 63ccf9003b..1808868066 100644 --- a/crates/ide-completion/src/tests/pattern.rs +++ b/crates/ide-completion/src/tests/pattern.rs @@ -414,7 +414,6 @@ fn foo() { st Bar kw crate:: kw self:: - kw super:: "#]], ); check_empty( @@ -430,7 +429,6 @@ fn foo() { st Foo 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 f2b9c061dc..a8676e2f24 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 d9b3183208..ec32602fa3 100644 --- a/crates/ide-completion/src/tests/record.rs +++ b/crates/ide-completion/src/tests/record.rs @@ -171,7 +171,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 fcd4743f74..f0b7726c51 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:: "#]], ); } @@ -115,7 +112,6 @@ fn foo() -> B$0 { it () kw crate:: kw self:: - kw super:: "#]], ) } @@ -141,7 +137,6 @@ const FOO: $0 = Foo(2); it Foo kw crate:: kw self:: - kw super:: "#]], ); } @@ -168,7 +163,6 @@ fn f2() { it i32 kw crate:: kw self:: - kw super:: "#]], ); } @@ -197,7 +191,6 @@ fn f2() { it u64 kw crate:: kw self:: - kw super:: "#]], ); } @@ -223,7 +216,6 @@ fn f2(x: u64) -> $0 { it u64 kw crate:: kw self:: - kw super:: "#]], ); } @@ -250,7 +242,6 @@ fn f2(x: $0) { it i32 kw crate:: kw self:: - kw super:: "#]], ); } @@ -285,7 +276,6 @@ fn foo<'lt, T, const C: usize>() { it a::Foo> kw crate:: kw self:: - kw super:: "#]], ); } @@ -315,7 +305,6 @@ fn foo<'lt, T, const C: usize>() { it Foo kw crate:: kw self:: - kw super:: "#]], ); } @@ -342,7 +331,6 @@ fn foo<'lt, T, const C: usize>() { bt u32 kw crate:: kw self:: - kw super:: "#]], ); check( @@ -412,7 +400,6 @@ fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {} bt u32 kw crate:: kw self:: - kw super:: "#]], ); check( @@ -465,7 +452,6 @@ impl Tr<$0 bt u32 kw crate:: kw self:: - kw super:: "#]], ); } @@ -512,7 +498,6 @@ fn f(t: impl MyTrait