diff --git a/crates/ide_completion/src/completions/keyword.rs b/crates/ide_completion/src/completions/keyword.rs index 7970e75c72..0a3df79d46 100644 --- a/crates/ide_completion/src/completions/keyword.rs +++ b/crates/ide_completion/src/completions/keyword.rs @@ -349,49 +349,6 @@ fn quux() -> i32 { ); } - #[test] - fn test_keywords_in_trait_def() { - check( - r"trait My { $0 }", - expect![[r#" - kw unsafe - kw fn - kw const - kw type - "#]], - ); - } - - #[test] - fn test_keywords_in_impl_def() { - check( - r"impl My { $0 }", - expect![[r#" - kw pub(crate) - kw pub - kw unsafe - kw fn - kw const - kw type - "#]], - ); - } - - #[test] - fn test_keywords_in_impl_def_with_attr() { - check( - r"impl My { #[foo] $0 }", - expect![[r#" - kw pub(crate) - kw pub - kw unsafe - kw fn - kw const - kw type - "#]], - ); - } - #[test] fn test_keywords_in_loop() { check( diff --git a/crates/ide_completion/src/completions/snippet.rs b/crates/ide_completion/src/completions/snippet.rs index 4e64a00901..d142265e08 100644 --- a/crates/ide_completion/src/completions/snippet.rs +++ b/crates/ide_completion/src/completions/snippet.rs @@ -36,7 +36,7 @@ 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]) { + if !ctx.expects_item() || ctx.previous_token_is(T![unsafe]) || ctx.path_qual().is_some() { 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 2c623bf7ae..3910de2c47 100644 --- a/crates/ide_completion/src/completions/unqualified_path.rs +++ b/crates/ide_completion/src/completions/unqualified_path.rs @@ -500,18 +500,6 @@ fn f() {$0} check( r#" #[rustc_builtin_macro] -pub macro Clone {} - -struct S; -impl S { - $0 -} -"#, - expect![[r#""#]], - ); - check( - r#" -#[rustc_builtin_macro] pub macro bench {} fn f() {$0} @@ -772,42 +760,6 @@ impl My$0 ) } - #[test] - fn completes_in_assoc_item_list() { - check( - r#" -macro_rules! foo {} -mod bar {} - -struct MyStruct {} -impl MyStruct { - $0 -} -"#, - expect![[r#" - md bar - ma foo!(…) macro_rules! foo - "#]], - ) - } - - #[test] - fn completes_in_item_list() { - check( - r#" -struct MyStruct {} -macro_rules! foo {} -mod bar {} - -$0 -"#, - expect![[r#" - md bar - ma foo!(…) macro_rules! foo - "#]], - ) - } - #[test] fn completes_types_and_const_in_arg_list() { check( diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs index 907ffdc7ac..441c080b12 100644 --- a/crates/ide_completion/src/context.rs +++ b/crates/ide_completion/src/context.rs @@ -313,7 +313,10 @@ impl<'a> CompletionContext<'a> { pub(crate) fn is_path_disallowed(&self) -> bool { self.attribute_under_caret.is_some() || self.previous_token_is(T![unsafe]) - || self.has_visibility_prev_sibling() + || matches!( + self.prev_sibling, + Some(ImmediatePrevSibling::Attribute) | Some(ImmediatePrevSibling::Visibility) + ) || matches!( self.completion_location, Some(ImmediateLocation::Attribute(_)) diff --git a/crates/ide_completion/src/patterns.rs b/crates/ide_completion/src/patterns.rs index 345977d48b..02cfe91e18 100644 --- a/crates/ide_completion/src/patterns.rs +++ b/crates/ide_completion/src/patterns.rs @@ -20,6 +20,7 @@ pub(crate) enum ImmediatePrevSibling { TraitDefName, ImplDefType, Visibility, + Attribute, } /// Direct parent "thing" of what we are currently completing. @@ -113,6 +114,7 @@ pub(crate) fn determine_prev_sibling(name_like: &ast::NameLike) -> Option ImmediatePrevSibling::Attribute, _ => return None, } }; @@ -438,4 +440,9 @@ mod tests { fn test_vis_prev_sibling() { check_prev_sibling(r"pub w$0", ImmediatePrevSibling::Visibility); } + + #[test] + fn test_attr_prev_sibling() { + check_prev_sibling(r"#[attr] w$0", ImmediatePrevSibling::Attribute); + } } diff --git a/crates/ide_completion/src/tests.rs b/crates/ide_completion/src/tests.rs index 4485a908e5..2205603fa6 100644 --- a/crates/ide_completion/src/tests.rs +++ b/crates/ide_completion/src/tests.rs @@ -44,7 +44,17 @@ fn completion_list_with_config(config: CompletionConfig, code: &str) -> String { } fn check(ra_fixture: &str, expect: Expect) { - let actual = completion_list(ra_fixture); + let base = r#"#[rustc_builtin_macro] +pub macro Clone {} +enum Enum { Variant } +struct Struct {} +#[macro_export] +macro_rules! foo {} +mod bar {} +const CONST: () = (); +trait Trait {} +"#; + let actual = completion_list(&format!("{}{}", base, ra_fixture)); expect.assert_eq(&actual) } diff --git a/crates/ide_completion/src/tests/item_list.rs b/crates/ide_completion/src/tests/item_list.rs index c8aa44d88a..33b23b8b4c 100644 --- a/crates/ide_completion/src/tests/item_list.rs +++ b/crates/ide_completion/src/tests/item_list.rs @@ -9,6 +9,64 @@ fn in_mod_item_list() { $0 } "#, + expect![[r##" + kw pub(crate) + kw pub + kw unsafe + kw fn + kw const + kw type + kw impl + kw extern + kw use + kw trait + kw static + kw mod + kw enum + kw struct + kw union + sn tmod (Test module) + sn tfn (Test function) + sn macro_rules + ma foo!(…) #[macro_export] macro_rules! foo + "##]], + ) +} + +#[test] +fn in_source_file_item_list() { + check( + r#"$0"#, + expect![[r##" + kw pub(crate) + kw pub + kw unsafe + kw fn + kw const + kw type + kw impl + kw extern + kw use + kw trait + kw static + kw mod + kw enum + kw struct + kw union + 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 in_item_list_after_attr() { + check( + r#"#[attr] $0"#, expect![[r#" kw pub(crate) kw pub @@ -32,56 +90,10 @@ fn in_mod_item_list() { ) } -#[test] -fn in_source_file_item_list() { - check( - r#" -enum Enum { Variant } -struct MyStruct {} -#[macro_export] -macro_rules! foo {} -mod bar {} -const CONST: () = (); - -$0"#, - expect![[r##" - kw pub(crate) - kw pub - kw unsafe - kw fn - kw const - kw type - kw impl - kw extern - kw use - kw trait - kw static - kw mod - kw enum - kw struct - kw union - 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 in_qualified_path() { check( - r#" -enum Enum { Variant } -struct MyStruct {} -#[macro_export] -macro_rules! foo {} -mod bar {} -const CONST: () = (); - -crate::$0"#, + r#"crate::$0"#, expect![[r##" kw pub(crate) kw pub @@ -98,11 +110,8 @@ crate::$0"#, kw enum kw struct kw union - 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 "##]], ) } @@ -110,15 +119,7 @@ crate::$0"#, #[test] fn after_unsafe_token() { check( - r#" -enum Enum { Variant } -struct MyStruct {} -#[macro_export] -macro_rules! foo {} -mod bar {} -const CONST: () = (); - -unsafe $0"#, + r#"unsafe $0"#, expect![[r#" kw fn kw trait @@ -130,15 +131,7 @@ unsafe $0"#, #[test] fn after_visibility() { check( - r#" -enum Enum { Variant } -struct MyStruct {} -#[macro_export] -macro_rules! foo {} -mod bar {} -const CONST: () = (); - -pub $0"#, + r#"pub $0"#, expect![[r#" kw unsafe kw fn @@ -154,3 +147,69 @@ pub $0"#, "#]], ); } + +#[test] +fn after_visibility_unsafe() { + // FIXME this shouldn't show `impl` + check( + r#"pub unsafe $0"#, + expect![[r#" + kw fn + kw trait + kw impl + "#]], + ); +} + +#[test] +fn in_impl_assoc_item_list() { + check( + r#"impl Struct { + $0 +}"#, + expect![[r##" + kw pub(crate) + kw pub + kw unsafe + kw fn + kw const + kw type + md bar + ma foo!(…) #[macro_export] macro_rules! foo + ma foo!(…) #[macro_export] macro_rules! foo + "##]], + ) +} + +#[test] +fn in_impl_assoc_item_list_after_attr() { + check( + r#"impl Struct { + #[attr] $0 +}"#, + expect![[r#" + kw pub(crate) + kw pub + kw unsafe + kw fn + kw const + kw type + "#]], + ) +} + +#[test] +fn in_trait_assoc_item_list() { + check( + r"trait Foo { $0 }", + expect![[r##" + kw unsafe + kw fn + kw const + kw type + md bar + ma foo!(…) #[macro_export] macro_rules! foo + ma foo!(…) #[macro_export] macro_rules! foo + "##]], + ); +}